Spring模块 | 拦截器如何实现

简介: Spring根据官方文档实现拦截器

拦截器

官方文档介绍

所有实现都支持处理程序拦截器,当您要将特定功能应用于某些请求(例如,检查主体)时,这些拦截器非常有用。拦截器必须使用三种方法从包中实现,这些方法应提供足够的灵活性来执行各种预处理和后处理:HandlerMappingHandlerInterceptororg.springframework.web.servlet

  • preHandle(..):在运行实际处理程序之前,
  • postHandle(..):运行处理程序后
  • afterCompletion(..):完成请求后

拦截器如何实现

实现一个自己的拦截器,需要实现HandlerInterceptor接口。接口内的三个核心方法如下:

1.preHandle():该方法在业务处理器处理请求之前调用。主要用来进行一些前置初始化操作或者是对当前请求的预处理,也可以进行一些判断来决定请求是否要继续下去,该方法的返回值类型位boolean值,如果返回位false,就表示当前请求结束,如果返回为true,那么就会继续调用下一个Interceptor 的 preHandle 方法,如果已经是最后一个 Interceptor 的时候就会调用当前请求的 Controller 方法。

2.postHandle():这个方法在当前请求进行处理之后,也就是Controller方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的ModelAndView 对象进行操作。

3.afterCompletion():在postHandle执行之后执行,发生异常也会执行。该方法将在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。

拦截器的代码实现

登陆拦截器

publicclassLogInterceptorextendsHandlerInterceptorAdapter {

 

   //在执行Controller方法之前来执行的

   //用于用户认证校验、用户权限校验

   @Override

   publicbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler)

           throwsException {

       longstartTime=System.currentTimeMillis();

       System.out.println("\n-------- LogInterception.preHandle --- ");

       System.out.println("Request URL: "+request.getRequestURL());

       System.out.println("Start Time: "+System.currentTimeMillis());

 

       request.setAttribute("startTime", startTime);

 

       returntrue;

   }

   //在执行Controller方法之后返回modelAndView之前来执行

   //如果需要向页面提供一些公用的数据或配置一些视图信息,使用此方法实现从modelAndView入手

   @Override

   publicvoidpostHandle(HttpServletRequestrequest, HttpServletResponseresponse, //

                          Objecthandler, ModelAndViewmodelAndView) throwsException {

 

       System.out.println("\n-------- LogInterception.postHandle --- ");

       System.out.println("Request URL: "+request.getRequestURL());

 

       // You can add attributes in the modelAndView

       // and use that in the view page

   }

 

   //完成对页面的渲染之后执行此方法

   //作系统统一异常处理,进行方法执行性能监控,在preHandle中设置一个时间点,在afterCompletion设置一个时间,两个时间       点的差就是执行时长

   //实现系统统一日志记录

   @Override

   publicvoidafterCompletion(HttpServletRequestrequest, HttpServletResponseresponse, //

                               Objecthandler, Exceptionex) throwsException {

       System.out.println("\n-------- LogInterception.afterCompletion --- ");

 

       longstartTime= (Long) request.getAttribute("startTime");

       longendTime=System.currentTimeMillis();

       System.out.println("Request URL: "+request.getRequestURL());

       System.out.println("End Time: "+endTime);

 

       System.out.println("Time Taken: "+ (endTime-startTime));

   }

 

}

 

鉴权拦截器

publicclassAdminInterceptorextendsHandlerInterceptorAdapter {

 

   @Override

   publicbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler)

           throwsException {

 

       System.out.println("\n-------- AdminInterceptor.preHandle --- ");

       returntrue;

   }

 

   @Override

   publicvoidpostHandle(HttpServletRequestrequest, HttpServletResponseresponse, //

                          Objecthandler, ModelAndViewmodelAndView) throwsException {

 

       System.out.println("\n-------- AdminInterceptor.postHandle --- ");

   }

 

   @Override

   publicvoidafterCompletion(HttpServletRequestrequest, HttpServletResponseresponse, //

                               Objecthandler, Exceptionex) throwsException {

 

       System.out.println("\n-------- AdminInterceptor.afterCompletion --- ");

   }

 

}

 

拦截器添加到拦截列表

@Configuration

