Restful后台系统搭建(四)

来源:互联网 发布:安纳金·天行者知乎 编辑:程序博客网 时间:2024/05/22 14:26

上篇文章介绍简单启动Jetty+Jersey服务,并可以通过Jmeter进行简单测试。本章再深入搭建一个Service+Action的框架,还会引入JSON解析工具。


请求的执行流程:

web前端 -> Service接口(通过@Path(xxx)访问) -> AbstractAction -> json解析成请求体req -> Action中的校验validate -> Action中的doAction -> 将返回体转换成json字符串 -> 转换成Response -> 返回给Web前端


包以及类分布:



各个类源码:

FrameworkErrorCode:

/** * 2017年4月29日 黑苹果 */package com.black.apple.framework.exception;/** * @author 黑苹果 2017年4月29日 */public enum FrameworkErrorCode{    /**     * 成功     */    OK(0),    /**     * Jersey服务启动失败     */    JERSEY_SERVICE_START_FAILED(1),    /**     * JSON解析异常     */    JSON_DECODE_EXCEPTION(2),    /**     * 参数非法     */    PARAM_INVALID(3),    /**     * 未知异常     */    UNKNOW_EXCEPTION(9999);    private int errorCode;    /**     * 错误码范围为:10000000~10009999     */    private static final int ERROR_CODE_PREFIX = 1000_0000;    private FrameworkErrorCode(int errorCode)    {        this.errorCode = ERROR_CODE_PREFIX + errorCode;    }    public String toString()    {        return String.valueOf(errorCode);    }}

AbstractAction:


/** * 2017年4月29日 黑苹果 */package com.black.apple.framework.jersey.rest.action.abs;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import javax.ws.rs.core.MediaType;import javax.ws.rs.core.Response;import javax.ws.rs.core.Response.Status;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.black.apple.framework.exception.FrameworkErrorCode;import com.black.apple.framework.exception.FrameworkException;import com.black.apple.framework.jersey.utils.JsonDecodeUtil;/** * @author 黑苹果 2017年4月29日 */public abstract class AbstractAction<S, T>{    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAction.class);    /**     * Action主方法     *      * @param content     *            json串     * @return Response     */    public Response execute(String content)    {        Response response;        try        {            S s = decodeJson(content);            validateParam(s);            T t = doAction(s);            String responseJson = encodeJson(t);            response = buildSuccessResponse(responseJson);        }        catch (FrameworkException e)        {            LOGGER.error("FrameworkException.", e);            response = buildErrorResponse(e);        }        catch (Exception e)        {            LOGGER.error("Exception.", e);            response = buildErrorResponse(e);        }        return response;    }    private Response buildErrorResponse(Exception e)    {        return Response                .status(Status.SERVICE_UNAVAILABLE)                .type(MediaType.APPLICATION_JSON)                .entity(encodeJson(new ErrorResp(FrameworkErrorCode.UNKNOW_EXCEPTION.toString(),                        FrameworkErrorCode.UNKNOW_EXCEPTION.toString()))).build();    }    private Response buildErrorResponse(FrameworkException e)    {        return Response.status(Status.SERVICE_UNAVAILABLE).type(MediaType.APPLICATION_JSON)                .entity(encodeJson(new ErrorResp(e.getErrorCode(), e.getErrorCode()))).build();    }    private Response buildSuccessResponse(String responseJson)    {        return Response.ok(responseJson, MediaType.APPLICATION_JSON).build();    }    private S decodeJson(String json) throws FrameworkException    {        return JsonDecodeUtil.decode(json, getRequestClassType());    }    @SuppressWarnings("unchecked")    private Class<S> getRequestClassType()    {        Type genType = getClass().getGenericSuperclass();        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();        Class<S> sClass = (Class<S>) params[0];        return sClass;    }    private <O> String encodeJson(O obj)    {        try        {            String json = JsonDecodeUtil.encode(obj);            return json;        }        catch (FrameworkException e)        {            LOGGER.error("json decode failed.obj={}", obj, e);        }        return StringUtils.EMPTY;    }    protected abstract T doAction(S request) throws FrameworkException;    protected abstract void validateParam(S request) throws FrameworkException;}

ErrorResp:

/** * 2017年4月29日 黑苹果 */package com.black.apple.framework.jersey.rest.action.abs;import org.apache.commons.lang3.builder.ToStringBuilder;import org.apache.commons.lang3.builder.ToStringStyle;/** * @author 黑苹果 2017年4月29日 */public class ErrorResp{    private String errorCode;    private String errorMsg;    /**     * @param errorCode     * @param errorM     */    public ErrorResp(String errorCode, String errorMsg)    {        super();        this.errorCode = errorCode;        this.errorMsg = errorMsg;    }    /**     * @return the errorCode     */    public String getErrorCode()    {        return errorCode;    }    /**     * @return the errorMsg     */    public String getErrorMsg()    {        return errorMsg;    }    /*     * (non-Javadoc)     *      * @see java.lang.Object#toString()     */    @Override    public String toString()    {        return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("errorCode", errorCode)                .append("errorMsg", errorMsg).build();    }}

