个人笔记,如有错误,恳请批评指正。
Spring Web MVC是一种基于java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。 另外还有一种基于组件的、事件驱动的Web框架在此就不介绍了,如Tapestry、JSF等。 Spring Web MVC也是服务到工作者模式的实现,但进行可优化。前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(ViewResolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持
mvc、aop、core相关包
新建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>org.springframework.web.servlet.DispatcherServlet,继承HttpServlet,需要在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><!-- 继承servlet --> <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> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping></web-app>创建控制器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); }}修改spring-mvc.xm.文件
<?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.ustb.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>新建目录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>编写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=mike&pwd=admin">firstMVC</a> </body></html>strong text BeanNameUrlHandlerMapping:它将收到的HTTP请求映射到bean的名称(这些bean需要在web应用上下文中定义)
<!-- 声明bean的name,因为使用了BeanNameUrlHandlerMapping,所以不是定义id,用户调用的URL将通过bean的name匹配 --> <bean name="/first.action" class="cn.ustb.action.FirstAction" /> <!-- 声明 BeanNameUrlHandlerMapping,使用名称映射 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />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.ustb.action.FirstAction" /> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="first.action">first</prop> </props> </property> </bean>作为UrlBasedViewResolver的子类, 它支持页面jstl处理.
<!-- 支持servlet与jsp视图解析,可进行进一步处理,此步可省略, --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 可以加前缀或后缀 --> <property name="prefix" value="/jsp/"/> <property name="suffix" value=".jsp"/> </bean>forward使用转发方式:
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";在spring mvc中控制对象要实现controller接口,并且必须实现handRequest方法。此控制器在接收到DispatcherServlet分配置的请求时,执行handRequest方法,并返回ModelAndView实例,此实例中封装了Model与View。
public class FirstAction implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ... ...}可以将请求参数值自动设置到command对象中,便于后继的使用。
/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>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="student.action?stuName=mike&stuPwd=admin">test student</a> </body></html>除action类以外,其它继续使用上一节代码
继承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"); }}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>继续使用上一章节的代码(注意新建项目记得重新配置web.xml文件)
添加DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter等相关信息。其中 DefaultAnnotationHandlerMapping:支持通过url找到相关的action AnnotationMethodHandlerAdapter:支持通过url匹配action定义方法 base-package:定 义扫描的范围,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean
<?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 "> <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>加入@Controller,@RequestMapping注解信息
@Controller //用来声明控制器@RequestMapping("/student")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("/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"; }}基于上面的示例,在spring3中可以进一步简化配置,取代上面的注解方式. 步骤如下 1. 使用上面的action类,仍然给类及方法添加@Controller(类)、@RequestMapping(类及方法)注解 2. 本文件顶部添加spring mvc 命名空间的信息(可以参考org.springframework.web.servlet.config包) 3. 添加下面注解驱动mvc:annotation-driven,取代了上面的DefaultAnnotationHandlerMapping、AnnotationMethodHandlerAdapter,并启动了json的注解。
修改内容如下:
修改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: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>Spring 2.0 定义了一个 org.springframework.ui.ModelMap 类,它作为通用的模型数据承载对象,传递数据供视图所用。我们可以在请求处理方法中声明一个 ModelMap 类型的入参,Spring 会将本次请求模型对象引用通过该入参传递进来,这样就可以在请求处理方法内部访问模型对象了在默认情况下,ModelMap 中的属性作用域是 request 级别是,也就是说,当本次请求结束后,ModelMap 中的属性将销毁,但实际上有时候需要把ModelMap值存放于session中或有时候也可以从Session中获取对象的值注入到ModelMap中。
继续使用上一节代码
如果希望在多个请求中共享 ModelMap 中的属性,必须将其属性转存到 session 中,这样 ModelMap 的属性才可以被跨请求访问; 可以在定义 类时使用@SessionAttributes(“属性名”)或@SessionAttributes({“attr1”,”attr2”})等方式将尝试从modelMap中寻找相同属性名相应的value. 修改StudentAction.java类,
@Controller@RequestMapping("/student")//下边如有多个属性可以用 @SessionAttributes({“attr1”,”attr2”})。@SessionAttributes("user") public class StudentAction { public StudentAction(){ System.out.println("---StudentAction构造方法被调用---"); } @RequestMapping(value="/save") public String save(Student student,ModelMap map){ System.out.println("---调用业务逻辑进行业务处理---"); Student s2=new Student(); s2.setStuAge(11); s2.setStuId(11111); map.addAttribute("user", s2);//属性名必须与session一致 //map.addAttribute("stu", student); //直接使用字符串,返回视图,进行结果展现等 return "forward:/jsp/main.jsp"; } //同一个action中可以定义多个方法 @RequestMapping(value="/update") public String update(Student student){ System.out.println("update方法已注入student对象:"+student); System.out.println("---调用业务逻辑进行业务处理---"); paramMap.put("student",student); //直接使用字符串,返回视图,进行结果展现等 return "forward:/jsp/main.jsp"; }}修改/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.student}<br/> <!-- 默认直接通过session传递的值stu:${sessionScope.stu}<br/> --> 默认直接通过session传递user值:${sessionScope.user}<br/><!--下边的代码给下一示例使用:调用update方法测试把session的值注入到map中,此时session已经有user相关信息--> <a href="../student/update.action">session的值注入到map中</a> </body></html>在参数中使用@ModelAttribute(“user”),可以获取@SessionAttributes(“user”)值
继续使用上节代码 修改StudentAction.java类, 定义类时继续使用@SessionAttributes(“user”),并修改update方法,在参数中添加@ModelAttribute(“user”):参数中的student的对象将由session中获取。
@Controller@RequestMapping("/student")//下边如有多个属性可以用 @SessionAttributes({“attr1”,”attr2”})。@SessionAttributes("user") public class StudentAction { public StudentAction(){ System.out.println("---StudentAction构造方法被调用---"); } //同一个action中可以定义多个方法 @RequestMapping(value="/update") public String update(@ModelAttribute("user")Student student){ System.out.println("update方法已注入student对象:"+student); System.out.println("---调用业务逻辑进行业务处理---"); //直接使用字符串,返回视图,进行结果展现等 return "forward:/jsp/main.jsp"; }}新闻热点
疑难解答