特殊类的异常处理/映射 [英] Exception Handling/Mapping for a particular class
问题描述
@PATH(/ user)
@GET
public Response getUser QueryParam(id)String userId){
assertNotNull(userId);
try {
User user = service.getUser(userId);
return Response.ok(user).build();
}
catch(MyOwnException moe){//基本上是400的
return Response.status(400).entity(moe.getMsg())。build();
}
catch(异常e){//意外异常
logger.debug(e.getMessage);
return Response.status(500).entity(moe.getMsg())。build();
}
}
这里的问题是我必须这样做每个REST api端点的异常处理相同。我可以为这个特定的资源做一些异常映射,以便我可以把所有的处理逻辑和日志记录在那里?
我知道我可以为运动衫中的特殊异常构建一个映射器,但是整个模块不是一个类。
Afaig你不能向资源方法注册一个 ExceptionMapper
。我已经通过实现一个 DynamicFeature
来寻求一个自定义注释,然后尝试注册一个自定义的 ExceptionMapper
与 FeatureContext
。
结果令人失望:
警告:类path.to.CustomExceptionMapper提供程序的给定合同(接口javax.ws.rs.ext.ExceptionMapper)无法绑定到资源方法。
可能不工作:
但是...
对于资源类,其实很简单。在您的 ResourceConfig
中注册您的资源类的 ExceptionMapper
。对我来说,它看起来像:
@ApplicationPath(/)
public class ApplicationResourceConfig扩展ResourceConfig {
public ApplicationResourceConfig(){
// [...]
register(YourExceptionMapper.class,YourResource.class);
// [...]
}
}
所以如果你在资源类级别上可以这样做,就这样做。
否则,您可能需要使用Aspects (但我没有看到任何理由这样做) / EM> 撞击>。例如:
Aspect
@Aspect
public class ResourceAspect {
Logger logger = [...]
private static final String RESOURCE =execution(public!static javax.ws.rs.core.Response path.to .resources .. *(..))&& @annotation(path.to.HandleMyOwnException);
@Around(RESOURCE)
public Object translateRuntimeException(ProceedingJoinPoint p)throws Throwable {
try {
return p.proceed();
} catch(MyOwnException moe){
return Response.status(400).entity(moe.getMsg())。build();
} catch(Exception e){//意外异常
logger.debug(e.getMessage);
return Response.status(500).entity(e.getMessage())。build();
}
}
}
请注意, RESOURCE
config。这里它适用于 none
方法在 path.to.resources
下返回 Response
并与$ code> HandleMyOwnException
注释结合。
HandleMyOwnException
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HandleMyOwnException {}
ResourceMethod
@GET
@PATH(/ user)
@HandleMyOwnException
public Response getUser(@QueryParam(id)String userId){
assertNotNull(userId);
return Response.ok(service.getUser(userId))。build();
}
pom.xml
< pre class =lang-xml prettyprint-override>
<! - deps - >
< dependency>
< groupId> org.aspectj< / groupId>
< artifactId> aspectjrt< / artifactId>
< version> 1.8.2< / version> <! - 或更新版本 - >
< / dependency>
<! - 构建插件 - >
< plugins>
< plugin>
< groupId> org.codehaus.mojo< / groupId>
< artifactId> aspectj-maven-plugin< / artifactId>
< version> 1.7< / version>
< configuration>
< complianceLevel> 1.8< / complianceLevel>
< showWeaveInfo> true< / showWeaveInfo>
< / configuration>
<执行>
< execution>
< goals>
< goal> compile< / goal>
< / goals>
< / execution>
< / executions>
< / plugin>
< / plugins>
< pluginManagement>
< plugins>
< plugin>
< groupId> org.eclipse.m2e< / groupId>
< artifactId>生命周期映射< / artifactId>
< version> 1.0.0< / version>
< configuration>
< lifecycleMappingMetadata>
< pluginExecutions>
< pluginExecution>
< pluginExecutionFilter>
< groupId> org.codehaus.mojo< / groupId>
< artifactId> aspectj-maven-plugin< / artifactId>
< versionRange> [1.7,)< / versionRange>
< goals>
< goal> compile< / goal>
< / goals>
< / pluginExecutionFilter>
< action>
< ignore>< / ignore>
< / action>
< / pluginExecution>
< / pluginExecutions>
< / lifecycleMappingMetadata>
< / configuration>
< / plugin>
< plugins>
< pluginManagement>
有一个愉快的一天!
〜添加更完整的pom.xml配置
〜更正了ResourceAspect中注释缺少的路径
I have resource class which itself's talks with a internal service. This resource acts a rest API for the service. The service layer can throw unexpected exceptions, thus the resource should handle those handled unexpected exceptions and log it. I am using dropwizard framework which in turns use jersey. It goes like this.
@PATH(/user)
@GET
public Response getUser(@QueryParam("id") String userId) {
assertNotNull(userId);
try {
User user = service.getUser(userId);
return Response.ok(user).build();
}
catch (MyOwnException moe) { //basically 400's
return Response.status(400).entity(moe.getMsg()).build();
}
catch (Exception e) { //unexpected exceptions
logger.debug(e.getMessage);
return Response.status(500).entity(moe.getMsg()).build();
}
}
The problem here is that i have to do this exact same exception handling for each REST api endpoint. Can i do some kind of exception mapping for this particular resource so that i can put all the handling logic and logging there? I know i can build a mapper for an particular exception in jersey, but that is for the whole module not a single class.
Afaig you can't register an ExceptionMapper
to a resource method. I've tried this by implementing a DynamicFeature
which was looking for a custom Annotation and then tried to register a custom ExceptionMapper
with the FeatureContext
.
The result was disillusioning:
WARNING: The given contract (interface javax.ws.rs.ext.ExceptionMapper) of class path.to.CustomExceptionMapper provider cannot be bound to a resource method.
Might not work:
But...
For a resource class this is in fact easy. Just register your ExceptionMapper
for your resource class within your ResourceConfig
. For me it looks like:
@ApplicationPath("/")
public class ApplicationResourceConfig extends ResourceConfig {
public ApplicationResourceConfig() {
// [...]
register(YourExceptionMapper.class, YourResource.class);
// [...]
}
}
So if you are okay with having this on resource class level, do it like this.
Otherwise you might need to use Aspects (but I don't see any reasons to do so). Example:
Aspect
@Aspect
public class ResourceAspect {
Logger logger = [...]
private static final String RESOURCE = "execution(public !static javax.ws.rs.core.Response path.to.resources..*(..)) && @annotation(path.to.HandleMyOwnException)";
@Around(RESOURCE)
public Object translateRuntimeException(ProceedingJoinPoint p) throws Throwable {
try {
return p.proceed();
} catch (MyOwnException moe) {
return Response.status(400).entity(moe.getMsg()).build();
} catch (Exception e) { //unexpected exceptions
logger.debug(e.getMessage);
return Response.status(500).entity(e.getMessage()).build();
}
}
}
Please notice, the RESOURCE
config. Here it works for none static
methods under path.to.resources
which returning Response
and are anntotated with the HandleMyOwnException
annotation.
HandleMyOwnException
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HandleMyOwnException {}
ResourceMethod
@GET
@PATH("/user")
@HandleMyOwnException
public Response getUser(@QueryParam("id") String userId) {
assertNotNull(userId);
return Response.ok(service.getUser(userId)).build();
}
pom.xml
<!-- deps -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.2</version> <!-- or newer version -->
</dependency>
<!-- build plugins -->
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<showWeaveInfo>true</showWeaveInfo>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<versionRange>[1.7,)</versionRange>
<goals>
<goal>compile</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
<plugins>
<pluginManagement>
Have a nice day!
EDITED
~ Added more complete pom.xml config
~ Corrected missing path for Annotation in ResourceAspect
这篇关于特殊类的异常处理/映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!