在项目的开发中,在某些情况下,我们需要对客户端发出的请求进行拦截,常用的API拦截方式有Fliter,Interceptor,ControllerAdvice以及Aspect。
请求从Filter-->>Controller的过程中,只要在指定的环节出现异常,可以通过对应的机制进行处理。反之在任何一个环节如果异常未处理则不会进入下一个环节,会直接往外抛,例如在ControllerAdvice验证发生异常则会抛给Filter,如果Filter未处理,则最终会由Tomcat容器抛出。
可以获得Http原始的请求和响应信息,但是拿不到响应方法的信息。
注册Filter,在springboot当中提供了FilterRegistrationBean类来注册Filter
- /**
- * 检查用户是否已经完成登录
- */
- @WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
- @Slf4j
- public class LoginCheckFilter implements Filter{
- //路径匹配器,支持通配符
- public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- HttpServletRequest request = (HttpServletRequest) servletRequest;
- HttpServletResponse response = (HttpServletResponse) servletResponse;
-
- //1、获取本次请求的URI
- String requestURI = request.getRequestURI();// /backend/index.html
-
- log.info("拦截到请求:{}",requestURI);
-
- //定义不需要处理的请求路径
- String[] urls = new String[]{
- "/employee/login",
- "/employee/logout",
- "/backend/**",
- "/front/**"
- };
-
-
- //2、判断本次请求是否需要处理
- boolean check = check(urls, requestURI);
-
- //3、如果不需要处理,则直接放行
- if(check){
- log.info("本次请求{}不需要处理",requestURI);
- filterChain.doFilter(request,response);
- return;
- }
-
- //4、判断登录状态,如果已登录,则直接放行
- if(request.getSession().getAttribute("employee") != null){
- log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
- filterChain.doFilter(request,response);
- return;
- }
-
- log.info("用户未登录");
- //5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据
- response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
- return;
-
- }
-
- /**
- * 路径匹配,检查本次请求是否需要放行
- * @param urls
- * @param requestURI
- * @return
- */
- public boolean check(String[] urls,String requestURI){
- for (String url : urls) {
- boolean match = PATH_MATCHER.match(url, requestURI);
- if(match){
- return true;
- }
- }
- return false;
- }
- }
最后在Springboot主启动类中添加@ServletComponentScan
- @Slf4j
- @SpringBootApplication
- @ServletComponentScan //使用过滤器需加此注解
- public class ReggieApplication {
- public static void main(String[] args) {
- SpringApplication.run(ReggieApplication.class,args);
- log.info("项目启动成功...");
- }
- }
可以获得Http原始的请求和响应信息,也拿得到响应方法的信息,但是拿不到方法响应中的参数的值。
在web开发中,拦截器是经常用到的功能。它可以帮我们验证是否登陆、预先设置数据以及统计方法的执行效率等。在spring中拦截器有两种,第一种是HandlerInterceptor,第二种是MethodInterceptor。HandlerInterceptor是SpringMVC中的拦截器,它拦截的是Http请求的信息,优先于MethodInterceptor。而MethodInterceptor是springAOP的。前者拦截的是请求的地址,而后者是拦截controller中的方法
1.请求到达经过拦截器,响应回来也经过拦截器
2.只能拦截控制器相关请求不能拦截JSP请求
3.拦截器可以中断用户请求轨迹
将多个控制器中共有代码放入拦截器可以减少控制器代码冗余
1.实现HandlerInterceptor接口(或继承其实现类)或者实现实现WebRequestInterceptor(或继承其实现类)。
2.XML文件中配置拦截器
- package wmq.fly.mybatis.interceptor;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import org.springframework.stereotype.Component;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- @Component
- public class LoginInterceptor implements HandlerInterceptor {
- /**
- * 预处理回调方法,实现处理器的预处理
- * 返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或处理器
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
- System.out.println("开始拦截.........");
- //业务代码
- return false;
- }
-
- /**
- * 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
- * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
- */
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
- ModelAndView modelAndView) throws Exception {
- // TODO Auto-generated method stub
-
- }
- /**
- * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,
- * 如性能监控中我们可以在此记录结束时间并输出消耗时间,
- * 还可以进行一些资源清理,类似于try-catch-finally中的finally,
- * 但仅调用处理器执行链中
- */
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
- throws Exception {
- // TODO Auto-generated method stub
-
- }
-
- }