用于凭证输入表的Bean组件
public class UserCredentials {
private String username;
private String password;
public UserCredentials() {
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
资源
@Path("auth")
public class AuthenticationResource {
@POST
@Consumes( MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@PermitAll
public Response authenticateUserName(UserCredentials credentials) {
EmployeeDao dao = new EmployeeDaoImpl();
Employee email = dao.loadEmployeeByFieldStr("email", credentials.getUsername());
if(email == null){
throw new AccessDeniedException("Non found!");
}
credentials.setUsername(email.getEmail());
Response response = Response.ok(credentials).build();
return response;
}
用于存储错误详细信息的模型
@JsonInclude( JsonInclude.Include.NON_NULL)
public class ApiErrorDetails {
private Integer status;
private String title;
private String message;
private String path;
public ApiErrorDetails() {
}
public void setStatus(Integer status) {
this.status = status;
}
public void setTitle(String title) {
this.title = title;
}
public void setMessage(String message) {
this.message = message;
}
public void setPath(String path) {
this.path = path;
}
}
ExceptionMapper
@Provider
public class AccessDeniedExceptionMapper
implements ExceptionMapper<AccessDeniedException> {
@Context
private UriInfo uriInfo;
@Override
public Response toResponse(AccessDeniedException exception) {
Response.Status status = Response.Status.UNAUTHORIZED;
ApiErrorDetails errorDetails = new ApiErrorDetails();
errorDetails.setStatus(status.getStatusCode());
errorDetails.setTitle(status.getReasonPhrase());
errorDetails.setMessage(exception.getMessage());
errorDetails.setPath(uriInfo.getAbsolutePath().getPath());
Response.ResponseBuilder statusResponse = Response.status(status);
Response.ResponseBuilder entity =
statusResponse.entity(errorDetails);
Response.ResponseBuilder type =
entity.type(MediaType.APPLICATION_JSON);
Response response = type.build();
return response;
}
}
注册配置
@ApplicationPath("/api/*")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("com.skillsimprover.restexamples.rest");
register(AuthenticationResource.class);
register(AccessDeniedExceptionMapper.class);
register(AuthenticationExceptionMapper.class);
register(DataNotFoundExceptionMapper.class);
}
}
web.xml
<servlet>
<servlet-name>Jersey REST Service</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.skillsimprover.restexamples.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
pom.xml
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.rest.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.26</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlets.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
发生 RuntimeException 时,必须由实现 ExceptionMapper 接口的Jersey类拦截。
在调试过程中,我观察到响应的形成方式以及 AccessDeniedExceptionMapper 类中错误的详细信息。 但是在客户端,我只获得状态代码,状态代码已全部设置好,而不是带有错误详细信息的 JSON 对象,这里是空括号{}。
为什么?
答案 0 :(得分:0)
在ExceptionMapper类中:
Response.Status status = Response.Status.UNAUTHORIZED;
status
是设置为Response.Status.UNAUTHORIZED
的静态最终枚举变量。设置为单个值。您不能在像这样的值上使用get方法,因为它没有getter方法。我怀疑接下来的几行:
ApiErrorDetails errorDetails = new ApiErrorDetails();
errorDetails.setStatus(status.getStatusCode());
errorDetails.setTitle(status.getReasonPhrase());
errorDetails.setMessage(exception.getMessage());
实际上什么也没做。 status.getStatusCode()
,status.getReasonPhrase()
,status.getMessage()
不返回任何内容,因为上述getter方法不是Response.status
类的一部分,而是ApiErrorDetails
类的一部分。您应该使用Response
getter方法并选择要设置的适当数据。
答案 1 :(得分:0)
Solution
资源
@Provider
@Produces( MediaType.APPLICATION_JSON )
@Consumes( MediaType.APPLICATION_JSON )
@Path("auth")
public class AuthenticationResource {
@POST
@PermitAll
@Path("username")
public Response authenticateUserName(UserCredentials credentials) {
EmployeeDao dao = new EmployeeDaoImpl();
Employee email = dao.loadEmployeeByFieldStr("email", credentials.getUsername());
if(email == null){
throw new DataNotFoundException("An object not found!!!!!!");
}
credentials.setUsername(email.getEmail());
Response response = Response.ok(credentials).build();
return response;
}
...
类例外
public class DataNotFoundException extends RuntimeException {
public DataNotFoundException(String message) {
super(message);
}
}
更改库 jersey-media-json-jackson ,而是将库 jackson-jaxrs-json-provider 。
错误详细信息类必须具有所有设置方法和获取方法。
和
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiErrorDetails {
private Integer status;
private String title;
private String message;
private String path;
public ApiErrorDetails() {
}
public void setStatus(Integer status) {
this.status = status;
}
public void setTitle(String title) {
this.title = title;
}
public void setMessage(String message) {
this.message = message;
}
public void setPath(String path) {
this.path = path;
}
public Integer getStatus() {
return status;
}
public String getTitle() {
return title;
}
public String getMessage() {
return message;
}
public String getPath() {
return path;
}
}
必须注册 JacksonJsonProvider.class
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import org.glassfish.jersey.server.ResourceConfig;
import javax.ws.rs.ApplicationPath;
@ApplicationPath("api")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
packages("com.skillsimprover.restexamples.rest");
register(JacksonJsonProvider.class);
}
}
请记住,必须将注释@ Provider 放在正在使用的自定义 ExceptionMappers 上。
@Provider
public class DataNotFoundExceptionMapper <E> implements ExceptionMapper<DataNotFoundException> {
@Context
private UriInfo uriInfo;
@Override
public Response toResponse(DataNotFoundException exception) {
return getResponseException(Response.Status.NOT_FOUND, exception);
}
private <E> Response getResponseException(Response.Status status, E exceptionSource ){
Throwable exception = (Throwable) exceptionSource;
ApiErrorDetails errorDetails = new ApiErrorDetails();
errorDetails.setStatus(status.getStatusCode());
errorDetails.setTitle(status.getReasonPhrase());
errorDetails.setMessage(exception.getMessage());
errorDetails.setPath(uriInfo.getAbsolutePath().getPath());
Response.ResponseBuilder statusResponse = Response.status(status);
Response.ResponseBuilder entity = statusResponse.entity(errorDetails);
Response.ResponseBuilder type = entity.type(MediaType.APPLICATION_JSON);
Response response = type.build();
return response;
}
}
例如,方法getResponseException()可以写入另一个类。 ClassUtils。
如果您知道如何做得更好,请在此处写下