什么是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的比较
- Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC就容易实现restful url,而struts2的架构实现起来要费劲,因为Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共 享,这也就无法用注解或其他方式标识其所属方法了。
- 由上边原因,SpringMVC的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结 果通过ModelMap交回给框架,方法之间不共享变量, Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有 Action变量是共享的,这不会影响程序运行,却给我们编码 读程序时带来麻烦,每次来了请求就创建一个Action,一个Action对象对应一个request上下文。
- springmvc的内存消耗比struts2小,由于Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。
- 拦截器实现机制上,Struts2有以自己的interceptor机制,SpringMVC用的是独立的AOP方式,这样导致Struts2的配置文件量还是比SpringMVC大。
- SpringMVC的入口是servlet,而Struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。
- SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
- SpringMVC验证支持JSR-303,处理起来相对更加灵活方便,而Struts2验证比较繁琐,感觉太烦乱。
- Spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC一样的效果,但是需要xml配置的地方不少)。
- 设计思想上,Struts2更加符合OOP的编程思想, SpringMVC就比较谨慎,在servlet上扩展。
- SpringMVC开发效率和性能高于Struts2。
- SpringMVC可以认为已经100%零配置。
springmvc原理图
- 用户发送请求至前端控制器DispatcherServlet;
- DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
- 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
- DispatcherServlet通过HandlerAdapter处理器适配器调用处理器;
- 执行处理器(Handler,也叫后端控制器);
- Handler执行完成返回ModelAndView;
- HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
- DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
- ViewResolver解析后返回具体View;
- DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
- DispatcherServlet响应用户。
springmvc的四种处理器映射
程序通过什么方式来找到我请求所要访问的是哪一个Action
- 根据controller的name名称来映射寻找controller(StudentAction)
- 开启该映射:默认是开启的
- 定义bean的name属性:
- 界面访问URL:与bean的name属性值一致
http://localhost:5080/springmvc/hello1.do
2.根据URL来映射寻找controller:推荐使用
- 开启该映射:
< property name=“mappings”>
< props>
< prop key="/hello2.do">HelloController
< /props>
< /property>
< /bean> - 定义bean:
- 界面URL访问:与prop的key属性值一致
http://localhost:5080/springmvc/hello2.do
优点:将controller定义与映射分离开,耦合性低。
3.根据controller的类名来映射寻找controller:
- 开启类名映射处理器:
- 定义bean
< bean id=“hello3Controller” class=“com.controller.Hello2Controller”> - 界面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 (不建议使用)
4.使用注解来映射寻找controller:
DefaultAnnotationHandlerMapping
DefaultAnnotationHandlerMapping和RequestMappingHandlerMapping都是处理requestMapping的注解,
前者以废弃,不建议使用,后者用来代替前者
- 开启注解扫描组件:
作用:当我加载配置文件时,到我们指定的包下扫描(读取)Java文件,
寻找标注注解的地方(接口,类,方法或者其他),进行完成初始化。
< 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”>
- 在类上标记:@Controller 声明该类是一个springMVC Controller
- 在方法上使用:@RequestMapping("/login") 声明该方法处理哪一个请求
eg:
@Controller
public class Login {
@RequestMapping("/login")
public ModelAndView login(){
ModelAndView mv = new ModelAndView();
mv.setViewName(“login”);
return mv;
}
}