- 什么是SpringMVC
类似于struts2的一款轻量级框架
使用了mvc架构模式思想,将web层进行 职责解耦
springMVC就是spring框架中的webmvc
用来管理用户请求映射
- SpringMVC结构图
- SpringMVC作用
清晰的角色划分:控制器(controller)、验证器(validator)、命令对象
(command obect)、表单对象(form object)、模型对象(model object)、Servlet
分发器(DispatcherServlet)、处理器映射(handler mapping)、视图解析器
(view resoler)等等。每一个角色都可以由一个专门的对象来实现。 可适配、非侵入:可以根据不同的应用场景,选择何事的控制器子类(simple型、
command型、from型、wizard型、multi-action型或者自定义),而不是一个
单一控制器(比如Action/ActionForm)继承。 灵活的model转换:在Springweb框架中,使用基于Map的键/值对来达到轻
易的与各种视图技术集成。
特别的喜欢使用:map类型的参数
model:basedao,StudentDAO,Student Spring MVC支持国际化,支持根据用户区域显示多国语言,并且国际化的配置
非常简单。 Spring MVC 提供了一个前端控制器DispatcherServlet,开发者无须额外开发控制
器对象。DispatcherServlet:私人秘书 Spring MVC可以自动绑定用户输入,并正确地转换数据类型。例如:Spring MVC
能自动解析字符串,并将其设置为模型的int或float类型的属性。
- SpringMVC和struts2的比较
1、Struts2是类级别的拦截, 一个类对应一个request上下文, SpringMVC是方法级别的拦截,一个方法对应一个request上下文, 而方法同时又跟一个url对应,所以说从架构本身上SpringMVC就容易 实现restful url,而struts2的架构实现起来要费劲,因为Struts2 中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。
2、由上边原因,SpringMVC的方法之间基本上独立的,独享 request response数据,请求数据通过参数获取,处理结 果通过ModelMap交回给框架,方法之间不共享变量,而 Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有 Action变量是共享的,这不会影响程序运行,却给我们编码 读程序时带来麻烦,每次来了请求就创建一个Action,
一个Action对象对应一个request上下文。
3、springmvc的内存消耗比struts2小,由于Struts2需要针对每个request进行封装,把request,session
等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。
4、 拦截器实现机制上,Struts2有以自己的interceptor机制,SpringMVC用的是独立的AOP方式,这样导致Struts2的配置文件 量还是比SpringMVC大。
5、SpringMVC的入口是servlet,而Struts2是filter(这里要指出, filter和servlet是不同的。以前认为filter是servlet的一种特殊),这就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。
6、SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody 就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
7、SpringMVC验证支持JSR-303,处理起来相对更加灵活方便, 而Struts2验证比较繁琐,感觉太烦乱。
8、Spring MVC和Spring是无缝的。从这个项目的管理和安全上 也比Struts2高(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC一样的效果,但是需要xml配置的地方不少)。
9、 设计思想上,Struts2更加符合OOP的编程思想, SpringMVC就比较谨慎,在servlet上扩展。
10、SpringMVC开发效率和性能高于Struts2。
11、SpringMVC可以认为已经100%零配置。
- SpringMVC的原理图
- 处理流程
用户发起请求,首先到达前端控制器(DispatcherServlet), DispatcherServlet通过处理器映射器找到解析该请求的正确的Handler, DispatcherServlet得到这个Handler后会请求处理器适配器去按照指定的Handler处理请求,并执行请求中的方法,最后返回一个ModelAndView类型的参数。DispatcherServlet会最终请求视图解析器解析ModelAndView得到里面的数据和页面信息,进行视图渲染后交给用户。
1、用户发送请求到前端控制器(中央处理器)DispatcherServlet
2、请求调用HandlerMapping处理器映射器:根据你的配置信息判断你该使用哪一种处理器 注释:springMVC有4中类型的处理器映射器springMVC的Handler接口根据HTTP请求选择合适的controller。 详情见:springmvc4中处理器映射器文档.docx
3、 DispatcherServlet调用HandlerAdapter处理器适配器 :按照你所指定额处理器处理请求。
3.1 HandlerMapping 和 HandlerAdapter
3.2 Spring mvc 使用HandlerMapping来找到并保存url请求和处理函数间的 mapping 关系。DefaultAnnotationHandlerMapping:将扫描当前所有已经注册的springbeans中的@requestmapping标注以找出url 和 handler method处理函 数的关系并予以关联。
3.3 Spring MVC 通过HandlerAdapter来实际调用处理函数。 AnnotationMethodHandlerAdapter:DispatcherServlet中根据handlermapping 找到对应的handler method后,首先检查当前工程中注册的所有可用的 handlerAdapter,根据handlerAdapter中的supports方法找到可以使用的 handlerAdapter。通过调用handlerAdapter中的handle方法来处理及准备handler method中的参数及annotation(这就是spring mvc如何将reqeust中的参数变成handle method中的输入参数的地方),最终调用实际的handle method。
- SpringMVC的四种处理器映射器
- 根据controller的name名称来映射寻找controller(StudentAction)
BeanNameUrlHandlerMapping (默认)
1.1开启该映射:默认是开启的
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
1.2定义bean的name属性:
<bean id="helloController" name="/hello1.do" class="com.controller.HelloController"></bean>
1.3界面访问URL:与bean的name属性值一致
http://localhost:5080/springmvc/hello1.do
- 根据URL来映射寻找controller:推荐使用
SimpleUrlHandlerMapping
2.1开启该映射:
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
< property name="mappings">
< props>
< prop key="/hello2.do">HelloController</prop>
< /props>
< /property>
< /bean>
2.2定义bean:
<bean id="helloController" class="com.controller.HelloController"></bean>
2.3界面URL访问:与prop的key属性值一致
http://localhost:5080/springmvc/hello2.do
优点:将controller定义与映射分离开,耦合性低。
- 根据controller的类名来映射寻找controller:
ControllerClassNameHandlerMapping
3.1开启类名映射处理器:
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean>
3.2定义bean
< bean id="hello3Controller" class="com.controller.Hello2Controller"></bean>
3.3界面URL访问:与bean的id属性值无关。
http://localhost:5080/springmvc/hello2.do 正确
http://localhost:5080/springmvc/hello2Controller.do 正确
http://localhost:5080/springmvc/hello21111.do 正确
http://localhost:5080/springmvc/hello3.do 错误
注意点:使用类名来访问一个Controller,
类名首字符要小写,后面要加.do (不建议使用)
- 使用注解来映射寻找controller:
DefaultAnnotationHandlerMapping
efaultAnnotationHandlerMapping和RequestMappingHandlerMapping都是处理requestMapping的注解,
前者以废弃,不建议使用,后者用来代替前者
1.开启注解扫描组件:
作用:当我加载配置文件时,到我们指定的包下扫描(读取)Java文件,
寻找标注注解的地方(接口,类,方法或者其他),进行完成初始化。
<beans>
<!--配置扫描使用注解的包路径 -->
< context:component-scan base-package="com.it"></context:component-scan>
< !--开启springMVC注解 -->
< bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
< bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>
</beans>
2.在类上标记:@Controller 声明该类是一个springMVC Controller
3.在方法上使用:@RequestMapping("/login") 声明该方法处理哪一个请求
eg:
@Controller
public class Login {
@RequestMapping("/login")
public ModelAndView login(){
ModelAndView mv = new ModelAndView();
mv.setViewName("login");
return mv;
}
}
- 上手案例
- maven中pom.xml添加jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
- 配置web.xml文件(前端控制器)以及spring配置文件
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 通过监听扫描spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:application-*.xml </param-value>
</context-param>
<!-- 配置监听以实例化Spring上下文 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
- spring的配置文件
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- spring 扫描 -->
<context:component-scan base-package="com.it"></context:component-scan>
<!-- mvc注解驱动 -->
<mvc:annotation-driven/>
<!--通用视图解析器 -->
<bean id="viewResolverCommon"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
- 控制层Controller
StudentController通过@Controller,实例了@Controller之后,程序是如何找到对应的方法,springmvc通过注解进行匹配,@RequestMapping就是请求映射:
value="add.do":请求的地址
method=RequestMethod.GET:设定当前的方法只支持那种类型的请求。
return "index";//这里的index表明的是views目录中的index.jsp,是受到了spring-core.xml中的视图解析器的影响。
- SpringMVC中转发和重定向
- 转发
@RequestMapping(value="test6.do",method=RequestMethod.GET)
public String test6(){
return "forward:/WEB-INF/views/index.jsp";
}
- 重定向
@RequestMapping(value=“test6.do”,method=RequestMethod.GET)
public String test6(){
return “redirect:add.do”;
}
- SpringMVC前后端值得交互方式
- 方法括号的中的参数(request,session,自定义的参数)
@RequestMapping(value="test4.do")
public String test4(HttpServletRequest request,HttpSession session,String username3){
request.setAttribute("username", "呼保义");
session.setAttribute("username1","及时雨");
string name=username3;//前端传来的值
return "index";
}
- ModelAndView
@RequestMapping("/test2.do")
public ModelAndView test2(){
ModelAndView mv=new ModelAndView("index");//index是逻辑视图
mv.addObject("username", "txc");
return mv;
}
- Model和ModelMap
public String test5(Model model,ModelMap mm){
model.addAttribute("username","海贼王");
mm.put("username","路飞");
return "index";
}
- Map
@RequestMapping("/test8")
@ResponseBody
//返回jsonl类型的数据
public Map<String,Object> test8(){
Map<String, Object> map=new HashMap<String, Object>();
map.put("flag", "1");
map.put("stus",new Student("1","2","3","4","5","6"));
return map;
}