Java 允许使用JAX-RS(Jersey)和@RolesAllowed自定义HTTP状态响应

Java 允许使用JAX-RS(Jersey)和@RolesAllowed自定义HTTP状态响应,java,jersey,jax-rs,jsr250,Java,Jersey,Jax Rs,Jsr250,通过我非常简单的JAX-RS服务,我使用Tomcat和JDBC领域进行身份验证,因此我正在使用JSR250注释 问题是,我想在HTTP状态响应中返回一个自定义消息体。状态代码(403)应保持不变。例如,我的服务如下所示: @RolesAllowed({ "ADMIN" }) @Path("/users") public class UsersService { @GET @Produces(MediaType.TEXT_PLAIN) @Consumes({MediaTy

通过我非常简单的JAX-RS服务,我使用Tomcat和JDBC领域进行身份验证,因此我正在使用JSR250注释

问题是,我想在HTTP状态响应中返回一个自定义消息体。状态代码(403)应保持不变。例如,我的服务如下所示:

@RolesAllowed({ "ADMIN" })
@Path("/users")
public class UsersService {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
    public String getUsers() {
        // get users ...
        return ...;
    }
}
如果具有不同于“ADMIN”角色的用户访问该服务,我希望将响应消息更改为类似的内容(取决于媒体类型[xml/json]):


如何更改默认邮件正文?有没有一种方法可以处理(可能抛出的)异常来构建我自己的HTTP状态响应?

处理这类事情的最简单方法是抛出一个异常,并注册一个异常映射器,将其转换为您希望在这种情况下发送的消息类型。因此,假设您抛出一个
AccessDeniedException
,那么您将有一个这样的处理程序(为了清楚起见,在某些地方有完整的类名):

@javax.ws.rs.ext.Provider
公共类AccessDeniedHandler
实现javax.ws.rs.ext.ExceptionMapper{
public javax.ws.rs.core.Response to响应(AccessDeniedException exn){
//在这里构造并返回响应。。。
返回响应。状态(403)。类型(“文本/普通”)
.entity(“迷路,失败者!”).build();
}
}

注册异常映射器的方式因所使用的框架而异,但对于Jersey,只需使用
@Provider
就可以了。我会让您自己弄清楚如何生成所需的错误文档,但我确实建议您将故障作为某种HTTP错误代码处理(更为RESTful…

创建一个
ExceptionMapper
(映射
WebApplicationException
的异常),这样就可以“捕获”应用程序引发的某些异常:

@Provider
公共类MyExceptionMapper实现ExceptionMapper{
@凌驾
公共响应(WebApplicationException WeeException){
//获得初始响应
Response-Response=weeException.getResponse();
//创建自定义错误
MyError错误=。。。;
//返回自定义错误
返回Response.status(Response.getStatus()).entity(error.build();
}
}
您还需要将包添加到应用程序web.xml中以注册提供程序:


com.sun.jersey.config.property.packages
com.myapp.userservice;//分号分离
com.myapp.mappedexception

REST是基于HTTP构建的,因此您不必更改身份验证失败的默认行为。访问资源时出现403错误足以让客户机清楚地了解附加的内容


您的资源越符合HTTP,其他人就越能理解它。

问题是Jersey返回它的自定义403响应。我不能抛出
AccessDeniedException
进行授权,因为@RolesAllowed的东西可以处理这个问题。HTTP错误代码应该是一些我只想更改正文消息的代码;我知道您可以使用ApacheCXF(尽管由于我逐渐了解的原因,配置方式有所不同),因此我认为,考虑到它们都是JAX-RS引擎,而且这只是使用JAX-RS API,至少尝试一下是合理的,但我对泽西没有直接的经验,所以可能有一些意想不到的事情。我也面临着同样的问题,对我来说,这是一个完美的答案。谢谢Stefan!问题是,在不同的情况下,一个http错误可能会发生在occours上。一个是AS管理的会话超时(结果为403)。另一种可能是对rest资源的未经授权的尝试(403)。如果您必须以编程方式对这些错误做出不同的反应,这是一种自定义错误的好方法。@Lars我认为您可以在这种情况下使用自定义http代码4。第一个数字决定类别。4表示“请求包含错误语法或无法满足”,完整示例:
<error id="100">
    <message>Not allowed.</message>
</error>
HTTP Status 403 - Forbidden

type Status report
message Forbidden
description Access to the specified resource (Forbidden) has been forbidden.
Apache Tomcat/7.0.12
@javax.ws.rs.ext.Provider
public class AccessDeniedHandler
        implements javax.ws.rs.ext.ExceptionMapper<AccessDeniedException> {
    public javax.ws.rs.core.Response toResponse(AccessDeniedException exn) {
        // Construct+return the response here...
        return Response.status(403).type("text/plain")
                .entity("get lost, loser!").build();
    }
}