publicclassWebConfigimplementsWebMvcConfigurer {

   @Override

   publicvoidaddInterceptors(InterceptorRegistryregistry) {

       // LogInterceptor apply to all URLs.

       // LogInterceptor应用于所有url。

       registry.addInterceptor(newLogInterceptor());

 

       

       // 这个拦截器应用于/admin/*这样的URL

       // Exclude /admin/oldLogin

       registry.addInterceptor(newAdminInterceptor())//

               .addPathPatterns("/admin/*");

   }

 

}

 

业务逻辑处理Controller

@Controller

publicclassInterceptorTestController {

 

   @RequestMapping(value= { "/", "/test" })

   publicStringtest(Modelmodel) {

 

       System.out.println("\n-------- MainController --- ");

 

       System.out.println(" ** You are in Controller ** ");

 

       return"test";

   }

 

   @RequestMapping(value= { "/admin/login" })

   publicStringlogin(Modelmodel) {

 

       System.out.println("\n-------- MainController.login --- ");

 

       System.out.println(" ** You are in Controller ** ");

 

       return"login";

   }

 

}

 

流程顺序

拦截器

模拟登陆拦截

配置登陆拦截器

publicclassLoginInterceptor2implements  HandlerInterceptor{

   @Override

   publicbooleanpreHandle(HttpServletRequestrequest,

                            HttpServletResponseresponse, Objecthandler) throwsException {

       System.out.println("preHandle方法在控制器的处理请求方法调用之前执行");

       Stringuri=request.getRequestURI();

       //判断当前请求地址是否登录地址

       if(uri.contains("login") ||uri.contains("toLoginPage"))

       {

           //直接放行

           returntrue;

       }

       else

       {

           //判断用户是否登录

           if(request.getSession().getAttribute("userName")!=null)

               //说明已经登录,放行

               returntrue;          

           else

               //没有登录,重定向到登录界面

               response.sendRedirect(request.getContextPath() +"/toLoginPage");  

       }

 

       //默认拦截

       returnfalse;

   }

   @Override

   publicvoidpostHandle(HttpServletRequestrequest,

                          HttpServletResponseresponse, Objecthandler,

                          ModelAndViewmodelAndView) throwsException {

       System.out.println("postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行");

   }

   @Override

   publicvoidafterCompletion(HttpServletRequestrequest,

                               HttpServletResponseresponse, Objecthandler, Exceptionex)

           throwsException {

       System.out.println("afterCompletion方法在控制器的处理请求方法执行完成后执行,即视图渲染结束之后执行");

   }

}

 

添加登陆拦截器

@Configuration

publicclassWebConfigimplementsWebMvcConfigurer {

 

   @Override

   publicvoidaddViewControllers(ViewControllerRegistryregistry)

   {

       registry.addViewController("/toIndexPage").setViewName("/index");

       registry.addViewController("/").setViewName("/index");

   }

 

   @Override

   publicvoidaddInterceptors(InterceptorRegistryregistry) {

       registry.addInterceptor(newLoginInterceptor2())

           .addPathPatterns("/**") //所有路径都被拦截

           .excludePathPatterns( //添加不拦截路径

               "/toLoginPage", //登录页面

               "/login",       //登录请求

               "/**/*.html",   //html静态资源

               "/**/*.js",     //js静态资源

               "/**/*.css"     //css静态资源

       );

   }

}

controller层

@Controller

publicclassUserController {

 

   /**

    * 登录页面

    */

   @RequestMapping("/toLoginPage")

   publicStringtoLoginPage()

   {

       //跳转至登录页面

       return"login.html";

   }

   /**

    * 登录

    */

   @RequestMapping(value="/login", method=RequestMethod.POST)

   publicStringlogin(Modelmodel, HttpServletRequestrequest, StringuserName, Stringpassword)

   {

       //验证登录信息

       if (userName.equals("xiaoqi") &&password.equals("123456"))

       {

           //验证成功,记录Session信息

           request.getSession().setAttribute("userName", userName);

           //重定向到首页

           return"redirect:toIndexPage";

       }

       else

       {

           model.addAttribute("errorMsg", "账号或密码错误!");

       }

       //跳转至登录页面

       returntoLoginPage();

   }

 

   /**

    * 登出

    */

   @RequestMapping(value="/logout")

   publicStringlogout(HttpServletRequestrequest)

   {

       //销毁session对象

       request.getSession().invalidate();

       //重定向到登录页面

       return"redirect:toLoginPage";

   }

}

HTML页面

<!DOCTYPE html>

