简介:
学习了一下spring mvc,写下笔记,方便之后阅读。
因为我比较喜欢在代码中对程序进行注视,所以乍一看代码感觉会多。
注视当中有容易出错的地方的提醒,也有函数解释,所以会显得很罗嗦。
在这里没有连接数据库的部分,有兴趣的朋友可以看之后的MyBatis文章。
涉及到的内容:
spring mvc框架.
spring.xml方式的实现
annotation(注解)方式的实现
jQuery(ajax的一总框架)的验证。
响应流程。
需要的lib有:
ps:这里的jquery.js虽然显示红叉,不过可以无视它,是编译器问题。
spring版本为spring-framework-3.1.0.RELEASE.
源代码:
1. 在web.xml中添加如下代码:
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-configuration.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<!-- 这里不能写"/*",这样会拦截所有消息,连Index.jsp都被拦截而进步了了 -->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
2. 在WEB-INF/spring-configuration.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:sws="http://www.springframework.org/schema/web-services"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Resolver将把输出结果与输出界面相融合,为表现层提供呈现资源 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 这里我们使用JSP页面作为输出 -->
<!-- 其余可选的viewClass还有:
org.springframework.web.servlet.view.freemarker.FreeMarkerView
(用于基于FreeMarker模板的表现层实现)
org.springframework.web.servlet.view.velocity.VelocityView
(用于基于velocity模板的表现层实现)
等。 -->
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<!-- 指定了表现层资源的前缀 -->
<!-- 这里不能写成 <value> /WEB-INF/jsp/ </value> -->
<property name="prefix">
<!-- 不可写成
1. /jsp/
2. WEB-INF/jsp/
3. <value>
jsp/
</value> -->
<value>/WEB-INF/jsp/</value>
</property>
<!-- 指定了表现层资源的后缀 -->
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!--Request Mapping -->
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- 注意!在页面中要写成 <form method="POST" action="./login.do">
别忘了/login.do前面的 点 -->
<prop key="/login.do">LoginController</prop>
</props>
</property>
</bean>
<!-- Action Definition -->
<bean id="LoginController" class="com.controller.LoginController">
<property name="success_view">
<value>main</value>
</property>
</bean>
<!-- 注解方式的开始,如果只想用注解方式实现的话,配置文件中,除了<bean id="viewResolver">以外,上面的都可以删掉 -->
<!-- 扫描com.controller包下的所有文件,把标记了@Controller,@service等注解的类转换为bean,本程序是将有@controller的bean当成controller层 -->
<context:component-scan base-package="com.controller" />
<!-- 这里不能省略下面的bean。如果省略,将报:No mapping found for HTTP request with URI 错误 -->
<!-- DefaultAnnotationHandlerMapping 作用是将基于注解的映射 射到具体的Controller -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<!-- 不要添加<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> -->
</beans>
3. 在index.jsp中:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- 别忘了这句话,把jquery.js导入进来才可以,相当于导入jquery.jar包 -->
<script src="/SpringMVC/js/jquery.js"></script>
<script type="text/javascript">
function login() {
//清空错误信息
init();
//获取用户名和密码
//jquery可以通过 $("控件ID") 获取该对象
var id = $.trim($("#id").val());
var pwd = $.trim($("#pwd").val());
//进行简单校验,是否为空等
var tmp3 = true;
var tmp1 = validate(id);
var tmp2 = validate(pwd);
if(tmp1 != true){
setIdErrorMsg("red",tmp1);
tmp3 = false;
}
if(tmp2 != true){
setPwdErrorMsg("red",tmp2);
tmp3 = false;
}
if(!tmp3){
//既然有错,那就不必要继续下去了
return;
}
//异步方式向服务器发送请求
$.ajax({
type: "POST", //http请求方式
url: "<%=request.getContextPath()%>/check.do?method=loginCheck",
data: "userId="+id+"&userPwd="+pwd, //发送给服务器段的数据,这里必须要填的,否则“/check.do?method=loginCheck”得不到数据
dataType: "xml", //告诉JQuery返回的数据格式
beforeSend:function(){
setResultErrorMsg("black","处理中....请稍等");
},
success: callback, //定义交互完成,并且服务器正确返回数据时调用的回调函数
error :function(e){
setResultErrorMsg("red","网络异常");
}
});
}
function validate(tmp){
if(tmp == ""){
return "不能为空";
}
//else if( /^\d.*$/.test(tmp)){
// return "不能以数字开头";
//}
else if(tmp.length<6 || tmp.length>18 ){
return "合法长度为6-18个字符";
}
else if(! /^\w+$/.test(tmp) ){
return "只能包含_,英文字母,数字";
}
//else if(! /^([a-z]|[A-Z])[0-9a-zA-Z_]+$/.test(tmp) ){
// return "只能以英文字母开头";
//}
else if(!(/[0-9a-zA-Z]+$/.test(tmp))){
return "只能以英文字母或数字结尾";
}
else{
return true;
}
}
function init(){
$('#idResult').html("");
$('#pwdResult').html("");
$('#result').html("");
}
function setIdErrorMsg(color,str){
$('#idResult').css("color",color);
$('#idResult').html(str);
}
function setPwdErrorMsg(color,str){
$('#pwdResult').css("color",color);
$('#pwdResult').html(str);
}
function setResultErrorMsg(color,str){
$('#result').css("color",color);
$('#result').html(str);
}
function callback(data) {
//成功接收到了消息的话,等待消息提示就可以去除了。
$('#result').html("");
//接收服务器端返回的数据
//首先需要将dom的对象转换成JQuery的对象
var jqueryObj = $(data);
parseXml(jqueryObj);
}
//解析XML
// 更详细可以看:http://shawphy.com/2008/01/load-xml-by-ajax-with-jquery-and-parse-it.html
function parseXml(obj){
if(obj.find("msg").text() == "OK"){
//如果验证成功的话,就进行跳转
window.location.href="<%=request.getContextPath() %>/login.do";
}
else{
obj.find("errorMsg").each(function(i){
var tmpErrorMsg = $(this).children("msg").text();
//alert(tmpErrorMsg);
//显示错误信息
switch($(this).attr("type")){
case "id":
$('#idResult').css("color","red");
$('#idResult').html(tmpErrorMsg);
break;
case "pwd":
$('#pwdResult').css("color","red");
$('#pwdResult').html(tmpErrorMsg);
break;
}
});
}
}
</script>
<body>
<!-- 这里不能写成 action="/login.do",这里的"."相当于request.getContextPath(),也就是工程名(Struts2) -->
<form method="POST" action="./login.do">
<p align="center">登录</p>
<br>
<font color=red >基于spring-configuration.xml配置文件执行</font>
<br>
<br>
用户名: <input type="text" id="id" name="id">
<!--这个span用于存放服务器段返回的信息,开始为空-->
<!--div和span的直观差异,div中的内容独占行,span中的内容和前后其他内容在同一行中-->
<span id="idResult"></span><br>
密 码 : <input type="password" id="pwd" name="pwd" >
<span id="pwdResult"></span><br>
<p>
<input type="button" value="提交" οnclick="login()">
<input type="reset" value="重置" >
<div id="result"></div>
</p>
</form>
<div id="result" class="resultType"></div>
</body>
</html>
jQuery解析xml部分想看更详细的话请看:点击打开链接
4. 在com.controller.LoginController中:
package com.controller;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import com.entity.User;
public class LoginController implements Controller {
private String success_view; // 成功的页面地址
public String getSuccess_view() {
return success_view;
}
//spring-configuration.xml自动调用该方法把xml中的值“main”放进来
public void setSuccess_view(String string) {
success_view = string;
}
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
// 获得当前时间
String now = (new java.util.Date()).toString();
Map userModel = new HashMap();
// 模拟数据,就当从数据库中取出的值。
User user = new User("mizhiwu", "123");
User user1 = new User("mizhiwu1", "123");
User user2 = new User("mizhiwu2", "123");
ArrayList<User> userList = new ArrayList<User>();
userList.add(user);
userList.add(user1);
userList.add(user2);
userModel.put("userList", userList);
userModel.put("now", now);
return new ModelAndView(this.getSuccess_view(), "model", userModel);
}
}
5. 在com.controller.Validation中(基于注解的实现):
package com.controller;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.entity.User;
@Controller
@RequestMapping("/check.do")
public class Validation {
@RequestMapping(params = "method=loginCheck")
public void login(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 注意:这里不能用request.getParameter("id").这不是servlet了
String tempID = request.getParameter("userId");
String tempPwd = request.getParameter("userPwd");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String idError = "用户名请输入 mizhiwu";
String pwdError = "密码请输入mizhiwu";
String resultError = "用户已存在";
if (tempID.equalsIgnoreCase("mizhiwu") && tempPwd.equals("mizhiwu")) {
out.print("<result>");
out.print("<msg>");
out.print("OK");
out.print("</msg>");
out.print("</result>");
//提交
out.flush();
out.close();
} else {
// 将处理结果返回给客户端
out.print("<result>");
out.print("<errorMsg type='id'>");
out.print("<msg>");
out.print(idError);
out.print("</msg>");
out.print("</errorMsg>");
out.print("<errorMsg type='pwd'>");
out.print("<msg>");
out.print(pwdError);
out.print("</msg>");
out.print("</errorMsg>");
out.print("</result>");
//提交
out.flush();
out.close();
}
}
}
其实ajax返回的就是一个xml信息。然后在页面中对该xml进行解析后输出。
验证效果图:
如果不想要 jQuery 验证部分的话,将index.jsp中的第150行改成 <input type="submit" value="提交"> 就可以了。
有兴趣的人可以看jQuery的验证插件,那样的话就不用这么多代码了。
5. 在WebContent/jsp/main.jsp中:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ page session="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
<!-- 别忘了这句话,把jquery.js导入进来才可以,相当于导入jquery.jar包 -->
<script src="/SpringMVC/js/jquery.js"></script>
<script type="text/javascript">
function deleteUser(id) {
$.ajax( {
type : "POST",
url : "<%=request.getContextPath()%>/user.do?method=del&id=" + id,
dataType: "json",
success : function(data) {
if(data.del == "true"){
//在jsp页面中移除该用户
$("#" + id).remove();
//动态改变结果信息的字体颜色
$('#delResult').css("color","green");
$('#delResult').html("删除成功!");
}
else{
$('#delResult').css("color","red");
$('#delResult').html("删除失败!");
}
},
error :function(e){
$('#delResult').css("color","red");
$('#delResult').html("网络异常!"+e);
}
});
}
</script>
</head>
<body>
<h1>Hello~<c:out value="${id}"/></h1>
<p>当前时间: <c:out value="${model.now}" /></p>
<font color=red >基于注解方式的执行</font>
<h3>所有用户信息</h3>
<table>
<tr>
<td>用户名</td>
<td>密码</td>
</tr>
<!-- 这个是通过return new ModelAndView(this.getSuccess_view(), "model", userModel);实现的 -->
<c:forEach items="${model.userList}" var="list">
<tr id="<c:out value="${list.id}"/>">
<td><c:out value="${list.id}"/></td>
<td><c:out value="${list.pwd}"/></td>
<td><input type="button" value="删除该用户" οnclick="deleteUser('<c:out value="${list.id}"/>')"></td>
</tr>
</c:forEach>
<!-- 这个是通过modelMap.put("userList", userList);实现的 。与上面实现是不同的
不过同意的好,这里用两个是因为为了学习。-->
<c:forEach items="${userList}" var="list">
<tr id="<c:out value="${list.id}"/>">
<td><c:out value="${list.id}"/></td>
<td><c:out value="${list.pwd}"/></td>
<td><input type="button" value="删除该用户" οnclick="deleteUser('<c:out value="${list.id}"/>')"></td>
</tr>
</c:forEach>
</table>
<span id="delResult"></span>
<!-- 这里的request.getContextPath()就是项目的名字,也就是SpringMVC。不可以省略 -->
<form method="POST" action="./user.do?method=add">
<input type="submit" value="添加新用户">
</form>
</body>
</html>
6. 在com.controller.UserController中(基于注解的实现):
package com.controller;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.entity.User;
@Controller
@RequestMapping("/user.do")
public class UserController {
@RequestMapping
public String load(ModelMap modelMap){
//重新从数据库取值后返回到main.jsp,显示所有用户
//模拟数据,就当从数据库中取出的值。
String now = (new java.util.Date()).toString();
User user = new User("mizhiwu","123");
User user1 = new User("mizhiwu1","123");
User user2 = new User("mizhiwu2","123");
ArrayList<User> userList = new ArrayList<User>();
userList.add(user);
userList.add(user1);
userList.add(user2);
modelMap.put("userList", userList);
modelMap.put("now", now);
return "main";
}
@RequestMapping(params = "method=add")
public String addUser() throws Exception{
//只要跳转到addUser.jsp页面就可以了
return "addUser";
}
@RequestMapping(params = "method=save")
public void saveUser(HttpServletRequest request, HttpServletResponse response) throws Exception{
//在数据库中错insert操作,如果没问题则返回下面的信息。
response.getWriter().print("{\"add\":\"true\"}");
}
@RequestMapping(params = "method=del")
public void deleteUser(@RequestParam("id") String id, HttpServletResponse response) throws Exception{
//在数据库中错delete操作,如果没问题则返回下面的信息。
response.getWriter().print("{\"del\":\"true\"}");
}
}
7. 在WebContent/jsp/addUser.jsp中:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
<script src="/SpringMVC/js/jquery.js"></script>
<script type="text/javascript">
function returnPage(){
window.location.href="<%=request.getContextPath() %>/user.do";
//window.location.href="<%=request.getContextPath() %>/user.do?method=del";
}
function addOneUser(){
$.ajax( {
type : "POST",
url : "<%=request.getContextPath()%>/user.do?method=save",
dataType: "json",
success : function(data) {
if(data.add == "true"){
//动态改变结果信息的字体颜色
$('#addResult').css("color","green");
$('#addResult').html("添加成功!");
}
else{
$('#addResult').css("color","red");
$('#addResult').html("添加失败!");
}
},
error :function(e){
$('#addResult').css("color","red");
$('#addResult').html("网络异常!"+e);
}
});
}
</script>
</head>
<body>
<br>
<font color=red >基于注解方式的执行</font>
<br>
<br>
<form method="post" action="user.do?method=save">
<table>
<tr>
<td>用户名:</td>
<td><input name="id" type="text" /></td>
</tr>
<tr>
<td>密码:</td>
<td><input name="pwd" type="text" /></td>
</tr>
<tr>
<td>
<input type="button" value="确定" οnclick="addOneUser()">
</td>
<td>
<input type="reset" value="重置" >
</td>
<td>
<input type="button" value="返回" οnclick="returnPage()">
</td>
</tr>
<tr>
<td>
<span id="addResult"></span>
</td>
</tr>
</table>
</form>
</body>
</html>
OK,现在你可以尝试运行代码了。
响应流程:
- index.jsp中点击“提交”按钮javascript:login()函数开始校验
- 基础校验成功(用户名不能为空等)后,发送请求"check.do?method=loginCheck"
- “check.do”被web.xml的第13行截获到.
- web.xml根据第6行找到spring-configuration.xml。
- spring-configuration.xml中的第61行开始扫描com.controller包下的所有文件。
- 符合"check.do?method=loginCheck"条件的为com.controller.Validation.class的login()函数。
- 如果校验没有问题,返回信息“OK”。
- 被index.jsp的第109行截获并发送请求"login.do".
- 被web.xml的第13行截获到.
- web.xml根据第6行找到spring-configuration.xml。
- spring-configuration.xml中的第48行满足"login.do"要求,并通过"LoginController"找到53行的com.controller.LoginController.clss文件。
- LoginController.class执行handleRequest方法返回值是"main"。
- 通过spring-configuration.xml的第12行给"main"添加前缀和后缀,最终跳转的实际地址为:/WEB-INF/jsp/main.jsp页面。
例子程序请到: 点击打开链接 下载。
下载了源代码的朋友请把index.jsp中的
<form method="POST" action="./login.do" onSubmit="return login()">
改为 <form method="POST" action="./login.do"> 。呵呵,程序中忘改完就上传了,sorry。
参考文献:
http://www.4ucode.com/Study/Topic/477284
http://hanmei.blog.51cto.com/521325/203139
http://blog.youkuaiyun.com/penngo/article/details/6038991
收工~~~~~