一、SpringMVC架构
SpringMVC框架主要分为四个部分:DispatcherServlet、HandlerMapping、Controller、ViewResolver
1、DispatcherServlet
DispatcherServlet(前端控制器)提供Spring MVC的几种访问点,而且负责职责的调度,用于控制流程,主要职责:
- 文件上传解析,如果请求类型是multipart将通过MultipartResolver进行文件上传解析;
- 通过HandlerMapping,将请求映射到处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);
- 通过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);
- 通过ViewResolver解析逻辑视图名到具体视图实现;
- 本地化解析;
- 渲染具体的视图等;
- 如果执行过程中遇到异常将交给HandlerExceptionResolver来解析。
DispatcherServlet具体工作流程如下:
- 拦截符合特定格式的URL请求
- 初始化DispatcherServlet上下文对应的WebApplicationContext,并于业务层、持久层建立联系
- 初始化SpringMVC的各个组件,并装配到DispatherServlet中
DispatcherServlet需要在Web.xml中进行正确配置,才能接受http请求并组织协调SpringMVC的各个组成部分。
<servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:/springMVC.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>param-name:contextConfigLocation 不可更改
param-value:DispatcherServlet的配置文件,如果不指定该参数,则默认配置文件为/WEB-INF/
<servlet-name>
-servlet.xml。load-on-startup:定义为1表示启动容器时初始化该Servlet;
url-pattern:定义要拦截的URL请求。
拦截规则:
*.xxx
,指定要拦截的特定类型,最简单实用的方式,并且不会拦截静态文件 ,例如*.html 标致拦截所有以html为扩展名的请求/
,标识所有请求都通过DIspatcherServlet来处理2、处理映射HandlerMapping
通过处理器映射,你可以将Web请求映射到正确的处理器Controller上。当接收到请求时,DispatcherServlet将请求交给HandlerMapping处理器映射,让它检查请求并找到一个适当的HandlerExecutionChain,这个HandlerExecutionChain包含一个能处理该请求的处理器Controller。然后,DispatcherServlet执行定义在HandlerExecutionChain中的处理器Controller。
SpringMVC有四种映射处理器handlerMapping:
1)、BeanNameUrlHandlerMapping
该处理器是默认开启的,再spring-mvc.xml中配置:
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> <bean id="helloController" name="/hello" class="com.controller.HelloController"></bean>新建HelloController.java
public class HelloController implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { //do your things here... return new ModelAndView("hello"); } }新建hello.jsp
配置好后,启动程序,在浏览器中输入http://localhost:8080/hello
2)、SimpleUrlHandlerMapping
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <value> /hello=helloController </value> </property> </bean> <bean id="helloController" class="com.test.ssm.controller.HelloController"/>这种映射的优点是将映射器于Controller的定义分开,解耦
3)、ControllerClassNameHandlerMapping
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean> <bean id="hello3Controller" class="com.test.ssm.controller.HelloController"></bean>启动后浏览器中输入:http://localhost:8080/helloController,即可顺利进入页面
4)、DefaultAnnotationHandlerMapping
使用注解来映射寻找Controller,这个应该是目前最常用的方式
<beans> <!--配置扫描使用注解的包路径 --> <context:component-scan base-package="com"></context:component-scan> <!--开启springMVC注解 --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean> </beans>在类上标记:@Controller 声明该类是一个springMVC Controller
在方法上使用:@RequestMapping("/user") 声明该方法处理哪一个请求@Controller @RequestMapping("/user") public class UserController { @Resource private IUserService userService; @RequestMapping("/showUser") @ResponseBody public User getUserByID(HttpServletRequest request, Model model) { int userId = Integer.parseInt(request.getParameter("id")); User user = this.userService.getUserByID(userId); //绑定对象到User.jsp //model.addAttribute("user", user); return user; } @RequestMapping(value="/saveUser",method=RequestMethod.POST) @ResponseBody public Result postData(@RequestBody String userJson) { User user = JSON.parseObject(userJson, User.class); userService.saveUser(user); Result r = new Result(); r.setResCode(0); r.data.setMsg("success"); return r; }在浏览器中输入:http://localhost:8080/user/showUser?id=1
3、控制器Controller
负责处理用户请求,完成之后返回ModelAndView对象给DispatcherServlet
@Controller @RequestMapping("/user") public class UserController { @Resource private IUserService userService; @RequestMapping("/showUser") @ResponseBody public User getUserByID(HttpServletRequest request, Model model) { int userId = Integer.parseInt(request.getParameter("id")); User user = this.userService.getUserByID(userId); //绑定对象到User.jsp //model.addAttribute("user", user); return user; } @RequestMapping(value="/saveUser",method=RequestMethod.POST) @ResponseBody public Result postData(@RequestBody String userJson) { User user = JSON.parseObject(userJson, User.class); userService.saveUser(user); Result r = new Result(); r.setResCode(0); r.data.setMsg("success"); return r; }
4、视图解析器ViewResolver
暂略
二、工作原理
- 将客户端请求提交给DispatcherServlet
- 根据
<servlet-name>
servlet.xml的配置,查找HandlerMapping - 通过HandlerMapping找到处理请求的具体Controller
- Controller调用业务逻辑处理
- 处理完成之后,返回ModelAndView对象给DispatcherServlet
- 通过ViewResolver找到负责显示的具体View
- 由View将结果渲染到客户端
三、常用注解
- @Controller:声明Action组件,负责注册bean到Spring上下文
- @RequestMapping:用于为控制器指定可以处理的url请求
- @RequestParam:用于指定参数的name属性
- @RequestBody:用于读取Request请求的body部分数据
- @ResponseBody:用于将控制器方法返回的对象写入到Response对象的body数据区
- @PathVariable:用于指定url作为参数
- @Resource用于注入,( 由j2ee提供 ) 默认按名称装配
- @Autowired用于注入,(由spring提供) 默认按类型装配
- @ExceptionHandler:用于异常处理的方法
- @ControllerAdvice:用于使控制器成为全局的异常处理类
- @ModelAttribute:用于优先调用被注解的方法,或注解参数中的隐藏对象
四、拦截器
Spring提供了HandlerInterceptor接口和HandlerInterceptorAdapter适配器。实现这个接口或继承此类,就可以实现自己的拦截器。接口HandlerInterceptor包含三个方法,每个方法的参数handler,用来指向下一个拦截器。
- preHandle(),在Action之前执行的预处理,可以进行编码、安全控制等处理
- postHandle(),在生成View之前执行的后处理,调用了Service并返回ModelAndView,但未进行页面渲染,可以修改ModelAndView
- afterCompletion(),最后执行的返回处理,这时已经进行了页面渲染,可以进行日志记录、释放资源等处理
在实现了接口之后,就可以在配置文件中进行拦截器的配置。
public class TestInteceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("我被拦截了: preHandle"); return super.preHandle(request, response, handler); } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("我被拦截了: postHandle"); super.postHandle(request, response, handler, modelAndView); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("我被拦截了: afterCompletion"); super.afterCompletion(request, response, handler, ex); } }