<htmllang="en"xmlns:th="http://www.thymeleaf.org">

<head>

   <metacharset="UTF-8">

   <title>用户登录</title>

</head>

<body>

<divalign="center">请输入登录信息

   <formname="Mfrom"method="post"action="/login"onsubmit="SubmitLogin()">

       <table>

           <tr>

               <td>用户姓名:</td>

               <td><inputtype="text"name="userName"value="xiaoqi"class="txtBox"/></td>

           </tr>

           <tr>

               <td>登录密码:</td>

               <td><inputtype="password"name="password"value="123456"class="txtBox"/></td>

           </tr>

           <!-- 以下是提交、取消按钮 -->

           <tr>

               <td>

                   <inputtype="submit"value="登录"/>

               </td>

               <td>

                   <inputtype="reset"value="取消"/>

               </td>

           </tr>

       </table>

       <pstyle="color:red"th:text="${errorMsg}"></p>

   </form>

</div>

</body>

<script>

   //提交登录

   functionSubmitLogin() {

       //判断用户名是否为空

       if (!Mfrom.userName.value) {

           alert("请输入用户姓名!");

           Mfrom.userName.focus();

           returnfalse;

       }

 

       //判断密码是否为空

       if (!Mfrom.password.value) {

           alert("请输入登录密码!");

           Mfrom.password.focus();

           returnfalse;

       }

       returntrue;

   }

</script>

</html>

<!DOCTYPE html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>

   <meta charset="UTF-8">

   <title>首页</title>

   <meta name="author" content="pan_junbiao的博客">

</head>

<body>

<h1>首页</h1>

<p>当前Session中保存的登录人名称:<span th:text="${session.userName}"/></p>

<a href="logout" onclick="return confirm('确定注销吗?');">注销</a>

</body>

</html>


相关文章
|
24天前
|
监控 Java 数据安全/隐私保护
如何用Spring Boot实现拦截器:从入门到实践
如何用Spring Boot实现拦截器:从入门到实践
42 5
|
1月前
|
Java 数据库连接 数据库
不可不知道的Spring 框架七大模块
Spring框架是一个全面的Java企业级应用开发框架,其核心容器模块为其他模块提供基础支持,包括Beans、Core、Context和SpEL四大子模块;数据访问及集成模块支持数据库操作,涵盖JDBC、ORM、OXM、JMS和Transactions;Web模块则专注于Web应用,提供Servlet、WebSocket等功能;此外,还包括AOP、Aspects、Instrumentation、Messaging和Test等辅助模块,共同构建强大的企业级应用解决方案。
68 2
|
2月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
34 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
4月前
|
前端开发 JavaScript Java
Spring Boot中使用拦截器
本节主要介绍了 Spring Boot 中拦截器的使用,从拦截器的创建、配置,到拦截器对静态资源的影响,都做了详细的分析。Spring Boot 2.0 之后拦截器的配置支持两种方式,可以根据实际情况选择不同的配置方式。最后结合实际中的使用,举了两个常用的场景,希望读者能够认真消化,掌握拦截器的使用。
|
5月前
|
消息中间件 负载均衡 Java
最容易学会的springboot gralde spring cloud 多模块微服务项目
最容易学会的springboot gralde spring cloud 多模块微服务项目
|
6月前
|
监控 Java 关系型数据库
java版MES系统源码,后端采用 Spring Boot 多模块架构
MES系统采用Vue3的vue-element-plus-admin为后台,Spring Boot多模块架构,支持MySQL、Oracle等数据库,具备SaaS多租户功能。核心功能包括车间计划排程、工艺流程配置、生产质量管理、进度追踪、库存和排班管理等,全面覆盖生产运营关键环节。
101 0
java版MES系统源码,后端采用 Spring Boot 多模块架构
|
5月前
|
监控 前端开发 Java
Spring Boot中的拦截器配置
Spring Boot中的拦截器配置
|
5月前
|
IDE Java Spring
Spring Boot中的多模块项目构建
Spring Boot中的多模块项目构建
|
7月前
|
前端开发 Java 程序员
Spring Boot统一功能处理(拦截器, 统一数据返回格式, 统一异常处理)
Spring Boot统一功能处理(拦截器, 统一数据返回格式, 统一异常处理)
132 1
|
6月前
|
IDE Java Spring
Spring Boot中的多模块项目构建
Spring Boot中的多模块项目构建