Jersey ExceptionMapper 不映射异常
Posted
技术标签:
【中文标题】Jersey ExceptionMapper 不映射异常【英文标题】:Jersey ExceptionMapper doesn't map exceptions 【发布时间】: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'
【问题讨论】:
【参考方案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】:我遇到了同样的问题
刚才在<init-param>
的<param-value>
标签中提到了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);
【讨论】:
以上是关于Jersey ExceptionMapper 不映射异常的主要内容,如果未能解决你的问题,请参考以下文章
使用 Jersey 的 ExceptionMapper 映射 Shiro 的 AuthenticationException
JAX-RS自定义ExceptionMapper不拦截RuntimeException