refine code

This commit is contained in:
Mengyi Zhou 2015-04-02 19:08:45 +08:00
parent d01cfe0b24
commit f5364be740
8 changed files with 131 additions and 69 deletions

View file

@ -7,7 +7,16 @@ import java.io.Serializable;
*/
public interface Message {
/**
* Get http response status code
* reference: http://docs.oracle.com/javaee/6/api/javax/ws/rs/core/Response.Status.html
* @return
*/
int getStatus();
/**
* Get serialized object
* @return
*/
Serializable getResponse();
}

View file

@ -8,9 +8,12 @@ import javax.ws.rs.core.Response;
*/
public interface ResponseHandler {
Message generateMessage(Object object) throws Exception;
/**
* Serializing and handle the given object according to its media type
* @param object the (un)serialized object
* @param mediaType the media type, accept application/json and application/xml by default
* @return http response
* @throws Exception
*/
Response handle(Object object, MediaType mediaType) throws Exception;
MediaType getMediaType();
}

View file

@ -3,14 +3,13 @@ package com.ctrip.zeus.restful.message.impl;
import com.ctrip.zeus.exceptions.ValidationException;
import com.ctrip.zeus.restful.message.Message;
import com.ctrip.zeus.restful.message.ResponseHandler;
import com.ctrip.zeus.support.GenericSerializer;
import org.springframework.stereotype.Component;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
@ -18,45 +17,44 @@ import java.util.Set;
*/
@Component("responseHandler")
public class DefaultResponseHandler implements ResponseHandler {
private static final List<MediaType> registeredMediaTypes = registerDefault();
private final Set<MediaType> acceptedMediaTypes;
private MediaType mediaType;
private static final Set<MediaType> acceptedMediaTypes = getDefault();
private static final MediaType defaultMediaType = MediaType.APPLICATION_JSON_TYPE;
public DefaultResponseHandler() {
acceptedMediaTypes = new HashSet<>();
acceptedMediaTypes.addAll(registeredMediaTypes);
}
public Message generateMessage(Object object, String type) throws Exception {
ZeusResponse zr = new ZeusResponse();
if (object == null)
return zr;
@Override
public Message generateMessage(Object object) throws Exception {
if (object instanceof Serializable) {
return new ZeusResponse().setResponse((Serializable)object);
if (type.equals(MediaType.APPLICATION_JSON)) {
zr.setResponse(GenericSerializer.writeJson(object));
} else if (type.equals(MediaType.APPLICATION_XML)) {
zr.setResponse(GenericSerializer.writeXml(object));
} else if (object instanceof Serializable) {
zr.setResponse((Serializable)object);
} else {
throw new ValidationException("Response object cannot be serialized.");
}
throw new ValidationException("Response object is not serializable");
return zr;
}
@Override
public Response handle(Object object, MediaType mediaType) throws Exception {
Message response = generateMessage(object);
if (acceptedMediaTypes.contains(mediaType)) {
this.mediaType = mediaType;
return Response.status(response.getStatus())
.entity(response.getResponse())
.type(mediaType.getType())
.build();
if (mediaType == null) {
mediaType = defaultMediaType;
}
throw new ValidationException("Unaccepted media type: " + mediaType.getType());
if (acceptedMediaTypes.contains(mediaType)) {
Message response = generateMessage(object, mediaType.toString());
return Response.status(response.getStatus()).entity(response.getResponse())
.type(mediaType).build();
}
throw new ValidationException("Unaccepted media type: " + mediaType.toString());
}
@Override
public MediaType getMediaType() {
return mediaType;
}
private static List<MediaType> registerDefault() {
List<MediaType> list = new ArrayList<>();
list.add(MediaType.APPLICATION_JSON_TYPE);
list.add(MediaType.APPLICATION_XML_TYPE);
return list;
private static Set<MediaType> getDefault() {
Set<MediaType> set = new HashSet<>();
set.add(MediaType.APPLICATION_JSON_TYPE);
set.add(MediaType.APPLICATION_XML_TYPE);
return set;
}
}

View file

@ -1,13 +1,15 @@
package com.ctrip.zeus.restful.message.impl;
import com.ctrip.zeus.exceptions.ValidationException;
import com.ctrip.zeus.restful.message.Message;
import com.ctrip.zeus.restful.message.ResponseHandler;
import com.ctrip.zeus.restful.response.entity.ErrorMessage;
import com.ctrip.zeus.support.GenericSerializer;
import com.ctrip.zeus.util.ExceptionUtils;
import org.springframework.stereotype.Component;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.Serializable;
/**
* Created by zhoumy on 2015/4/2.
@ -15,29 +17,33 @@ import java.io.Serializable;
@Component("errorResponseHandler")
public class ErrorResponseHandler implements ResponseHandler {
private static final MediaType defaultMediaType = MediaType.APPLICATION_JSON_TYPE;
private MediaType mediaType = defaultMediaType;
private int status;
public Message generateMessage(Throwable object, String type) throws Exception {
ErrorMessage em = ExceptionUtils.getErrorMessage(object);
ErrorResponse err = new ErrorResponse();
@Override
public Message generateMessage(Object object) throws Exception {
return new ErrorResponse().setStatus(status).setResponse((Serializable)object);
if (type.equals(MediaType.APPLICATION_XML)) {
err.setResponse(GenericSerializer.writeXml(em));
} else {
err.setResponse(GenericSerializer.writeJson(em));
}
if (object instanceof Exception) {
err.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
return err;
}
@Override
public Response handle(Object object, MediaType mediaType) throws Exception {
if (mediaType != null)
this.mediaType = mediaType;
Message message = generateMessage(object);
return Response.status(message.getStatus()).entity(message.getResponse()).build();
}
if (object == null || !(object instanceof Throwable)) {
throw new ValidationException("ErrorResponseHandler only accepts Throwable object");
}
@Override
public MediaType getMediaType() {
return mediaType;
}
public void setResponseStatus(int status) {
this.status = status;
if (mediaType == null || !MediaType.APPLICATION_XML_TYPE.equals(mediaType)) {
mediaType = defaultMediaType;
}
Message message = generateMessage((Throwable) object, mediaType.toString());
return Response.status(message.getStatus()).entity(message.getResponse())
.type(mediaType).build();
}
}

View file

@ -1,18 +1,19 @@
package com.ctrip.zeus.restful.message.impl;
import com.ctrip.zeus.restful.message.Message;
import javax.ws.rs.core.Response;
import java.io.Serializable;
/**
* Created by zhoumy on 2015/4/2.
*/
public class ZeusResponse implements Message {
public static final int OK = 200;
private Serializable response;
@Override
public int getStatus() {
return OK;
return Response.Status.ACCEPTED.getStatusCode();
}
@Override

View file

@ -6,13 +6,13 @@ import com.ctrip.zeus.util.ExceptionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.glassfish.jersey.server.ContainerRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.lang.reflect.InvocationTargetException;
/**
@ -21,25 +21,34 @@ import java.lang.reflect.InvocationTargetException;
@Aspect
@Component
public class ExceptionAspect {
// @AfterThrowing(throwing = "ex",
// pointcut = "execution(* com.ctrip.zeus.service..*Repository.*(..)) || " +
// "execution(* com.ctrip.zeus.service..*Service.*(..))")
@Resource
private ErrorResponseHandler errorResponseHandler;
Logger logger = LoggerFactory.getLogger(this.getClass());
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Around("execution(* com.ctrip.zeus.restful.resource.*Resource.*(..))")
public Object interceptException(ProceedingJoinPoint point) {
Object target = point.getTarget();
String objectName = point.getSignature().getDeclaringTypeName();
String methodName = point.getSignature().getName();
try {
return point.proceed();
} catch (Throwable throwable) {
logger.error(objectName + " throws an error when calling " + methodName + ".");
Throwable cause = (throwable instanceof InvocationTargetException) ? ((InvocationTargetException) throwable).getTargetException() : throwable;
ErrorMessage err = ExceptionUtils.getErrorMessage(cause);
try {
return (Object) errorResponseHandler.handle(err, MediaType.APPLICATION_XML_TYPE);
MediaType mediaType = null;
for (Object arg : point.getArgs()) {
if (arg instanceof ContainerRequest) {
ContainerRequest cr = (ContainerRequest) arg;
mediaType = cr.getMediaType();
break;
}
}
if (mediaType == null) {
logger.warn("Request media type cannot be found - use json by default.");
}
return errorResponseHandler.handle(cause, mediaType);
} catch (Exception e) {
logger.error("Error response handler doesn't work.");
return null;
}
}

View file

@ -0,0 +1,35 @@
package com.ctrip.zeus.support;
/**
* Created by zhoumy on 2015/4/3.
*/
public class GenericSerializer {
public static final String JSON = "%#.3s";
public static final String JSON_COMPACT = "%#s";
public static final String XML = "%.3s";
public static final String XML_COMPACT = "%s";
public static String writeJson(Object object) {
return writeJson(object, true);
}
public static String writeJson(Object object, boolean pretty) {
if (pretty) {
return String.format(JSON, object);
} else {
return String.format(JSON_COMPACT, object);
}
}
public static String writeXml(Object object) {
return writeXml(object, true);
}
public static String writeXml(Object object, boolean pretty) {
if (pretty) {
return String.format(XML, object);
} else {
return String.format(XML_COMPACT, object);
}
}
}

View file

@ -15,12 +15,13 @@ public class ExceptionUtils {
}
public static String getStackTrace(Throwable throwable) {
String print = "";
StringBuilder builder = new StringBuilder();
StackTraceElement[] stackTraces = throwable.getStackTrace();
for (StackTraceElement e : stackTraces) {
print += e.getClassName();
int count = stackTraces.length > 10 ? 10 : stackTraces.length;
for (int i = 0; i < count; i++) {
builder.append(stackTraces[i].toString() + "\n");
}
return print;
return builder.toString();
}
public static ErrorMessage getErrorMessage(Throwable throwable) {