【问题标题】:Jersey ExceptionMapper doesn't map exceptionsJersey ExceptionMapper 不映射异常
【发布时间】:2015-03-14 23:57:23
【问题描述】:

我的 Spring Boot + Jersey REST 服务没有按预期工作。

在 UserController 中引发了 EmailExistsException,但我只收到错误 500。一直。而且我的异常没有被记录。

我怀疑异常处理存在一些配置问题,但不知道在哪里进行设置。有什么建议吗?

@POST
@Path("register")
@Produces(MediaType.APPLICATION_JSON)
public Response register(NewUserPayload newUserPayload) throws EmailExistsException, MessagingException

EmailExistsExceptionMapper

@Provider
public class EmailExistsExceptionMapper extends AbstractExceptionMapper       implements
    ExceptionMapper<EmailExistsException>
{
@Override
public Response toResponse(EmailExistsException e)
{
    ResponseEntity re = new ResponseEntity(org.springframework.http.HttpStatus.BAD_REQUEST);

    return this.errorResponse(HttpStatus.BAD_REQUEST_400, re, e);
}
}

AbstractExceptionMapper

@Slf4j
public abstract class AbstractExceptionMapper
{
protected Response errorResponse(int status, ResponseEntity responseEntity, Throwable t)
{
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    t.printStackTrace(pw);
    log.error(sw.toString()); // logging stack trace.

    return customizeResponse(status, responseEntity);
}

private Response customizeResponse(int status, ResponseEntity responseEntity)
{
    return Response.status(status).entity(responseEntity).build();
}
}

build.gradle

compile("org.springframework.boot:spring-boot-starter-web") {
    exclude module: 'spring-boot-starter-tomcat'
}
compile "org.springframework.boot:spring-boot-starter-jetty"
compile "org.springframework.boot:spring-boot-starter-security"
compile "org.springframework.boot:spring-boot-starter-aop"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "org.springframework.boot:spring-boot-starter-thymeleaf"
compile "org.springframework.boot:spring-boot-starter-jersey"
compile 'org.springframework.boot:spring-boot-starter-mail'

【问题讨论】:

    标签: spring web-services rest jersey spring-boot


    【解决方案1】:

    解决了我的问题的答案:

    我已经放了 packages("package.name");这是我的根包名,异常映射器就像一个魅力。

    @Component
    @ApplicationPath("/api")
    public class JerseyConfig extends ResourceConfig
    {
    public JerseyConfig()
    {
        packages("package.name");
        register(UserController.class);
        register(TimezoneController.class);
    }
    }
    

    【讨论】:

    • jersey documentation 中没有关于此配置的信息。 package 声明会避免你声明控制器吗?
    • 我在网上的一些代码 sn-p 中找到了它。我现在在 Scala,所以无法告诉你更多关于它的信息。
    • 谢谢!事实证明,您必须明确地 register(YourExceptionMapper.class) 或通过 packages("YourExceptionMapperPackage") 将其放入扫描包中。在找到您的答案之前,我花了几个小时试图弄清楚这一点。
    【解决方案2】:

    您是否已将自定义 ExceptionMapper 配置为 jax-rs 提供程序,并且您确定您的异常被包装到 EmailExistsException 中吗?你可能需要看看这篇文章。

    JAX-RS using exception mappers

    【讨论】:

    • 它有一个 @Provider 注释,是的,我确信它会被包装和抛出。另一件事是,当我尝试在 EmailExistsExceptionMapper 中放置断点时,它在调试模式下的 IDEA 中并不存在。似乎不知何故它没有被使用?可能缺少一些配置,但在哪里?
    【解决方案3】:

    我遇到了同样的问题

    刚才在&lt;init-param&gt;&lt;param-value&gt;标签中提到了web.xml文件中的根包

    然后它开始像魅力一样工作

    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.two95.restful</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    

    【讨论】:

      【解决方案4】:

      如果您使用 ExceptionMapper,则必须注册您的异常映射器:

      @Component
      @Provider
      public class ApiApplicationExceptionMapper implements ExceptionMapper<Exception> {
      
          @Override
          public Response toResponse(Exception exception) {
             ...
          }
      }
      

      在 Jersey 配置类中,扫描带有 @Path 注释的 Jersey Endpoint 类和带有 @Provider 注释的自定义异常映射器进行注册:

      @Configuration
      public class JerseyConfig extends ResourceConfig {
      
          @Autowired
          ApplicationContext applicationContext;
      
          @PostConstruct
          public void init() {
              this.registerEndpoints();
              this.registerExceptionMappers();
          }
      
          private void registerEndpoints() {
              Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Path.class);
              for (Object apiClass : beans.values()) {
                  logger.info("Jersey register: " + apiClass.getClass().getName());
                  register(apiClass);
              }
          }
      
          private void registerExceptionMappers() {
              Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Provider.class);
              for (Object exceptionMapper : beans.values()) {
                  logger.info("Jersey exception mapper register: " + exceptionMapper.getClass().getName());
                  register(exceptionMapper);
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2017-01-01
        • 1970-01-01
        • 2015-10-28
        • 2013-11-18
        • 1970-01-01
        • 2015-03-29
        • 2012-05-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多