Implementing Unified Functionality in Spring with Interceptors, AOP, Exception Handling, and Response Formatting
This article explains how to use Spring's HandlerInterceptor to implement common cross‑cutting concerns such as user login validation, unified exception handling, and standardized JSON response formats, comparing it with Spring AOP and providing step‑by‑step code examples and configuration details.
This article demonstrates how to use Spring interceptors to handle common cross‑cutting concerns in a project, including unified user login permission verification, exception handling, and data format responses.
It first compares three approaches for login validation: the original servlet‑based check, Spring AOP, and finally Spring's HandlerInterceptor, highlighting the limitations of AOP (e.g., difficulty obtaining HttpServletRequest).
HttpSession session = req.getSession(false);
if (session == null) {
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write("用户未登陆,请登录!!");
return;
}
User user = (User) session.getAttribute("user");
if (user == null) {
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write("用户未登陆,请登录!!");
return;
}Using Spring AOP, a @Aspect is defined with a pointcut and an @Around advice that manually retrieves the request via RequestContextHolder , but this adds complexity.
@Component
@Aspect
public class LoginAspect {
@Pointcut("execution(* com.chenshu.intercept_demo.controller..*.*(..))")
private void myPointcut() {}
@Around("myPointcut()")
public String loginValidate(ProceedingJoinPoint joinPoint) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession(false);
if (session == null) {
return "用户未登陆,请登录!!";
}
String username = (String) session.getAttribute("user");
if (username == null) {
return "用户未登陆,请登录!!";
}
return (String) joinPoint.proceed();
}
}To overcome these drawbacks, the article introduces Spring's HandlerInterceptor , which can intercept requests before they reach controllers, allowing easy access to request/response objects and straightforward configuration.
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("user") != null) {
return true;
}
response.setStatus(401);
return false;
}
}The interceptor is registered via a WebMvcConfigurer implementation:
@Configuration
public class MyMvcConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/user/login", "/user/reg");
}
}Next, the article covers unified exception handling using @ControllerAdvice and @ExceptionHandler , returning a consistent JSON structure with error codes and messages.
@ResponseBody
@ControllerAdvice
public class ExceptionAdvice {
@ExceptionHandler(Exception.class)
public HashMap
handleException(Exception e) {
HashMap
retMap = new HashMap<>();
retMap.put("code", "-1");
retMap.put("msg", e.getMessage());
return retMap;
}
@ExceptionHandler(ArithmeticException.class)
public HashMap
handleArithmetic(ArithmeticException e) {
HashMap
retMap = new HashMap<>();
retMap.put("code", "-2");
retMap.put("msg", e.getMessage());
return retMap;
}
}Finally, a unified response format is achieved with ResponseBodyAdvice , wrapping successful responses in a JSON object containing code , msg , and body . Special handling for String responses uses Jackson's ObjectMapper to avoid type‑casting errors.
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice
{
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return !returnType.getParameterType().equals(HashMap.class);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
HashMap
retMap = new HashMap<>();
retMap.put("code", "200");
retMap.put("msg", "");
retMap.put("body", body);
if (body instanceof String) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(retMap);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
return retMap;
}
}The article concludes that using Spring interceptors together with @ControllerAdvice and ResponseBodyAdvice provides a clean, maintainable way to implement login validation, unified exception handling, and standardized response structures in backend applications.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.