SpringBoot 在过滤器中处理报错信息并返回 Json 数据

本贴最后更新于 1545 天前,其中的信息可能已经时移世改

最近在写一个商业的小项目,一个省的专升本报考平台,期间遇到了一个问题就是,如果在过滤器中处理错误,如何返回前端相应的 json 数据,记录一下!

首先,我们新建一个 WebMvcConfig

@Component
public class WebMvcConfig implements WebMvcConfigurer {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").
                        allowedOrigins("*"). //允许跨域的域名,可以用*表示允许任何域名使用
                        allowedMethods("PUT", "DELETE", "GET", "POST"). //允许任何方法(post、get等)
                        allowedHeaders("*"). //允许任何请求头
                        allowCredentials(true). //带上cookie信息
                        exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
            }
        };
    }

    @Bean
    @Order(1)
    //  @Order用于控制过滤器的级别,值越小级别越高
    public FilterRegistrationBean errorFilter() {
        FilterRegistrationBean frBean = new FilterRegistrationBean();
        frBean.setFilter(new ExceptionHandlerFilter());
        frBean.addUrlPatterns("*");
        return frBean;
    }
    @Bean
    @Order(2)
    //  @Order用于控制过滤器的级别,值越小级别越高
    public FilterRegistrationBean logginFilter() {
        FilterRegistrationBean frBean = new FilterRegistrationBean();
        frBean.setFilter(new LoginFilter());
        frBean.addUrlPatterns("/admin/*");
        return frBean;
    }

}

我们要做的就是用一个过滤器进行监控整个过滤链

如果,在其他过滤器中爆出指定的错误后,他会监控到,然后返回前端相应的信息

过滤器 1


 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String url = request.getRequestURI();
        String URI = request.getRequestURI();
        //打印请求信息
        if (!url.contains("static") || !url.contains(".")) {
            logger.info("请求地址为:" + url);
        }
        //如果是访问后台,必须进行登录+权限验证

        long start = System.currentTimeMillis();
        String token = request.getHeader("Authorization");
        if (token == null || token.isEmpty()) {
            throw new TokenException("Token为空");
        }

        String user = null;
        try {
            user = Jwts.parser()
                    .setSigningKey(ConstantKey.SIGNING_KEY)
                    .parseClaimsJws(token.replace("Bearer ", ""))
                    .getBody()
                    .getSubject();
            long end = System.currentTimeMillis();
            logger.info("执行时间: {}", (end - start) + " 毫秒");
            if (user != null) {
                String[] split = user.split("-")[1].split(",");
                if (Integer.parseInt(split[0]) > 2 && URI.contains("min")) {
                    throw new TokenException("权限不足...");
                }
            }
        } catch (ExpiredJwtException e) {
            logger.error("Token已过期: {} " + e);
            throw new TokenException("Token已过期");
        } catch (UnsupportedJwtException e) {
            logger.error("Token格式错误: {} " + e);
            throw new TokenException("Token格式错误");
        } catch (MalformedJwtException e) {
            logger.error("Token没有被正确构造: {} " + e);
            throw new TokenException("Token没有被正确构造");
        } catch (SignatureException e) {
            logger.error("签名失败: {} " + e);
            throw new TokenException("签名失败");
        } catch (IllegalArgumentException e) {
            logger.error("非法参数异常: {} " + e);
            throw new TokenException("非法参数异常");
        }
        //验证token是否有效(redis)
        System.out.println("user-->" + user);
        String oldToken = RedisClient.get("Token::" + user.split("-")[0]);
        System.out.println("oldToken-->" + oldToken);
        System.out.println("token-->" + token);
        if (oldToken == null || !oldToken.equals(token)) {
            throw new TokenException("token异常,请重新获取...");
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

这里省略了 init,和 destory,可以自己补上,

过滤器 2

 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        try {
            filterChain.doFilter(servletRequest, servletResponse);
        } catch (ExpiredJwtException e) {
            action(servletRequest, servletResponse, "Token已过期", 405);
        } catch (UnsupportedJwtException e) {
            action(servletRequest, servletResponse, "Token格式错误", 406);
        } catch (MalformedJwtException e) {
            action(servletRequest, servletResponse, "Token没有被正确构造", 407);
        } catch (SignatureException e) {
            action(servletRequest, servletResponse, "签名失败", 408);
        } catch (IllegalArgumentException e) {
            action(servletRequest, servletResponse, "非法参数异常", 409);
        } catch (TokenException e) {
            action(servletRequest, servletResponse, "token异常", 410);
        }
    }

    public void action(ServletRequest servletRequest, ServletResponse servletResponse, String msg, int status) throws IOException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setStatus(status);
        servletResponse.setContentType("application/json; charset=utf-8");
        servletResponse.setCharacterEncoding("UTF-8");
        String userJson = convertObjectToJson(ServerResponse.createByError(msg, "401"));
        OutputStream out = servletResponse.getOutputStream();
        out.write(userJson.getBytes("UTF-8"));
        out.flush();
    }

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    944 引用 • 1459 回帖 • 17 关注
1 操作
yscxy 在 2020-08-29 21:20:53 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...