目录
一、实现过滤器
过滤器是Servlet规范的一部分,用于在请求到达Servlet之前或响应发送给客户端之后进行预处理和后处理。
1、创建过滤器
首先,需要创建一个实现javax.servlet.Filter接口的类,这个接口包含三个方法:init、doFilter和destroy:
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化代码,过滤器启动时执行
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// 在请求继续之前执行的代码
System.out.println("Before processing request");
// 继续执行过滤链中的下一个过滤器或目标资源(如Servlet)
chain.doFilter(request, response);
// 在请求处理之后执行的代码
System.out.println("After processing request");
}
@Override
public void destroy() {
// 清理代码,过滤器销毁时执行
}}
2、注册过滤器
在Spring Boot中,使用FilterRegistrationBean来注册过滤器:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter> myFilterRegistration() {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new MyFilter());
registration.addUrlPatterns("/api/*"); // 指定过滤器应用的URL模式
return registration;
}
}
3. 使用注解配置过滤器
如果使用的是Spring MVC或Spring Boot,可以通过在过滤器类上使用@Component注解来自动注册过滤器:
import javax.servlet.annotation.WebFilter;
import org.springframework.stereotype.Component;
@Component@WebFilter(urlPatterns = "/api/*")
public class MyFilter implements Filter {
// 实现init、doFilter和destroy方法
}
4. 在Web.xml中配置过滤器
在传统的Java EE应用中,可以在web.xml文件中配置过滤器:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.example.MyFilter</filter-class></filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
</filter>
5. 过滤器的执行顺序
过滤器的执行顺序取决于它们在web.xml中的声明顺序,或者在Spring配置中的注册顺序。如果想控制多个过滤器的执行顺序,可以使用setOrder方法:
registration.setOrder(1); // 数字越小,优先级越高
6. 过滤器的链式调用
过滤器可以形成一个链,一个请求会按顺序通过多个过滤器。在doFilter方法中,通过调用chain.doFilter(request, response)来传递请求到下一个过滤器或目标资源。
二、实现拦截器
在Spring框架中,拦截器(Interceptor)用于在处理HTTP请求之前、之后或请求处理过程中进行拦截,以实现如身份验证、日志记录、权限检查等功能。
1、创建拦截器
创建一个实现HandlerInterceptor接口的类。这个接口包含三个方法:preHandle、postHandle和afterCompletion:
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 在控制器执行之前调用
System.out.println("Pre Handle");
// 如果返回true,继续流程;如果返回false,停止流程
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 在控制器执行之后调用
System.out.println("Post Handle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 请求完成后调用
System.out.println("Request and Response is completed");
}
}
2. 注册拦截器
在Spring MVC配置中注册拦截器。如果你使用的是Spring Boot,可以通过添加一个配置类来实现:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 指定拦截器应用的URL模式
registry.addInterceptor(myInterceptor).addPathPatterns("/api/*");
}
}
3. 使用注解方式注册拦截器
如果你的拦截器不需要依赖注入,你也可以使用@Component注解和WebMvcConfigurer接口来自动注册拦截器:
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/*");
}
}
4. 拦截器的执行顺序
拦截器的执行顺序可以通过实现Ordered接口或使用@Order注解来控制:
public class MyInterceptor implements HandlerInterceptor, Ordered {
@Override
public int getOrder() {
return 1; // 数字越小,优先级越高
}
// 实现其他方法
}
5. 拦截器的匹配规则
拦截器可以通过addPathPatterns方法指定匹配的URL模式,也可以通过excludePathPatterns方法指定排除的URL模式。
6. 拦截器的高级使用
拦截器不仅可以用于简单的日志记录和权限检查,还可以用于复杂的业务逻辑,如请求预处理、响应后处理等。
三、实现全局异常捕获
在Spring框架中,实现全局异常处理的一种常见方法是使用@ControllerAdvice注解。这个注解允许定义一个类来全局处理异常,而不需要在每个控制器中单独处理。
1、创建全局异常处理器
使用@ControllerAdvice注解创建一个全局异常处理器类。可以在这个类中定义一个或多个方法来处理不同类型的异常。
使用@ControllerAdvice和@ExceptionHandler:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseEntity<String> handleException(Exception e) {
// 可以根据不同的异常类型返回不同的HTTP状态码
return new ResponseEntity<>("An error occurred: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
// 可以添加更多的异常处理方法
@ExceptionHandler(NullPointerException.class)
@ResponseBody
public ResponseEntity<String> handleNullPointerException(NullPointerException e) {
return new ResponseEntity<>("Null pointer error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
}
// 处理特定业务异常
@ExceptionHandler(CustomBusinessException.class)
@ResponseBody
public ResponseEntity<String> handleCustomBusinessException(CustomBusinessException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.FORBIDDEN);
}
}
2. 使用@ExceptionHandler注解
在全局异常处理器类中,使用@ExceptionHandler注解来指定哪些异常应该由哪个方法处理。可以为通用异常和特定异常类型定义不同的处理方法。
3. 返回适当的响应
在异常处理方法中可以构造一个适当的响应来通知客户端发生了错误。通常,这包括一个错误消息和一个HTTP状态码。使用ResponseEntity来构建这样的响应。
4. 记录异常信息
在异常处理方法中,可以将异常信息记录到日志中,这对于调试和监控应用程序非常有用。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseEntity<String> handleException(Exception e) {
logger.error("An error occurred", e);
return new ResponseEntity<>("An error occurred:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
5. 配置多个全局异常处理器
如果有多个@ControllerAdvice类,Spring会根据它们的@Order或@Priority注解来决定处理异常的顺序。如果没有这些注解,Spring会按照类名的字母顺序来处理。