SpringMVC高级开发(RestFul风格对url的规范,拦截器)
一. RestFul风格, 对url的规范
之前的url给后台传递数据:
localhost:8888/spring10/user/findById.action?K1=v1&k2=v2....
RestFul风格的url:
localhost:8888/spring10/user/findById/v1/v2
SpringMVC 支持restFull风格:
前端控制器: 拦截url:之前写法:
<servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
请求的url 只要包含.action, 这个url进入到SpringMVC的前端控制器, 前端控制器调用处理器映射器, 根据url 查找处理器,
*.html 访问的html页面, 这个url 进入到SpringMVC的前端控制器,前端控制器调用处理器映射器, 根据url 查找处理器, 没找到, 返回404
1、restFull风格的前端控制器:
<servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
所有的url( 静态资源[图片,css,js,html]),Controller 的url 都会到前端控制器, ,前端控制器调用处理器映射器,
根据url 查找处理器, 静态资源找不到对应的处理器, 404
注意:不能写成 /*, 包括, 静态资源的url, Controller的url, jsp 都进入到前端控制器
2、restFul风格对静态资源的处理: 映射到真实的静态资源
//在spring3.0 之后, 提供了静态资源处理器, 只需要在springMVC配置文件中,配置那些url是静态资源 <!-- 静态资源处理器 --> <!-- /** 表示该文件夹下的所有子文件夹 --> <mvc:resources location="/css/" mapping="/css/**" /> <mvc:resources location="/images/" mapping="/images/**" /> <mvc:resources location="/page/" mapping="/page/**" /> <mvc:resources location="/scripts/" mapping="/scripts/**" />
3、传递参数
// {名字} 参数占位符 /hello/嘻嘻 --> {name}: 嘻嘻 @GetMapping("/hello/{uname}/{cid}") // @PathVariable("uname") 加在参数名前面, 把url的指定名字的占位符的值 赋值到方法参数上 public String hello(@PathVariable("uname") String name,@PathVariable("cid") Integer id) { System.out.println(name); System.out.println(id); return "hello"; }
4、url写法:
http://localhost:8080/test/hello/张三/123456
传值方式只能是少量字段,如果传入多值或者对象还需要使用原来的url方式,不冲突
二、拦截器
功能与过滤器一样, 都是拦截用户的请求,
与过滤器(Filter)的区别, 执行的先后顺序, 过滤器在前, 拦截器在后, /* 过滤器拦截所有请求, /* 进入到前端控制器之后的请求
SpringMVC的拦截器(Interceptor):
1、编写一个类实现HandlerInterceptor接口
public class Interceptor1 implements HandlerInterceptor{ //preHandle() 在处理器方法之前执行 可以阻止执行处理器的方法 // true: 放行 false: 拦截 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Interceptor1的preHandle()...."); return true; } // postHandle() 在处理器执行完, 页面还没有响应之前执行. @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("Interceptor1的postHandle()...."); } // 在响应完成之后,执行, 资源的清理 日志的记录 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("Interceptor1的afterCompletion()...."); } }
可配置多个不同功能的拦截器
2、在springMVC的配置文件中进行拦截器的配置
<!-- 配置拦截器: 配置一组拦截器: 拦截器链 --> <mvc:interceptors> <!-- 多个拦截器preHandle() 执行顺序根据 mvc:interceptor postHandle() afterCompletion() 与 mvc:interceptor 顺序相反 --> <!-- 一个一个的拦截器 --> <mvc:interceptor> <!-- 设置拦截的url /** 拦截所有url 本级目录以及所有子目录 /test/aaa /test/bbb /test/aaa/bbb /test/hello --> <mvc:mapping path="/test/**"/> <!-- 排除那些不拦截 --> <!-- <mvc:exclude-mapping path="/test/hello/"/> --> <!-- 指明拦截器 --> <bean class="com.zl.house.web.interceptor.Interceptor1"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/test/**"/> <!-- 指明拦截器 --> <bean class="com.zl.house.web.interceptor.Interceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
1) 拦截器执行顺序, 拦截器的afterCompletion()执不执行, 由拦截器的preHandle()放回在决定, 如果拦截器的preHandle()返回true, 执行, 如果为false,不执行
2) 处理器方法执不执行, 由拦截器链所有的preHandle()决定, 只要有一个返回值为false, 不执行.
测试:
1 、两个拦截器都放行
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle
HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion
总结:
preHandle方法按顺序执行,
postHandle和afterCompletion按拦截器配置的逆向顺序执行。
2、拦截器1放行,拦截器2不放行
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion
总结:
拦截器1放行,拦截器2 preHandle才会执行。
拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行。
只要有一个拦截器不放行,postHandle不会执行。
3、拦截器1不放行,拦截器2不放行
HandlerInterceptor1...preHandle
拦截器1 preHandle不放行,postHandle和afterCompletion不会执行。
拦截器1 preHandle不放行,拦截器2不执行。
4、小结
preHandle按拦截器定义顺序调用
postHandler按拦截器定义逆序调用
afterCompletion按拦截器定义逆序调用
postHandler在拦截器链内所有拦截器返成功调用
afterCompletion只有preHandle返回true才调用