Spring MVC 高级特性与实战应用教程

目录

  1. 拦截器深入应用
  2. 异常处理最佳实践
  3. 文件上传下载
  4. 异步处理机制
  5. 缓存集成应用
  6. 安全防护策略
  7. 性能优化技巧
  8. 国际化实现
  9. WebSocket集成
  10. 项目实战案例
  11. 部署与运维
  12. 常见问题解决
  13. 总结

拦截器深入应用

Interceptor详解

HandlerInterceptor接口

public interface HandlerInterceptor {
   
   
    // 请求处理前调用
    boolean preHandle(HttpServletRequest request, 
                     HttpServletResponse response, 
                     Object handler);
    
    // 请求处理后,视图渲染前调用
    void postHandle(HttpServletRequest request, 
                   HttpServletResponse response, 
                   Object handler, 
                   ModelAndView modelAndView);
    
    // 整个请求完成后调用
    void afterCompletion(HttpServletRequest request, 
                         HttpServletResponse response, 
                         Object handler, 
                         Exception ex);
}

认证拦截器实现

用户认证拦截器

@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
   
   
    
    private static final Logger logger = LoggerFactory.getLogger(AuthenticationInterceptor.class);
    
    @Autowired
    private UserService userService;
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
   
   
        
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        
        logger.info("拦截请求: {} {}", method, requestURI);
        
        // 检查公开URL
        if (isPublicUrl(requestURI)) {
   
   
            return true;
        }
        
        // 验证用户登录状态
        HttpSession session = request.getSession(false);
        if (session == null) {
   
   
            redirectToLogin(request, response);
            return false;
        }
        
        User user = (User) session.getAttribute("currentUser");
        if (user == null) {
   
   
            redirectToLogin(request, response);
            return false;
        }
        
        // 检查用户状态
        if (!user.isActive()) {
   
   
            session.invalidate();
            redirectToLogin(request, response, "账户已被禁用");
            return false;
        }
        
        // 更新最后访问时间
        updateLastAccessTime(request, user);
        
        return true;
    }
    
    @Override
    public void postHandle(HttpServletRequest request, 
                          HttpServletResponse response, 
                          Object handler, 
                          ModelAndView modelAndView) throws Exception {
   
   
        
        if (modelAndView != null) {
   
   
            // 添加当前用户信息到模型
            HttpSession session = request.getSession(false);
            if (session != null) {
   
   
                User currentUser = (User) session.getAttribute("currentUser");
                if (currentUser != null) {
   
   
                    modelAndView.addObject("currentUser", currentUser);
                    modelAndView.addObject("userPermissions", getUserPermissions(currentUser));
                }
            }
            
            // 添加通用数据
            modelAndView.addObject("requestPath", request.getRequestURI());
            modelAndView.addObject("timestamp", System.currentTimeMillis());
        }
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, 
                               HttpServletResponse response, 
                               Object handler, 
                               Exception ex) throws Exception {
   
   
        
        // 记录请求完成日志
        if (ex != null) {
   
   
            logger.error("请求处理异常: {} {}", request.getMethod(), request.getRequestURI(), ex);
        } else {
   
   
            logger.debug("请求完成: {} {} - {}", 
                       request.getMethod(), 
                       request.getRequestURI(), 
                       response.getStatus());
        }
    }
    
    private boolean isPublicUrl(String uri) {
   
   
        String[] publicUrls = {
   
   
            "/", "/login", "/register", "/public", "/static", 
            "/api/public", "/health", "/error"
        };
        
        for (String publicUrl : publicUrls) {
   
   
            if (uri.startsWith(publicUrl)) {
   
   
                return true;
            }
        }
        
        return false;
    }
    
    private void redirectToLogin(HttpServletRequest request, 
                               HttpServletResponse response, 
                               String message) throws IOException {
   
   
        String loginUrl = request.getContextPath() + "/login";
        if (message != null) {
   
   
            loginUrl += "?error=" + URLEncoder.encode(message, "UTF-8");
        }
        response.sendRedirect(loginUrl);
    }
    
    private void redirectToLogin(HttpServletRequest request, 
                               HttpServletResponse response) throws IOException {
   
   
        redirectToLogin(request, response, null);
    }
    
    private void updateLastAccessTime(HttpServletRequest request, User user) {
   
   
        String userAgent = request.getHeader("User-Agent");
        String clientIp = getClientIP(request);
        
        // 异步更新用户访问信息
        CompletableFuture.runAsync(() -> {
   
   
            userService.updateLastAccess(user.getId(), userAgent, clientIp);
        });
    }
    
    private String getClientIP(HttpServletRequest request) {
   
   
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
   
   
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
   
   
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
   
   
            ip = request.getRemoteAddr();
        }
        return ip;
    }
    
    private Set<String> getUserPermissions(User user) {
   
   
        // 获取用户权限
        return userService.getUserPermissions(user.getId());
    }
}

权限控制拦截器

基于角色的权限拦截器

@Component
public class AuthorizationInterceptor implements HandlerInterceptor {
   
   
    
    @Autowired
    private PermissionService permissionService;
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
   
   
        
        // 获取当前用户
        HttpSession session = request.getSession(false);
        if (session == null) {
   
   
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        
        User user = (User) session.getAttribute("currentUser");
        if (user == null) {
   
   
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        
        // 检查权限
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        
        if (!hasPermission(user, requestURI, method)) {
   
   
            logger.warn("用户{}访问资源{}被拒绝", user.getUsername(), requestURI);
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "权限不足");
            return false;
        }
        
        return true;
    }
    
    private boolean hasPermission(User user, String uri, String method) {
   
   
        try {
   
   
            // 根据URL和HTTP方法检查权限
            return permissionService.checkPermission(user.getId(), uri, method);
        } catch (Exception e) {
   
   
            logger.error("权限检查异常", e);
            return false;
        }
    }
}

日志拦截器

请求日志拦截器

@Component
public class LoggingInterceptor implements HandlerInterceptor {
   
   
    
    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
   
   
        
   
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小凯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值