2.1 静态资源处理

在web.xml中进行配置配置,配置的方式有三种,配置方式如下:

  1. 带后缀,比如.action .do *.aaa 该种方式比较精确、方便,在以前和现在企业中都有很大的使用比例
  2. / 不会拦截 .jsp,但是会拦截.html等静态资源(静态资源:除了servlet和jsp之外的js、css、png等)

    为什么配置为/ 会拦截静态资源???
    因为tomcat容器中有一个web.xml(父),你的项目中也有一个web.xml(子),是一个继承关系父web.xml中有一个DefaultServlet, url-pattern 是一个 / ,此时我们自己的web.xml中也配置了一个 / ,覆写了父web.xml的配置为什么不拦截.jsp呢?
    因为父web.xml中有一个JspServlet,这个servlet拦截.jsp文件,而我们并没有覆写这个配置,所以springmvc此时不拦截jsp,jsp的处理交给了tomcat

  3. 方式三:/* 拦截所有,包括.jsp

解决方案一:在spring.xml配置中加上

原理:添加该标签配置之后,会在SpringMVC上下文中定义一个DefaultServletHttpRequestHandler对象 ,这个对象如同一个检查人员,对进入DispatcherServlet的url请求进行过滤筛查,如果发现是一个静态资源请求,那么会把请求转由web应用服务器(tomcat)默认的DefaultServlet来处理,如果不是静态资源请求,那么继续由SpringMVC框架处理 缺点:静态资源只能放到 webapp/ 目录下,不能放进 WEB-INF目录中

解决方案二:SpringMVC框架自己处理静态资源,mapping:约定的静态资源的url规则,location:指定的静态资源的存放位置

  1. <mvc:resources location="classpath:/" mapping="/resources/**"/>
  2. <mvc:resources location="/WEB-INF/js/" mapping="/js/**"/>

2.2数据输出机制Model

SpringMVC在handler方法上传入Map、Model和ModelMap参数,并向这些参数中保存数据(放入到请求域),都可以在页面获取到
它们之间是什么关系?
运行时的具体类型都是BindingAwareModelMap,相当于给BindingAwareModelMap中保存的数据都会放在请求域中
Map(jdk中的接口)
Model(spring的接口)
ModelMap(class,实现Map接口)
BindingAwareModelMap继承了ExtendedModelMap,ExtendedModelMap继承了ModelMap,实现了Model接口

  1. /**
  2. * 直接声明形参ModelMap,封装数据
  3. * url: http://localhost:8080/demo/handle11
  4. *
  5. * =================modelmap:class org.springframework.validation.support.BindingAwareModelMap
  6. */
  7. @RequestMapping("/handle11")
  8. public String handle11(ModelMap modelMap) {
  9. Date date = new Date();// 服务器时间
  10. modelMap.addAttribute("date",date);
  11. System.out.println("=================modelmap:" + modelMap.getClass());
  12. return "success";
  13. }
  14. /**
  15. * 直接声明形参Model,封装数据
  16. * url: http://localhost:8080/demo/handle12
  17. * =================model:class org.springframework.validation.support.BindingAwareModelMap
  18. */
  19. @RequestMapping("/handle12")
  20. public String handle12(Model model) {
  21. Date date = new Date();
  22. model.addAttribute("date",date);
  23. System.out.println("=================model:" + model.getClass());
  24. return "success";
  25. }
  26. /**
  27. * 直接声明形参Map集合,封装数据
  28. * url: http://localhost:8080/demo/handle13
  29. * =================map:class org.springframework.validation.support.BindingAwareModelMap
  30. */
  31. @RequestMapping("/handle13")
  32. public String handle13(Map<String,Object> map) {
  33. Date date = new Date();
  34. map.put("date",date);
  35. System.out.println("=================map:" + map.getClass());
  36. return "success";
  37. }

2.3 拦截器(Interceptor)应用

2.3.1 监听器、过滤器和拦截去对比