TestAction:

/** * 2017年4月29日 黑苹果 */package com.black.apple.framework.jersey.rest.action;import java.util.HashMap;import java.util.Map;import com.black.apple.framework.exception.FrameworkErrorCode;import com.black.apple.framework.exception.FrameworkException;import com.black.apple.framework.jersey.rest.action.abs.AbstractAction;import com.black.apple.framework.jersey.rest.req.TestReq;import com.black.apple.framework.jersey.rest.resp.TestResp;/** * @author 黑苹果 2017年4月29日 */public class TestAction extends AbstractAction<TestReq, TestResp>{    private Map<String, String> valueMap = new HashMap<String, String>();    public TestAction()    {        valueMap.put("key1", "value1");        valueMap.put("key2", "value2");        valueMap.put("key3", "value3");    }    /*     * (non-Javadoc)     *      * @see     * com.black.apple.framework.jersey.rest.action.abs.AbstractAction#doAction     * (java.lang.Object)     */    @Override    protected TestResp doAction(TestReq request) throws FrameworkException    {        String key = request.getKey();        String value = valueMap.get(key);        TestResp resp = new TestResp();        resp.setValue(value);        return resp;    }    /*     * (non-Javadoc)     *      * @see     * com.black.apple.framework.jersey.rest.action.abs.AbstractAction#validateParam     * (java.lang.Object)     */    @Override    protected void validateParam(TestReq request) throws FrameworkException    {        String key = request.getKey();        if (valueMap.containsKey(key))        {            return;        }        throw new FrameworkException(FrameworkErrorCode.PARAM_INVALID);    }}

TestReq:

/** * 2017年4月29日 黑苹果 */package com.black.apple.framework.jersey.rest.req;/** * @author 黑苹果 2017年4月29日 */public class TestReq{    private String key;    /**     * @return the key     */    public String getKey()    {        return key;    }    /**     * @param key     *            the key to set     */    public void setKey(String key)    {        this.key = key;    }    /*     * (non-Javadoc)     *      * @see java.lang.Object#toString()     */    @Override    public String toString()    {        return "TestReq [key=" + key + "]";    }}

TestResp:

/** * 2017年4月29日 * 黑苹果 */package com.black.apple.framework.jersey.rest.resp;/** * @author 黑苹果 * 2017年4月29日 */public class TestResp{    private String value;    /**     * @return the value     */    public String getValue()    {        return value;    }    /**     * @param value the value to set     */    public void setValue(String value)    {        this.value = value;    }    /* (non-Javadoc)     * @see java.lang.Object#toString()     */    @Override    public String toString()    {        return "TestResp [value=" + value + "]";    }    }

TestService:

/** * 2017年4月29日 黑苹果 */package com.black.apple.framework.jersey.rest.service;import javax.ws.rs.POST;import javax.ws.rs.Path;import javax.ws.rs.Produces;import javax.ws.rs.core.MediaType;import javax.ws.rs.core.Response;import com.black.apple.framework.jersey.rest.action.TestAction;/** * @author 黑苹果 2017年4月29日 */@Path("framework")public class TestService{    @POST    @Path("test")    @Produces(MediaType.APPLICATION_JSON)    public Response test(String content)    {        return new TestAction().execute(content);    }}


JsonDecodeUtil:

/** *  */package com.black.apple.framework.jersey.utils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.black.apple.framework.exception.FrameworkErrorCode;import com.black.apple.framework.exception.FrameworkException;import com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;/** * @author 黑苹果 *  */public final class JsonDecodeUtil{    private static final Logger LOGGER = LoggerFactory.getLogger(JsonDecodeUtil.class);    private static ObjectMapper mapper = null;    static    {        mapper = new ObjectMapper();        mapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);    }    /**     * Json转换     *      * @param object     *            待转JSON的对象     * @return json串     * @throws TosException     */    public static <T> String encode(T object) throws FrameworkException    {        try        {            String json = mapper.writeValueAsString(object);            return json;        }        catch (JsonProcessingException e)        {            LOGGER.error("json encode failed.object={}", object, e);            throw new FrameworkException(FrameworkErrorCode.JSON_DECODE_EXCEPTION, e);        }    }    /**     * Json解析     *      * @param json     *            json串     * @param clazz     *            目标类     * @return 目标实例     */    public static <T> T decode(String json, Class<T> clazz) throws FrameworkException    {        try        {            T result = mapper.readValue(json, clazz);            return result;        }        catch (Exception e)        {            LOGGER.error("json decode failed. json={}, clazz={}", json, clazz, e);            throw new FrameworkException(FrameworkErrorCode.JSON_DECODE_EXCEPTION, e);        }    }}

log4j.properties:

log4j.rootCategory=INFO, stdout ,R log4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n log4j.appender.R=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.R.File=logs/run.loglog4j.appender.R.layout=org.apache.log4j.PatternLayoutlog4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n


Jmeter测试:


0 0
原创粉丝点击