2.1 静态资源处理
在web.xml中进行配置
- 带后缀,比如.action .do *.aaa 该种方式比较精确、方便,在以前和现在企业中都有很大的使用比例
/ 不会拦截 .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方式三:/* 拦截所有,包括.jsp
解决方案一:在spring.xml配置中加上
原理:添加该标签配置之后,会在SpringMVC上下文中定义一个DefaultServletHttpRequestHandler对象 ,这个对象如同一个检查人员,对进入DispatcherServlet的url请求进行过滤筛查,如果发现是一个静态资源请求,那么会把请求转由web应用服务器(tomcat)默认的DefaultServlet来处理,如果不是静态资源请求,那么继续由SpringMVC框架处理 缺点:静态资源只能放到 webapp/ 目录下,不能放进 WEB-INF目录中
解决方案二:SpringMVC框架自己处理静态资源,mapping:约定的静态资源的url规则,location:指定的静态资源的存放位置
<mvc:resources location="classpath:/" mapping="/resources/**"/>
<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接口
/**
* 直接声明形参ModelMap,封装数据
* url: http://localhost:8080/demo/handle11
*
* =================modelmap:class org.springframework.validation.support.BindingAwareModelMap
*/
@RequestMapping("/handle11")
public String handle11(ModelMap modelMap) {
Date date = new Date();// 服务器时间
modelMap.addAttribute("date",date);
System.out.println("=================modelmap:" + modelMap.getClass());
return "success";
}
/**
* 直接声明形参Model,封装数据
* url: http://localhost:8080/demo/handle12
* =================model:class org.springframework.validation.support.BindingAwareModelMap
*/
@RequestMapping("/handle12")
public String handle12(Model model) {
Date date = new Date();
model.addAttribute("date",date);
System.out.println("=================model:" + model.getClass());
return "success";
}
/**
* 直接声明形参Map集合,封装数据
* url: http://localhost:8080/demo/handle13
* =================map:class org.springframework.validation.support.BindingAwareModelMap
*/
@RequestMapping("/handle13")
public String handle13(Map<String,Object> map) {
Date date = new Date();
map.put("date",date);
System.out.println("=================map:" + map.getClass());
return "success";
}
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逻辑执⾏完毕但未跳转⻚⾯之前拦截⼀次
在跳转⻚⾯之后拦截⼀次
/**
* 自定义springmvc拦截器
*/
public class MyIntercepter01 implements HandlerInterceptor {
/**
* 会在handler方法业务逻辑执行之前执行
* 往往在这里完成权限校验工作
* @param request
* @param response
* @param handler
* @return 返回值boolean代表是否放行,true代表放行,false代表中止
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyIntercepter01 preHandle......");
return true;
}
/**
* 会在handler方法业务逻辑执行之后尚未跳转页面时执行
* @param request
* @param response
* @param handler
* @param modelAndView 封装了视图和数据,此时尚未跳转页面呢,你可以在这里针对返回的数据和视图信息进行修改
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyIntercepter01 postHandle......");
}
/**
* 页面已经跳转渲染完毕之后执行
* @param request
* @param response
* @param handler
* @param ex 可以在这里捕获异常
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyIntercepter01 afterCompletion......");
}
}
2.4 异常处理机制
//捕获全局异常说
@ControllerAdvice
public class GlobalExceptionResolver {
@ExceptionHandler(ArithmeticException.class)
public ModelAndView handleException(ArithmeticException exception, HttpServletResponse response) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg",exception.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
}
2.5 重定向参数传值
重定向时请求参数会丢失,我们往往需要重新携带请求参数,我们可以进⾏⼿动参数拼接如下:
return “redirect:handle01?name=” + name;
但是上述拼接参数的⽅法属于get请求,携带参数⻓度有限制,参数安全性也不⾼,此时,我们可以使 ⽤SpringMVC提供的flflash属性机制,向上下⽂中添加flflash属性,框架会在session中记录该属性值,当跳转到⻚⾯之后框架会⾃动删除flflash属性,不需要我们⼿动删除,通过这种⽅式进⾏重定向参数传递,参数⻓度和安全性都得到了保障,如下:
/**
* SpringMVC 重定向时参数传递的问题
* 转发:A 找 B 借钱400,B没有钱但是悄悄的找到C借了400块钱给A
* url不会变,参数也不会丢失,⼀个请求
* 重定向:A 找 B 借钱400,B 说我没有钱,你找别⼈借去,那么A ⼜带着400块的借钱需求找到C
* url会变,参数会丢失需要重新携带参数,两个请求
*/
@RequestMapping("/handleRedirect")
public String handleRedirect(String name,RedirectAttributes redirectAttributes) {
//return "redirect:handle01?name=" + name; // 拼接参数安全性、参数⻓度都有局限
// addFlashAttribute⽅法设置了⼀个flash类型属性,该属性会被暂存到session中,在
//跳转到⻚⾯之后该属性销毁
redirectAttributes.addFlashAttribute("name",name);
return "redirect:handle01";