* 1、编写一个拦截器实现HandlerInterceptor接口 * 2、拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors) * 3、指定拦截规则【如果是拦截所有,静态资源也会被拦截】
这段代码定义了一个 `LoginInterceptor` 类,它实现了 `HandlerInterceptor` 接口,用于在 Spring MVC 中进行拦截器的操作。拦截器可以用来在请求的处理流程中执行特定的逻辑,比如权限检查、日志记录等。下面是对这段代码的注释和解释:
```java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerInterceptor;
@Slf4j // 通过 Lombok 注解自动创建 Logger 实例
public class LoginInterceptor implements HandlerInterceptor {
/**
* 目标方法执行之前调用的拦截器逻辑
* @param request HTTP 请求对象
* @param response HTTP 响应对象
* @param handler 处理器,例如 Controller 中的方法
* @return 如果返回 true,则请求继续执行;如果返回 false,则请求中断,不再执行后续的拦截器或处理器
* @throws Exception 可能抛出的异常
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取请求的 URI
String requestURI = request.getRequestURI();
// 使用 SLF4J 记录拦截的请求路径
log.info("preHandle拦截的请求路径是{}", requestURI);
// 登录检查逻辑
// 通过 request 获取当前会话的 HttpSession 对象
HttpSession session = request.getSession();
// 从 session 中获取名为 "loginUser" 的属性,用于验证用户是否已登录
Object loginUser = session.getAttribute("loginUser");
// 如果用户已登录(即 loginUser 不为空),则放行请求
if (loginUser != null) {
return true;
}
// 如果用户未登录,则拦截请求
// 将错误消息 "请先登录" 存储在 request 属性中,以便在登录页面显示
request.setAttribute("msg", "请先登录");
// 转发到登录页面(这里使用了 request.getRequestDispatcher("/") 来获取登录页面的请求分发器)
request.getRequestDispatcher("/").forward(request, response);
// 返回 false 表示请求被拦截,不会继续执行后续的拦截器或处理器
return false;
}
}
```
解释:
1. `@Slf4j` 是 Lombok 库提供的一个注解,它可以自动生成一个名为 `log` 的 `Logger` 实例,用于记录日志。这样,你就可以直接使用 `log.info()` 等方法来记录日志,而不需要手动创建 `Logger` 对象。
2. `preHandle` 方法是 `HandlerInterceptor` 接口中的一个方法,它在控制器方法(handler)执行之前被调用。这个方法的返回值决定了请求是否继续执行。如果返回 `true`,则请求继续向下执行;如果返回 `false`,则请求被拦截,不会执行后续的拦截器或控制器方法。
3. 在 `preHandle` 方法中,首先记录了当前请求的 URI。然后,通过 `request.getSession()` 获取当前会话的 `HttpSession` 对象,并尝试从会话中获取名为 "loginUser" 的属性,这个属性通常用于存储用户的登录状态。
4. 如果用户已经登录(`loginUser` 不为空),则方法返回 `true`,请求继续执行。
5. 如果用户未登录(`loginUser` 为空),则在请求属性中设置一条消息,并转发到登录页面。这里使用 `request.getRequestDispatcher("/").forward()` 方法来实现请求的转发。
6. 最后,方法返回 `false`,表示请求被拦截,不会继续执行后续的拦截器或控制器方法。
代码行 `request.getRequestDispatcher("/").forward(request, response);
` 是 Java Servlet API 中的一部分,用于在当前请求的上下文中转发请求到另一个资源。这行代码通常用于拦截器或 Servlet 中,当你想要将用户的请求从当前路径重定向到另一个路径时。
让我们分解这行代码:
- `request.getRequestDispatcher`:这是 `HttpServletRequest` 对象的一个方法,它创建一个 `RequestDispatcher` 对象。`RequestDispatcher` 是用于转发请求到其他资源的接口。调用 `request.getRequestDispatcher` 时,你需要传入一个路径,这个路径是相对于当前请求的路径的。
- `"/"`:这是传递给 `request.getRequestDispatcher` 方法的路径。在这个例子中,`"/"` 表示应用程序的根路径。这意味着请求将被转发到应用程序的首页或登录页面,具体取决于应用程序的配置。
- `.forward(request, response)`:这是 `RequestDispatcher` 对象的一个方法,它将请求和响应对象作为参数。此方法将请求和响应对象传递给目标资源,这样目标资源就可以生成响应内容并将其发送回客户端。
在上下文中,`request.getRequestDispatcher("/").forward(request, response);` 这行代码的作用是:
1. 获取一个能够转发请求到应用程序根路径的 `RequestDispatcher` 对象。
2. 使用这个 `RequestDispatcher` 将当前的请求和响应对象转发到根路径。
3. 由于请求被转发,控制器中 `preHandle` 方法之后的代码不会被执行。
4. 用户的浏览器会收到一个转发到新页面的响应,通常是登录页面,用户可以在该页面进行登录操作。
这种转发是服务器端的,用户不会感知到 URL 的变化(除非他们查看浏览器的地址栏)。这与重定向(redirect)不同,重定向是通过发送一个新的响应给客户端,告诉浏览器去请求一个新的 URL。
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") //所有请求都被拦截包括静态资源 .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**", "/js/**","/aa/**"); //放行的请求 这段代码是 Spring Boot 应用中配置拦截器的一个典型例子。`InterceptorRegistry` 是 Spring MVC 提供的一个接口,用于注册拦截器(`HandlerInterceptor`)并配置它们的拦截规则。 ```java @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) // 注册自定义的拦截器 .addPathPatterns("/**") // 设置拦截器拦截所有请求,包括静态资源 .excludePathPatterns("/", "/login", "/css/**", "/fonts/**", "/images/**", "/js/**", "/aa/**") // 设置不拦截的请求路径 } ``` 解释: 1. `@Override` 注解表明该方法是对父类或接口中方法的重写。 2. `public void addInterceptors(InterceptorRegistry registry)` 是一个方法,它接收一个 `InterceptorRegistry` 类型的参数。这个方法通常在配置类中实现,并且使用 `@Override` 注解标记,因为它重写了 `WebMvcConfigurer` 接口中的 `addInterceptors` 方法。 3. `registry.addInterceptor(new LoginInterceptor())` 这行代码将一个名为 `LoginInterceptor` 的拦截器添加到 Spring MVC 的拦截器链中。`LoginInterceptor` 是一个自定义的拦截器类,它可能包含一些逻辑,比如检查用户是否登录、记录日志等。 4. `.addPathPatterns("/**")` 指定拦截器应该拦截的请求路径。`"/**"` 是一个 Ant 风格的路径模式,表示匹配所有的请求路径。这意味着 `LoginInterceptor` 将对所有的请求进行拦截,包括对静态资源的请求。 5. `.excludePathPatterns` 方法用于指定拦截器不应对哪些请求路径进行拦截。在这个例子中,它排除了以下几个路径: - `"/"`:应用的根路径,通常是首页。 - `"/login"`:登录页面的路径。 - `"/css/**"`:所有 `/css` 目录下的请求,包括子目录。 - `"/fonts/**"`:所有 `/fonts` 目录下的请求。 - `"/images/**"`:所有 `/images` 目录下的请求。 - `"/js/**"`:所有 `/js` 目录下的请求。 - `"/aa/**"`:所有 `/aa` 目录下的请求。 通过这种方式,你可以灵活地控制拦截器的行为,确保它们只对需要进行特定处理的请求进行拦截,而不影响对静态资源和其他不需要拦截的请求的访问。这是一种常见的做法,用于确保安全性和性能的最佳实践,例如,通过拦截器实现用户身份验证和授权。 `#spring.mvc.static-path-pattern=/static/**` 是一个 Spring Boot 的配置属性,用于定义静态资源的映射路径。这个配置通常位于 `application.properties` 或 `application.yml` 配置文件中。 在 Spring Boot 应用中,静态资源(如 HTML、CSS、JavaScript 文件等)通常由内置的 Tomcat 或其他嵌入式服务器提供。`spring.mvc.static-path-pattern` 属性指定了应用中哪些请求应该被视为静态资源请求,并告诉 Spring Boot 从哪里提供这些资源。 这里的配置表示: - `static`:这是一个占位符,表示静态资源的根目录。 - `/**`:这是一个 Ant 风格的路径模式,表示匹配 `/static/` 路径下的所有子路径。 换句话说,这个配置告诉 Spring Boot 将所有以 `/static/` 开头的请求映射为静态资源请求。例如,如果你有一个位于 `/static/css/style.css` 的 CSS 文件,你可以通过 `/static/css/style.css` 的 URL 来访问它。 如果你的静态资源位于类路径(classpath)的 `/static` 目录下,这个配置就会自动生效。如果你希望使用不同的目录或路径模式,你可以修改这个属性的值。 例如,如果你想要从 `/resources/static` 目录提供静态资源,并希望它们可以通过 `/static/**` 路径模式访问,你可以这样配置: ```properties spring.mvc.static-path-pattern=/static/** ``` 请注意,当使用 `#` 符号时,它通常表示这是一个注释,但在这个上下文中,它可能是配置文件中的一个注释掉的行,或者是在文档中用来说明的一个示例。在实际的 `application.properties` 文件中,你应该去掉 `#` 符号以激活这个配置。