【问题标题】:@ExceptionHandler not being triggered?@ExceptionHandler 没有被触发?
【发布时间】:2018-12-03 19:08:02
【问题描述】:

我在这个主题上看到了其他重复的堆栈溢出问题,但似乎没有一个能复制我的情况。

当抛出异常时,我的 ExceptionHandler 类不会将其拾取并返回 json,而是将带有异常详细信息的默认 500 代码作为 HTML 返回给客户端。我已经检查过了,Spring 确实初始化了我的 ExceptionHandler 类,但无论出于何种原因,这些方法都没有被调用。

GlobalExceptionHandler.class:

@ControllerAdvice
@RequestMapping(produces = "application/json")
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);

public GlobalExceptionHandler(){
    LOG.debug("This gets called in logs...");
}

@ExceptionHandler({CustomException.class})
public @ResponseBody ResponseEntity<Object> handleCustomException(HttpServletRequest request,
                                             CustomException ex) {

    LOG.debug("This does not get called...");
    Map<String, Object> response = new HashMap<>();

    response.put("message", ex.getMessage());
    return new ResponseEntity<>(response, ex.getCode());
}
}

CustomException.class:

public class CustomException extends RuntimeException{

private HttpStatus code;
private String message;

public CustomException(final HttpStatus code, final String message){

    this.code = code;
    this.message = message;
}


/**
 * Gets message.
 *
 * @return Value of message.
 */
public String getMessage() {
    return message;
}

/**
 * Sets new code.
 *
 * @param code
 *         New value of code.
 */
public void setCode(HttpStatus code) {
    this.code = code;
}

/**
 * Sets new message.
 *
 * @param message
 *         New value of message.
 */
public void setMessage(String message) {
    this.message = message;
}

/**
 * Gets code.
 *
 * @return Value of code.
 */
public HttpStatus getCode() {
    return code;
}
}

此处触发异常处理程序:

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

@Autowired
private JwtTokenProvider tokenProvider;

@Autowired
private CustomUserDetailsService customUserDetailsService;

private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain
        filterChain) throws ServletException, IOException {

    logger.debug("Filtering request for JWT header verification");

    String jwt = getJwtFromRequest(request);

    logger.debug("JWT Value: {}", jwt);

    if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
        String username = tokenProvider.getUserIdFromJWT(jwt);

        UserDetails userDetails = customUserDetailsService.loadUserByUsername(username);
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken
                (userDetails, null, userDetails.getAuthorities());
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

        SecurityContextHolder.getContext().setAuthentication(authentication);
    } else {

        logger.error("{}", new CustomException(HttpStatus.UNAUTHORIZED, "No Valid JWT Token Provided"));
        throw new CustomException(HttpStatus.UNAUTHORIZED, "No Valid JWT Token Provided");
    }

    filterChain.doFilter(request, response);
}
}

我在网络配置中有所有必要的属性:

<!--<context:annotation-config />-->
<tx:annotation-driven/>
<context:component-scan base-package="com.app.controller"/>

我的 Web.xml:

<web-app>

<!-- For web context -->
<servlet>
    <servlet-name>appDispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>appDispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!-- Logging -->
<context-param>
    <param-name>logbackConfigLocation</param-name>
    <param-value>/WEB-INF/classes/logback.xml</param-value>
</context-param>

<filter>
    <filter-name>jwtFilter</filter-name>
    <filter-class>com.app.controller.security.filters.JwtAuthenticationFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>jwtFilter</filter-name>
    <servlet-name>appDispatcher</servlet-name>
</filter-mapping>

</web-app>

一直在讨论这个问题..

这就是我得到的全部:

【问题讨论】:

  • @RequestMapping(produces = "application/json") 不应在建议中使用。异常在哪里抛出?
  • 啊,我试试看..
  • 运气不好...即使配置了 ...
  • 你在哪里抛出这个异常?
  • NiVer 我在描述中包含了这个...干杯

标签: spring spring-mvc spring-boot spring-security spring-data


【解决方案1】:

@ControllerAdvice 未捕获您的异常,因为您是从使用 @Component 而不是 @Controller 注释的类中抛出的。

根据文档:

@Component 对声明类的特殊化 @ExceptionHandler、@InitBinder 或 @ModelAttribute 方法 在多个 @Controller 类之间共享。

您可以找到更完整的参考here

【讨论】:

  • 谢谢。那么哪种方法最适合从不同层(而不是控制器)调用异常处理程序?
  • 即使我用@Controller注释过滤器类仍然没有运气
  • 另一个问题是过滤器在与您的控制器进行实际交互之前执行,这就是您看不到它的原因。您应该考虑不同的方式来处理过滤器的异常。
  • 我已经检查了我是否直接在我发送其余请求的控制器中抛出异常,它仍然作为 HTML 返回并且不会触发 ExceptionHandler
  • 好的,我现在明白了...过滤器仍在被调用。您能否修复您发布的完整参考链接以获取更多信息。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-22
  • 2012-06-03
  • 2019-11-07
  • 2018-09-01
  • 2021-04-23
  • 2019-01-30
  • 2020-08-15
相关资源
最近更新 更多