Servlet:处理Request请求和Response响应
过滤器(Filter):对Request请求起到过滤的作⽤,作⽤在Servlet之前,如果配置为/可以对所有的资源访问(servlet、js/css静态资源等)进⾏过滤处理
监听器(Listener):实现了javax.servlet.ServletContextListener 接⼝的服务器端组件,它随Web应⽤的启动⽽启动,只初始化⼀次,然后会⼀直运⾏监视,随Web应⽤的停⽌⽽销毁
作⽤⼀:做⼀些初始化⼯作,web应⽤中spring容器启动ContextLoaderListener
作⽤⼆:监听web中的特定事件,⽐如HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等。可以在某些动作前后增加处理,实现监控,⽐如统计在线⼈数,利⽤ HttpSessionLisener等。
*拦截器(Interceptor)
:是SpringMVC、Struts等表现层框架⾃⼰的,不会拦截 jsp/html/css/image的访问等,只会拦截访问的控制器⽅法(Handler)。 从配置的⻆度也能够总结发现:serlvet、fifilter、listener是配置在web.xml中的,⽽interceptor是 配置在表现层框架⾃⼰的配置⽂件中的 在Handler业务逻辑执⾏之前拦截⼀次 在Handler逻辑执⾏完毕但未跳转⻚⾯之前拦截⼀次 在跳转⻚⾯之后拦截⼀次
image.png

  1. /**
  2. * 自定义springmvc拦截器
  3. */
  4. public class MyIntercepter01 implements HandlerInterceptor {
  5. /**
  6. * 会在handler方法业务逻辑执行之前执行
  7. * 往往在这里完成权限校验工作
  8. * @param request
  9. * @param response
  10. * @param handler
  11. * @return 返回值boolean代表是否放行,true代表放行,false代表中止
  12. * @throws Exception
  13. */
  14. @Override
  15. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  16. System.out.println("MyIntercepter01 preHandle......");
  17. return true;
  18. }
  19. /**
  20. * 会在handler方法业务逻辑执行之后尚未跳转页面时执行
  21. * @param request
  22. * @param response
  23. * @param handler
  24. * @param modelAndView 封装了视图和数据,此时尚未跳转页面呢,你可以在这里针对返回的数据和视图信息进行修改
  25. * @throws Exception
  26. */
  27. @Override
  28. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  29. System.out.println("MyIntercepter01 postHandle......");
  30. }
  31. /**
  32. * 页面已经跳转渲染完毕之后执行
  33. * @param request
  34. * @param response
  35. * @param handler
  36. * @param ex 可以在这里捕获异常
  37. * @throws Exception
  38. */
  39. @Override
  40. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  41. System.out.println("MyIntercepter01 afterCompletion......");
  42. }
  43. }

2.4 异常处理机制

  1. //捕获全局异常说
  2. @ControllerAdvice
  3. public class GlobalExceptionResolver {
  4. @ExceptionHandler(ArithmeticException.class)
  5. public ModelAndView handleException(ArithmeticException exception, HttpServletResponse response) {
  6. ModelAndView modelAndView = new ModelAndView();
  7. modelAndView.addObject("msg",exception.getMessage());
  8. modelAndView.setViewName("error");
  9. return modelAndView;
  10. }
  11. }

2.5 重定向参数传值

重定向时请求参数会丢失,我们往往需要重新携带请求参数,我们可以进⾏⼿动参数拼接如下:

return “redirect:handle01?name=” + name;

但是上述拼接参数的⽅法属于get请求,携带参数⻓度有限制,参数安全性也不⾼,此时,我们可以使 ⽤SpringMVC提供的flflash属性机制,向上下⽂中添加flflash属性,框架会在session中记录该属性值,当跳转到⻚⾯之后框架会⾃动删除flflash属性,不需要我们⼿动删除,通过这种⽅式进⾏重定向参数传递,参数⻓度和安全性都得到了保障,如下:

  1. /**
  2. * SpringMVC 重定向时参数传递的问题
  3. * 转发:A 找 B 借钱400,B没有钱但是悄悄的找到C借了400块钱给A
  4. * url不会变,参数也不会丢失,⼀个请求
  5. * 重定向:A 找 B 借钱400,B 说我没有钱,你找别⼈借去,那么A ⼜带着400块的借钱需求找到C
  6. * url会变,参数会丢失需要重新携带参数,两个请求
  7. */
  8. @RequestMapping("/handleRedirect")
  9. public String handleRedirect(String name,RedirectAttributes redirectAttributes) {
  10. //return "redirect:handle01?name=" + name; // 拼接参数安全性、参数⻓度都有局限
  11. // addFlashAttribute⽅法设置了⼀个flash类型属性,该属性会被暂存到session中,在
  12. //跳转到⻚⾯之后该属性销毁
  13. redirectAttributes.addFlashAttribute("name",name);
  14. return "redirect:handle01";