更多python、PHP、JAVA教程请到友情连接: 菜鸟教程https://www.piaodoo.com

茂名一技http://www.enechn.com

ppt制作教程步骤 http://www.tpyjn.cn

兴化论坛http://www.yimoge.cn

电白论坛 http://www.fcdzs.com

表格制作excel教程 http://www.tsgmyy.cn


高州阳光论坛 http://www.tsgmyy.cn


拦截器应该分属于web框架的组件,每个框架提供的自己的支持,实现方式也就不同。例如Struts和Spring,以下是Spring 的拦截器总结,它是基于动态代理(反射)实现的。

Spring 中声明拦截器需要实现 HandlerInterceptor 接口,当然也可以通过继承HandlerInterceptorAdapter 抽象类,HandlerInterceptorAdapter也是实现了HandlerInterceptor 接口。

拦截器中有四个方法:

preHandle:在Controller中的方法之前执行,决定是否放行,return true表示放行。一旦放行其对应的afterCompletion就一定会执行。

postHandle:Controller中的方法处理完之后,DispatcherServlet进行视图的渲染之前,也就是说在这个方法中你可以对ModelAndView进行操作

afterCompletion:DispatcherServlet进行视图的渲染之后

afterConcurrentHandlingStarted:与异步相关

下面通过代码实践,备注了是否放行和异常对拦截器内方法执行的影响结论。其实只需对方法执行的时机进行分析,我们就可以得出相同的结论。

如果想深入了解每个方法的执行时机,可以阅读SpringMVC的 DispatcherServlet 源码

@Component
public class InterceptorTwo extends HandlerInterceptorAdapter {
?
? ? /**
? ? * handler 对应@RequestMapping对应的controller对象
? ? */
? ? @Override
? ? public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
? ? ? ? //这里我们是没办法拿到方法参数的,parameters是空的,但是可以拿到controller种注入的bean
? ? ? ? //可以断点验证
? ? ? ? HandlerMethod handlerMethod = (HandlerMethod)handler;
? ? ? ? MethodParameter [] parameters = handlerMethod.getMethodParameters();
? ? ? ? return true;//放行
? ? }
?
? ? @Override
? ? public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
? ? ? ? //在拦截器链中,只要有一个不放行的,所有的postHandle都不会执行
? ? ? ? //如果Controller方法抛异常了,所有的postHandle也不会执行
? ? ? ? System.out.println("postHandle");
? ? }
?
? ? @Override
? ? public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
? ? ? ? //只要对应的preHandle放行了就一定会执行,Controller方法抛异常也不会影响
? ? ? ? System.out.println("afterCompletion");
? ? }
?
? ? @Override
? ? public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
? ? ? ? System.out.println("afterConcurrentHandlingStarted");
? ? }
}

使拦截器生效

//Springboot 是1.x版本的项目中是extends WebMvcConfigurerAdapter ,代码也是一样的
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
?
? ? @Autowired
? ? private SourceAccessInterceptor interceptor;
? ? @Autowired
? ? private InterceptorOne interceptorOne;
? ? @Override
? ? public void addInterceptors(InterceptorRegistry interceptorRegistry) {
? ? ? ? //1.加入的顺序就是拦截器执行的顺序,设置@Order也不会影响
? ? ? ? //2.按顺序执行所有拦截器的preHandle
? ? ? ? //3.所有的preHandle 执行完再反向执行全部postHandle 最后是反向执行afterCompletion,
? ? ? ? //如果其中有一个未放行,或者抛异常了会影响执行顺序吗?怎样影响
? ? ? ? interceptorRegistry.addInterceptor(interceptor).addPathPatterns("/**");
? ? ? ? interceptorRegistry.addInterceptor(interceptorOne);
? ? }
}

应用示例

这个拦截器是用来拦截请求是否有携带token的,如果请求未携带token,将会302重定向到登录界面。

@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {?
??
? ? @Autowired
? ? private JwtUtil jwtUtil;
?
? ? @Value("${login.url}")
? ? private String loginUrl;
?
? ? /**
? ? ?* 验证access_token
? ? ?*
? ? ?* @param request ?请求
? ? ?* @param response 响应
? ? ?* @param handler ?处理器controller
? ? ?*/
? ? @Override
? ? public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
?
? ? ? ? HandlerMethod handlerMethod = (HandlerMethod) handler;
? ? ? ? //WithoutToken是我自定义的注解,标注在方法上,表示不需要验证token
? ? ? ? if (handlerMethod.getMethod().isAnnotationPresent(WithoutToken.class)) {
? ? ? ? ? ? //不需要验证token
? ? ? ? ? ? return true;
? ? ? ? } else {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? //校验jwt
? ? ? ? ? ? ? ? String access_token = request.getHeader("access_token");
? ? ? ? ? ? ? ? jwtUtil.verifierToken(access_token);
? ? ? ? ? ? ? ? //获取用户信息
? ? ? ? ? ? ? ? final String account = jwtUtil.getAccount(access_token);
? ? ? ? ? ? ? ? //TODO 可以在这里查询用户信息,然后将用户信息设置到线程变量
? ? ? ? ? ? ? ??
? ? ? ? ? ? } catch (NullPointerException | JWTVerificationException e) {
? ? ? ? ? ? ? ? //TODO 重定向到登陆页
? ? ? ? ? ? ? ? response.sendRedirect(loginUrl);
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? ? ? return true;
?
? ? ? ? }
? ? }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持菜鸟教程www.piaodoo.com。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