标签:jdb tom ccm mtu view back min htm inter
Spring MVC 自定义拦截器
Interceptor 拦截功能基于 java 的动态代理实现。
SpringMVC中的Interceptor拦截器是链式的,可以同时存在。
在spring 框架之中,实现自定义拦截类,可以实现
第一种是实现HandlerInterceptor接口,
第二种是实现WebRequestInterceptor接口
@Slf4j //lombok
@Component
public class AuthorityIntercept implements HandlerInterceptor{
/**
*在进入 Controller 之前调用
*
* true : 调用当前请求的 Controller 中的方法
* 或 下一个拦截器
* false : 请求结束,不会进入到 Controller 层
*
* handler : (HandlerMethod) 封装了请求控制层的 Bean 实例
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
//日志记录
String methodName = handlerMethod.getMethod().getName();
Class _class = handlerMethod.getBeanType();
String className = _class.getSimpleName();
Map<String,String[]> parameterMap = request.getParameterMap();
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String[]> entry: parameterMap.entrySet()) {
// == "" 易精确的查找
String key = entry.getKey();
String [] parameter = entry.getValue();
String value = Arrays.asList(parameter).toString();
sb.append("key :").append(key).append(",").append("value : ").append(value);
}
log.info("request className :{} methodName :{}, parameter :{}",className,methodName,sb);
//不拦截 user login 的方法,(无法登入)
//也可以在 dispatcher-servlet.xml 进行配置 exclude
if (methodName.equals("UserManageController") && className.equals("login")){
return true;
}
User user = null;
String loginToken = LoginCookieUtil.readLoginCookieValue(request);
if (StringUtils.isNotBlank(loginToken)){
user = JacksonUtil.stringToObject(SharedRedisPoolUtil.get(loginToken),User.class);
}
if (user == null || user.getRole() != Const.Role.ROLE_ADMIN) {
//返回false.即不会调用controller里的方法 需要返回设置格式
// 这里要添加reset,否则报异常 getWriter() has already been called for this response.
response.reset();
//这里要设置编码,否则会乱码
response.setCharacterEncoding("UTF-8");
// 这里要设置返回值的类型,因为全部是json接口。
response.setContentType("application/json;charset=UTF-8");
PrintWriter out = response.getWriter();
if (user == null){
out.print(JacksonUtil.objectToString(ServerResponse.createByErrorMessage("拦截器拦截,请登入")));
}else{
out.print(JacksonUtil.objectToString(ServerResponse.createByErrorMessage("拦截器拦截,用户无权限操作")));
}
}
return true;
}
/**
* Controller 执行之后调用
*/
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
//DispatcherServlet 渲染了对应的视图之后执行,这个方法的主要作用是用于进行资源清理的工作。
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
System.out.println("afterCompletion");
}
}
<!-- 声明拦截器 --> <mvc:interceptors> <!-- 使用 bean 定义一个 Interceptor,直接定义在 mvc:interceptors 下面的 Interceptor 将拦截所有的请求 --> <mvc:interceptor> <!-- /manage/** 包含子路径 /manage/* 当前路径 / web 项目根路径 --> <mvc:mapping path="/manage/**" /> <!-- 对登入不拦截 --> <mvc:exclude-mapping path="/manage/user/login.do"/> <!-- 定义在 mvc:interceptor 下面的 Interceptor,表示对特定的请求进行拦截 --> <bean class="com.mmall.controller.Intercept.AuthorityIntercept"/> </mvc:interceptor> </mvc:interceptors>
<!-- 配置拦截器 --> <mvc:interceptors> <!-- 多个拦截器,按顺序执行 --> <mvc:interceptor> <mvc:mapping path="/**"/> <!-- 表示拦截所有的url包括子url路径 --> <bean class="ssm.interceptor.HandlerInterceptor1"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="ssm.interceptor.HandlerInterceptor2"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="ssm.interceptor.HandlerInterceptor3"/> </mvc:interceptor> </mvc:interceptors>

当所有拦截器都放行的时候,preHandle方法是按照配置的顺序执的;而另外两个方法按照配置的顺序逆向执行的。

1. 由于拦截器1和2放行,所以拦截器3的preHandle才能执行。也就是说前面的拦截器放行,后面的拦截器才能执行preHandle。
2. 拦截器3不放行,所以其另外两个方法没有被执行。即如果某个拦截器不放行,那么它的另外两个方法就不会背执行。
3. 只要有一个拦截器不放行,所有拦截器的postHandle方法都不会执行,但是只要执行过preHandle并且放行的,就会执行afterCompletion方法。

只执行了第一个拦截器的preHandle方法,因为都不放行,所以没有一个执行postHandle方法和afterCompletion方法。
拦截器放行的时候,会进入下一个拦截器的preHandle方法(按照配置的顺序执行)或者进入 controller 层方法执行 ,
preHandle 所有的方法执行完,另外两个方法得到执行的前提式 preHandle 返回图 true ,因此,
另外两个方法按照配置的顺序逆向执行的(根据实际 preHandle 执行情况)。
标签:jdb tom ccm mtu view back min htm inter
原文地址:https://www.cnblogs.com/SacredOdysseyHD/p/9062463.html