我想得到 JSON 异常而不是 505 默认异常
I want to get JSON exception instead of 505 default exception
我正在 java 8 中创建 Messenger 应用程序并使用 REST。
我在我的应用程序中添加了触发消息。
我想得到一个 JSON 响应作为用户定义的异常而不是 apache tomcat 抛出的默认异常 tomcat。
例如,我的地图中有两条消息,id = 1 和 2。
如果我尝试通过提供 messageid 67 来获取消息,它应该会抛出异常。
apache tomcat 以 HTML 格式抛出异常,这不是我的要求,相反我想要 JSON 格式的用户定义异常。
我正在收到我定义的自定义消息,但不是 JSON 格式。
我正在使用 Postman。
这是我的代码。
MessageService.java
package com.diwakar.messenger.service;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import com.diwakar.messenger.database.DatabaseClass;
import com.diwakar.messenger.exception.DataNotFoundException;
import com.diwakar.messenger.model.Message;
public class MessageService {
private Map<Long, Message> messages = DatabaseClass.getMessages();
public MessageService() {
messages.put(1L, new Message(1L, "Hello World!", "Diwakar"));
messages.put(2L, new Message(2L, "Hello Jersey!", "Diwakar"));
}
public List<Message> getAllMessages() {
return new ArrayList<Message>(messages.values());
}
public List<Message> getAllMessagesForYear(int year) {
List<Message> messagesForYear = new ArrayList<>();
Calendar cal = Calendar.getInstance();
for (Message message : messages.values()) {
cal.setTime(message.getCreated());
if (cal.get(Calendar.YEAR) == year) {
messagesForYear.add(message);
}
}
return messagesForYear;
}
public List<Message> getAllMessagesPaginated(int start, int size) {
List<Message> list = new ArrayList<Message>(messages.values());
if (start + size > list.size()){
return new ArrayList<Message>();
}
return list.subList(start, start + size);
}
public Message getMessage(long id) {
Message message = messages.get(id);
if (message == null) {
throw new DataNotFoundException("Message with id : " + id + " not found. ");
}
return message;
}
public Message addMessage(Message message) {
message.setId(messages.size() + 1);
messages.put(message.getId(), message);
return message;
}
public Message updateMessage(Message message) {
if (message.getId() <= 0) {
return null;
}else {
messages.put(message.getId(), message);
return message;
}
}
public Message removeMessage(long id) {
return messages.remove(id);
}
}
DataNotFoundException.java
package com.diwakar.messenger.exception;
public class DataNotFoundException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = 1L;
public DataNotFoundException(String message) {
super(message);
}
}
DataNotFoundExceptionMapper.java
package com.diwakar.messenger.exception;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import com.diwakar.messenger.model.ErrorMessage;
@Provider
public class DataNotFoundExceptionMapper implements ExceptionMapper<DataNotFoundException> {
@Override
public Response toResponse(DataNotFoundException ex) {
ErrorMessage errorMessage = new ErrorMessage(ex.getMessage(), 404, "http://www.google.com");
return Response.status(Status.NOT_FOUND).entity(errorMessage).build();
}
}
ErrorMessage.java
package com.diwakar.messenger.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ErrorMessage {
private String errorMessage;
private int errorCode;
private String documentation;
public ErrorMessage() {
}
public ErrorMessage(String errorMessage, int errorCode, String documentation){
super();
this.errorMessage = errorMessage;
this.errorCode = errorCode;
this.documentation = documentation;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getDocumentation() {
return documentation;
}
public void setDocumentation(String documentation) {
this.documentation = documentation;
}
}
您必须 return 有效负载为序列化异常数据的 200 响应,然后您的客户端代码需要能够区分 'valid' 200 和'error' 200,可能也是负载中的标志。
我不是 100% 支持 java 和 tomcat,但硬抛出服务器异常通常会创建一个 500 响应,该响应被包装但是有问题的 REST 框架决定这样做,通常没有敏感的异常数据。取得控制权的唯一方法是 return 带有自定义负载数据的 200 响应。
还要记住,您的操作方式可能会将异常详细信息暴露给您通常不希望的客户端(java脚本)。
我得到了答案...
我们可以使用 com.diwakar.messenger 或(com.diwakar.messenger.resources 和 com.diwakar.messenger.exception)来代替 com.diwakar.messenger.resources。
这个 init-parm jersey.config.server.provider.packages 说的是 Jersey 应该扫描命名包以查找 @Path 注释资源 class 和 @Provider 注释提供者 classes 并注册它们。
我们只列出了资源包 com.diwakar.messenger.resources,但 ExceptionMapper 在不同的包中。默认行为是递归扫描,也意味着子包。因此,如果我们改写 com.diwakar.messenger,您将同时访问资源包和异常包。或者我们可以列出两个包,用逗号或分号分隔。两种方法都行
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<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.diwakar.messenger</param-value>
<!-- <param-value>com.diwakar.messenger.resources</param-value> -->
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
</web-app>
我正在 java 8 中创建 Messenger 应用程序并使用 REST。 我在我的应用程序中添加了触发消息。
我想得到一个 JSON 响应作为用户定义的异常而不是 apache tomcat 抛出的默认异常 tomcat。
例如,我的地图中有两条消息,id = 1 和 2。 如果我尝试通过提供 messageid 67 来获取消息,它应该会抛出异常。
apache tomcat 以 HTML 格式抛出异常,这不是我的要求,相反我想要 JSON 格式的用户定义异常。
我正在收到我定义的自定义消息,但不是 JSON 格式。
我正在使用 Postman。
这是我的代码。
MessageService.java
package com.diwakar.messenger.service;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import com.diwakar.messenger.database.DatabaseClass;
import com.diwakar.messenger.exception.DataNotFoundException;
import com.diwakar.messenger.model.Message;
public class MessageService {
private Map<Long, Message> messages = DatabaseClass.getMessages();
public MessageService() {
messages.put(1L, new Message(1L, "Hello World!", "Diwakar"));
messages.put(2L, new Message(2L, "Hello Jersey!", "Diwakar"));
}
public List<Message> getAllMessages() {
return new ArrayList<Message>(messages.values());
}
public List<Message> getAllMessagesForYear(int year) {
List<Message> messagesForYear = new ArrayList<>();
Calendar cal = Calendar.getInstance();
for (Message message : messages.values()) {
cal.setTime(message.getCreated());
if (cal.get(Calendar.YEAR) == year) {
messagesForYear.add(message);
}
}
return messagesForYear;
}
public List<Message> getAllMessagesPaginated(int start, int size) {
List<Message> list = new ArrayList<Message>(messages.values());
if (start + size > list.size()){
return new ArrayList<Message>();
}
return list.subList(start, start + size);
}
public Message getMessage(long id) {
Message message = messages.get(id);
if (message == null) {
throw new DataNotFoundException("Message with id : " + id + " not found. ");
}
return message;
}
public Message addMessage(Message message) {
message.setId(messages.size() + 1);
messages.put(message.getId(), message);
return message;
}
public Message updateMessage(Message message) {
if (message.getId() <= 0) {
return null;
}else {
messages.put(message.getId(), message);
return message;
}
}
public Message removeMessage(long id) {
return messages.remove(id);
}
}
DataNotFoundException.java
package com.diwakar.messenger.exception;
public class DataNotFoundException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = 1L;
public DataNotFoundException(String message) {
super(message);
}
}
DataNotFoundExceptionMapper.java
package com.diwakar.messenger.exception;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import com.diwakar.messenger.model.ErrorMessage;
@Provider
public class DataNotFoundExceptionMapper implements ExceptionMapper<DataNotFoundException> {
@Override
public Response toResponse(DataNotFoundException ex) {
ErrorMessage errorMessage = new ErrorMessage(ex.getMessage(), 404, "http://www.google.com");
return Response.status(Status.NOT_FOUND).entity(errorMessage).build();
}
}
ErrorMessage.java
package com.diwakar.messenger.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ErrorMessage {
private String errorMessage;
private int errorCode;
private String documentation;
public ErrorMessage() {
}
public ErrorMessage(String errorMessage, int errorCode, String documentation){
super();
this.errorMessage = errorMessage;
this.errorCode = errorCode;
this.documentation = documentation;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getDocumentation() {
return documentation;
}
public void setDocumentation(String documentation) {
this.documentation = documentation;
}
}
您必须 return 有效负载为序列化异常数据的 200 响应,然后您的客户端代码需要能够区分 'valid' 200 和'error' 200,可能也是负载中的标志。
我不是 100% 支持 java 和 tomcat,但硬抛出服务器异常通常会创建一个 500 响应,该响应被包装但是有问题的 REST 框架决定这样做,通常没有敏感的异常数据。取得控制权的唯一方法是 return 带有自定义负载数据的 200 响应。
还要记住,您的操作方式可能会将异常详细信息暴露给您通常不希望的客户端(java脚本)。
我得到了答案...
我们可以使用 com.diwakar.messenger 或(com.diwakar.messenger.resources 和 com.diwakar.messenger.exception)来代替 com.diwakar.messenger.resources。
这个 init-parm jersey.config.server.provider.packages 说的是 Jersey 应该扫描命名包以查找 @Path 注释资源 class 和 @Provider 注释提供者 classes 并注册它们。
我们只列出了资源包 com.diwakar.messenger.resources,但 ExceptionMapper 在不同的包中。默认行为是递归扫描,也意味着子包。因此,如果我们改写 com.diwakar.messenger,您将同时访问资源包和异常包。或者我们可以列出两个包,用逗号或分号分隔。两种方法都行
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<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.diwakar.messenger</param-value>
<!-- <param-value>com.diwakar.messenger.resources</param-value> -->
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
</web-app>