我希望将RuntimeExceptions
置于自定义json格式下,使servlet容器不会将堆栈跟踪转储到客户端。
我关注这个问题:JAX-RS (Jersey) custom exception with XML or JSON。 致电:
try {
doSomething(parameters);
}
catch(RuntimeException e) {
throw new MyCustomException(500 , e.getMessage() , Status.INTERNAL_SERVER_ERROR);
}
当我故意提供错误的参数(并触发RuntimeException
引发的doSomething()
)时,我没有看到MyCustomExceptionMapper
正常工作。相反,servlet容器转储:
The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
api.MyCustomException: (underlaying msgs)
MyCustomExceptionMapper
确实在javax.ws.rs.core.Application
:
@Override
public Set<Class<?>> getClasses()
{
Set<Class<?>> set = new HashSet<Class<?>>();
set.add(other classes);
set.add(MyCustomExceptionMapper.class);
return set;
}
我错过了什么?
非常感谢!
环境:JAX-RS,泽西服务器1.5
类规范:
class MyCustomException extends RuntimeException
@Provider
class MyCustomExceptionMapper implements ExceptionMapper<MyCustomException>
已更新:
我怀疑永远不会调用Application.getClasses()
,所以我添加了一些println消息:
@Override
public Set<Class<?>> getClasses()
{
System.out.println("\n\n\n\n ApiConfig getClasses");
}
在行动中,它永远不会显示出来!
我确信这个ApiConfig位于web.xml中:
<context-param>
<param-name>javax.ws.rs.core.Application</param-name>
<param-value>destiny.web.api.ApiConfig</param-value>
</context-param>
但为什么泽西岛似乎从不称呼它呢?
答案 0 :(得分:2)
我找到了解决方案。
我所要做的就是用Spring @Repository
注释MyCustomExceptionMapper。
删除web.xml中的部分(不需要)
<context-param>
<param-name>javax.ws.rs.core.Application</param-name>
<param-value>destiny.web.api.ApiConfig</param-value>
</context-param>
因为Spring会查找所有的@Repository并找到一个@Provider,而Jersey会使用它。
答案 1 :(得分:1)
我认为(根据我的实验)异常提供程序是通过精确的类匹配而不是通过继承匹配来查找的,因此处理RuntimeException
的异常提供程序只会如果应用程序抛出原始RuntimeException
,则触发;你向我们展示的课程并非如此。我有一些关于如何解决这个问题的理论(例如,使用自定义过滤器处理程序,或者可能使用AOP)但最终还没有。
关于你问题的后半部分,我只是不知道。我所知道的是Apache CXF(我曾与之合作的JAX-RS实现)在这方面有一些失败,因此我坚持在应用程序的Spring中手动注册我的所有@Provider
s配置。我提供经验......
答案 2 :(得分:1)
您的web.xml在web.xml中的param-name不正确,因此忽略了该设置。
正确的param名称是javax.ws.rs.Application(不是javax.ws.rs.core.Application,它是你要扩展的类)。
参见例如: docs.oracle.com/cd/E24329_01/web.1211/e24983/configure.htm#RESTF179
答案 3 :(得分:0)
您只需要在web.xml中配置servlet。您不需要将@Repository添加到ExceptionMapper。
<servlet>
<servlet-name>rest-servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>your.base.package.to.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
部署应用程序时,您可以在日志文件中看到以下行:
INFO: Scanning for root resource and provider classes in the packages:
your.base.package.to.rest
INFO: Root resource classes found:
class your.base.package.to.rest.resources.FooResource
INFO: Provider classes found:
class your.base.package.to.rest.providers.NotFoundMapper
经过测试:
答案 4 :(得分:0)
我遇到了同样的问题,web.xml中的更改,特别是在标签中解决了问题。 只需确保包含异常和异常映射器类的包不仅包含模型和资源的包 jersey.config.server.provider.packages basepackage
离。如果模型/实体的包是pkg.entity,而异常是pkg.exception,则param-value(basepackage)将是pkg。如果将basepackage设置为pkg.entity,它就不起作用......这就是我解决问题的方法。