一、框架基本使用
1.引入jar包
2.新建配置文件spring-mvc.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
">
</beans>
3.配置前端控制器web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
4.创建控制器FirstAction.java,实现Controller接口
// action实现Controller接口,并实现handleRequest方法(类似service方法),与JSP内置对象偶合
public class FirstAction implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
// TODO Auto-generated method stub
System.out.println("传入的数据为");
String userName=request.getParameter("userName");
String pwd=request.getParameter("pwd");
System.out.println("userName:"+userName);
System.out.println("这里可以调用业务层处理业务。");
//封装数据,可以直接使用request对象,也可以使用封装等方式,真正使用时可以选择一种
request.setAttribute("rUserName", userName);
Map<String, String > map=new HashMap<String, String>();
map.put("mUserName",userName);
//返回视图层,如果使用map封装数据,需要作为(第二个)参数传递,也是request作用域。
return new ModelAndView("/jsp/first.jsp",map);
//返回视图层,不传递map。
//return new ModelAndView("/jsp/first.jsp");
//也可以使用如下方式传递,不使用Map,数据一样是request作用域
//return new ModelAndView("/jsp/first.jsp","mUserName",userName);
}
}
5.修改配置文件spring-mvc.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
">
<!--
1。配置action,实现controler接口
2。配置映射处理器,用来处理请求与action的映射,可以不用写id,
3。配置视图解析器:完成ModelAndView的解析
缺点:
1。与JSP偶合
2。只支持属性的注入,不支持封闭后对象注入
-->
<!-- 声明bean的name,因为使用了BeanNameUrlHandlerMapping,所以不是定义id,用户调用的URL将通过bean的name匹配 -->
<bean name="/first.action" class="cn.itcast.action.FirstAction" />
<!-- 声明 BeanNameUrlHandlerMapping,使用名称映射-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!-- 支持servlet与jsp视图解析,可进行进一步处理,此步可省略, -->
<!-- InternalResourceViewResolver支持servlet与jsp视图解析,没有配置时,默认使用它,此步可省略, -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 可以加前缀或后缀 -->
<!--
<property name="prefix" value="/jsp/"/>
<property name="suffix" value=".jsp"/>
-->
</bean>
6.新建jsp/first.jsp,展示访问结果
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
这是/jsp/first.jsp页面.<br/>
<!-- 获取并展现控制层传递过来的值 -->
直接通过request传递的值:${requestScope.rUserName}<br/>通过Map传递的值:${requestScope.mUserName}
</body>
</html>
7.测试index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<a href="first.action?userName=zcf&pwd=admin">firstMVC</a>
</body>
</html>
8.流程分析
客户端发送请求后,由web.xml中的DispatchServlet过滤,再由spring-mvc.xml中的HandlerMapping识别到对应的action控制器,然后访问控制器,控制器处理后返回一个ModelAndView,通过视图解析器ViewResolver解析,跳转到对应的jsp页面。
二、URL处理器
1.BeanNameUrlHandlerMapping:它将收到的HTTP请求映射到bean的名称(这些bean需要在web应用上下文中定义)
<!-- 声明bean的name,因为使用了BeanNameUrlHandlerMapping,所以不是定义id,用户调用的URL将通过bean的name匹配 -->
<bean name="/first.action" class="cn.itcast.action.FirstAction" />
<!--
声明 BeanNameUrlHandlerMapping,使用名称映射
-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
2.SimpleUrlHandlerMapping:它将收到的HTTP请求映射到bean的ID(这些bean需要在web应用上下文中定义)
<!-- 配置URL与ACTION对象ID进行映射 ,<prop key="second.action">second</prop>,其中key匹配url信息,value为action的ID
-->
<bean id="first" class="cn.itcast.action.FirstAction" />
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="first.action">first</prop>
</props>
</property>
</bean>
三、视图解析器(默认使用 InternalResourceViewResolver)
1.UrlBasedViewResolver
<!-- 支持servlet与jsp视图解析1,可进行进一步处理,此步可省略, -->
<!-- viewClass不同的配置,可以解析不同的资源-->
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!--
<property name="prefix" value="/jsp/"/>
<property name="suffix" value=".jsp"/>
-->
</bean>
2.InternalResourceViewResolver:作为UrlBasedViewResolver的子类, 它支持页面jstl处理.
<!-- 支持servlet与jsp视图解析,可进行进一步处理,此步可省略, -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 可以加前缀或后缀 -->
<property name="prefix" value="/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
四、转发forword与重定向redirect(默认 forword)
forward使用转发方式:
return new ModelAndView("/jsp/first.jsp",map);
return new ModelAndView("forward:/jsp/first.jsp",map);
//控制器采用注解,方法在返回字符串时,可以使用:
return "forward:/jsp/first.jsp";
redirect使用重定向方式 :
return new ModelAndView("redirect:/jsp/first.jsp",map);
//控制器采用注解,方法在返回字符串时,可以使用
return "redirect:/jsp/first.jsp";
五、控制器
1.实现controller接口
在spring mvc中控制对象要实现此接口,并且必须实现handRequest方法。此控制器在接收到DispatcherServlet分配置 的请求时,执行handRequest方法,并 返回ModelAndView实例。
public class FirstAction implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
...
}
2. 继承AbstractCommandController类:可以将请求参数值自动设置到command对象中,便于后继的使用。
public class StudentAction extends AbstractCommandController {
public StudentAction(){
//配置student对象可以注入,student对象中定义好了stuName和stuPwd属性
setCommandClass(Student.class);
}
@Override
protected ModelAndView handle(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, BindException arg3)
throws Exception {
System.out.println("---接收数据---");
//方式1接收数据,只能每个属性都分开接收
String stuName=arg0.getParameter("stuName");
String stuPwd=arg0.getParameter("stuPwd");
System.out.println("方式1:"+stuName+","+stuPwd);
//方式2接收数据,实现对象属性注入,传递的数据名必须与被注入对象的属性名相同才能注入
Student student = (Student)arg2;
System.out.println("方式2:"+student);
System.out.println("---调用业务层,进行业务处理,略---");
//封装视图数据,有多种方式 ,这里列表方式 一和方式 二,可以任选一种:
//方式一,直接采用request对象封装
arg0.setAttribute("rStudent", student);
//封装视图数据,方式二,直接采用Map封装,默认作用域是request,需要在return的时候作为参数传递。
Map<String ,Student > map=new HashMap<String, Student>();
map.put("mStudent", student);
//默认为forward方式
return new ModelAndView("/jsp/main.jsp",map);
}
}
jsp/main.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>My JSP 'main.jsp' starting page</title>
</head>
<body>
这是/jsp/main.jsp页面.<br/>
<!-- 获取并展现控制层传递过来的值 -->
直接通过request传递的值:${requestScope.rStudent}<br/>通过Map传递的值:${requestScope.mStudent}
</body>
</html>
测试
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<a href="student.action?stuName=zcf&stuPwd=admin">test student</a>
</body>
</html>
3.继承MultiActionController类
public class StudentMultiAction extends MultiActionController {
//定义方法时,参数规则:(HttpServletRequest request, HttpServletResponse response, [,HttpSession session] [,MyObject]);
public ModelAndView add(HttpServletRequest request,HttpServletResponse response,Student student){
System.out.println("add.student:"+student);
student.setStuName("rename");
return new ModelAndView("jsp/main","student",student);
}
//定义方法时,参数规则:(HttpServletRequest request, HttpServletResponse response, [,HttpSession session] [,MyObject]);
public ModelAndView update(HttpServletRequest request,HttpServletResponse response,Student student){
System.out.println("update.student:"+student);
student.setStuName("rename");
return new ModelAndView("jsp/main","student",student);
}
//定义方法时,参数规则:(HttpServletRequest request, HttpServletResponse response, [,HttpSession session] [,MyObject]);
public ModelAndView list(HttpServletRequest request,HttpServletResponse response,Student student){
System.out.println("list.student:"+student);
student.setStuName("updateName");
return new ModelAndView("jsp/main");
}
}
修改spring-mvc.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
">
<!-- 配置控制器,并指定通过methodNameResolver方法名调用相关方法处理相关逻辑-->
<bean id="studentMultiAction" class="cn.itcast.action.StudentMultiAction">
<property name="methodNameResolver" ref="parameterMethodNameResolver"></property>
</bean>
<!-- 定义通过方法名调用控制器相关方法的规则 -->
<bean id="parameterMethodNameResolver"
class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<!-- 在url中使用do=方法名方式识别相关方法,例如:studentMulti.action?do=add,将调用add方法;这里的do不是固定的,可以改为其它 -->
<property name="paramName" value="do" />
<!-- 如果没有指定方法名时,默认 调用控制器的list方法 -->
<property name="defaultMethodName" value="list" />
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/studentMulti.action">studentMultiAction</prop>
</props>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
测试页面index.jsp
<body>
<form action="studentMulti.action?do=add" method="post">
<input type="text" name="stuName"><br> <input
type="password" name="stuPwd"><br> <input type="submit"
value="student_add">
</form>
<a href="studentMulti.action?do=update&stuPwd=testpwd&stuName=testName">调用修改方法</a>
<a href="studentMulti.action?&stuPwd=testpwd&stuName=testName">调用默认方法</a>
</body>
展示页面jsp/main.jsp
<body>
this is WEB-INF/JSP main jsp<br>
studentName:${requestScope.student.stuName}<br>
</body>
六、基于注解的mvc实现(重点)
1.基于DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter的注解
1)修改spring-mvc.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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
">
<!--
DefaultAnnotationHandlerMapping:支持通过url找到相关的action
AnnotationMethodHandlerAdapter:支持通过url匹配action定义方法
base-package:定 义扫描的范围,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean
-->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean>
<context:component-scan base-package="*"></context:component-scan>
</beans>
2)修改控制类,加入@Controller,@RequestMapping注解信息
@Controller:表示当前类是控制器
@RequestMapping("/controllerName"):表示url中通过controllerName可以访问该控制器
@Controller //用来声明控制器
@RequestMapping("/student") //声明可以访问到的url地址
public class StudentAction {
public StudentAction(){
System.out.println("---StudentAction构造方法被调用---");
}
//访问可用student/save.action,save后边的action是根据web.xml配置来的
//如果要添加其它的数据到最后跳转过去的页面,可以在方法中添加ModelMap的参数,例如 : public String save(Student student,ModelMap map){
//...,通过map再存放其它的数据
@RequestMapping(value="/save")
public ModelAndView save(Student student){
System.out.println("save方法注入的student对象:"+student);
System.out.println("---调用业务逻辑进行业务处理---");
//修改学生名字,跳转到下一页面时看能否显示修改后的名字
student.setStuName("rename");
//直接使用字符串,返回视图,进行结果展现等
return new ModelAndView("forward:/jsp/main.jsp");
}
//同一个action中可以定义多个方法,方法的返回类型也可以用String
@RequestMapping(value="/update")
public String update(Student student,ModelMap paramMap){
System.out.println("update方法已注入student对象:"+student);
System.out.println("---调用业务逻辑进行业务处理---");
paramMap.put("other","testOtherValue");
//直接使用字符串,返回视图,进行结果展现等
return "forward:/jsp/main.jsp";
}
}
3)测试页面,student为控制类中注解@RequestMapping("/student")声明过的controllerName
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<a href="student/save.action?stuName=zcf&stuPwd=admin">调用save方法</a>
4)展示页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>My JSP 'main.jsp' starting page</title>
</head>
<body>
这是/jsp/main.jsp页面.<br/>
<!-- 获取并展现控制层传递过来的值 -->
默认通过request传递的值:${requestScope.student}<br/>
</body>
</html>
2.基于annotation-driven的注解
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
">
<!--
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean>
<context:component-scan base-package="*"></context:component-scan>
-->
<!-- mvc:annotation-driven,取代了上面的DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter
两个Bean的配置 -->
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="*"/>
</beans>
七、springmvc文件上传
1.multipartResolver使用,配置spring-mvc.xml
<!--文件上传使用, 配置multipartResolver,id名为约定好的 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 配置文件(每次上传的所有文件总大小)大小,单位为b, 1024000表示1000kb -->
<property name="maxUploadSize" value="1024000" />
</bean>
2.中文乱码处理,配置web.xml
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
若配置完还是乱码,请尝试修改tomcat安装目录下的apache-tomcat安装目录\conf\server.xml文件,修改Connector元素内容,添加URIEncoding="UTF-8" ,修改后内容 如下:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8"/>
3.properties文件信息注入,配置spring-mvc.xml
<!--PropertiesFactoryBean对properties文件可用 ,可以用来注入properties配置文件的信息 -->
<bean id="uploadProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:xxxxx.properties"></property>
</bean>
八.拦截器
1.拦截器类
public class LoginInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("---访问请求资源后不管理有没有异常都一定执行此方法---");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
// TODO Auto-generated method stub
System.out.println("---访问请求资源后,如果没有异常,将执行此方法---");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("---访问请求资源前执行,如果此方法返回false,将不能访问请求资源---");
return true;
}
}
2.spring-mvc.xml配置
<!-- 配置spring mvc拦截器 -->
<mvc:interceptors>
<!-- 默认拦截DispatcherServlet指定的后缀(这里是.action) -->
<bean class="cn.itcast.interceptor.LoginInterceptor"/>
</mvc:interceptors>
九、json交互(使用注解 @ResponseBody)
@Controller
@RequestMapping(value="/student")
public class StudentAction {
public StudentAction(){
System.out.println("---StudentAction构造方法被调用---");
}
@RequestMapping("/doAjax")
@ResponseBody //如果返回json格式,需要这个注解
public Object doAjax(Student student){
System.out.println("---doAjax.student:"+student);
student.setStuName("1001name");
return student;
}
}
访问页面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/jquery-1.3.js"></script>
<script type="text/javascript">
$(
function(){
$("#bt1").click(
function(){
$.post(
"student/doAjax.action",
{stuId:1001,stuName:"name1001",stuPwd:"pwd1001",stuAge:20},
function(json){alert(json.stuName+"||"+json.stuPwd);},
"json"
);
}
);
}
);
</script>
</head>
<body>
<button id="bt1" >testajax</button>
</body>
</html>