Spring自定義注解實現(xiàn)json參數(shù)傳遞

實現(xiàn)(POST,GET)傳參自動轉(zhuǎn)換成Json對象,所有參數(shù)為Json格式然后再Base64加密

Spring Request詳解:

Spring 的DispatcherServlet 實現(xiàn)了Servlet方法体斩,來處理一次請求

DispatcherServlet主要是執(zhí)行了兩個方法doService(HttpServletRequest request, HttpServletResponse response)晚伙,doDispatch(HttpServletRequest request, HttpServletResponse response)

在doDispatch方法中

    // Determine handler for the current request.

    mappedHandler = getHandler(processedRequest);

獲取當前請求的handler,也就是獲取到執(zhí)行當前request的bean拷窜。

HandlerMapping有多個實現(xiàn)开皿,具體的還需自己看下實現(xiàn)

    // Determine handler adapter for the current request.

    HandlerAdapterha = getHandlerAdapter(mappedHandler.getHandler());

獲取到當前請求的HandlerAdapter

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    for (HandlerMapping hm : this.handlerMappings) {
        if (logger.isTraceEnabled()) {
            logger.trace(
                    "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
        }
        HandlerExecutionChain handler = hm.getHandler(request);
        if (handler != null) {
            return handler;
        }
    }
    return null;
}

獲取ha.supports(handler) 返回為true的HandlerAdapter

eg.
如果這個bean實現(xiàn)了HttpRequestHandler接口則返回HttpRequestHandlerAdapter

@Override
public boolean supports(Object handler) {
    return (handler instanceof HttpRequestHandler);
}

如果這個bean實現(xiàn)了Controller接口則返回SimpleControllerHandlerAdapter

@Override
public boolean supports(Object handler) {
    return (handler instanceof Controller);
}

目前常用的方式是通過@Controller、@RequestMapping和Spring配置中添加<context:component-scan/>

此時使用的是RequestMappingHandlerAdapter

RequestMappingHandlerAdapter 主要實現(xiàn)了請求參數(shù)的封裝處理篮昧,返回參數(shù)的封裝處理赋荆,支持注入argumentResolvers、returnValueHandlers懊昨、messageConverters等來實現(xiàn)擴展

RequestMappingHandlerAdapter.invokeHandlerMethod.invokeAndHandle.invokeForRequest.getMethodArgumentValues


if (this.argumentResolvers.supportsParameter(parameter)) {
    try {
        args[i] = this.argumentResolvers.resolveArgument(
                parameter, mavContainer, request, this.dataBinderFactory);
        continue;
    }
    catch (Exception ex) {
        if (logger.isDebugEnabled()) {
            logger.debug(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
        }
        throw ex;
    }
}

首先會調(diào)用argumentResolver的supportsParameter判斷是否可用窄潭,然后再執(zhí)行resolveArgument方法

SpecialArgumentsResolver,自定義argumentResolver

通過上面我們可以發(fā)現(xiàn)酵颁,基于自定義注解實現(xiàn)Json的參數(shù)傳遞嫉你,需要實現(xiàn)自定的argumentResolver并注入到RequestMappingHandlerAdapter中

  1. 實現(xiàn)自定義Json注解

/**
 * Created by zhaoqi on 2016/5/5.
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Json {

    Class[] types() default java.lang.Object.class;

    String path() default "";
}


  1. spring配置文件增加自定義argumentResolver

注意,如果是注入的argumentResolver躏惋,會覆蓋默認的argumentResolver幽污。

<!--RequestMappingHandlerAdapter加入自定義ArgumentsResolver-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="synchronizeOnSession" value="true" />
    <property name="argumentResolvers">
        <list>
            <bean class="com.zhaoqi.component.annotation.SpecialArgumentsResolver"/>
        </list>
    </property>
    <property name="messageConverters">
        <list>
            <ref bean="stringConverter" />
            <ref bean="jsonConverter" />
        </list>
    </property>
</bean>

如果不想覆蓋默認的argumentResolver,請注入customArgumentResolvers簿姨。


// Custom arguments

if(getCustomArgumentResolvers() !=null) {

    resolvers.addAll(getCustomArgumentResolvers());

}
  1. 實現(xiàn)SpecialArgumentsResolver

/**
 * Created by zhaoqi on 2016/5/6.
 */
public class SpecialArgumentsResolver implements HandlerMethodArgumentResolver {
    @Resource
    DotaJsonHttpMessageConverter dotaJsonHttpMessageConverter;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Json.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        return this.readArguments(webRequest, parameter, parameter.getGenericParameterType());
    }

    private Object readArguments(NativeWebRequest webRequest, MethodParameter parameter, Type genericParameterType) {
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);
        Object arg =null;
        try {
            // get方式取queryString
            if (servletRequest.getMethod().equals(RequestMappingHandlerAdapter.METHOD_GET)) {
                // base64解碼
                String decodedQueryString = new String(Base64Utils.decodeFromString(servletRequest.getQueryString()));
                return JsonUtil.toObject(decodedQueryString, Class.forName(genericParameterType.getTypeName()));
            }
            // Json注解使用dotaJsonHttpMessageConverter讀取參數(shù)
            arg = dotaJsonHttpMessageConverter.readInternal(Class.forName(genericParameterType.getTypeName()), inputMessage);
            if (null == arg) {
                throw new HttpMessageNotReadableException("Required request body is missing: " +
                        parameter.getMethod().toGenericString());
            }
        } catch (IOException | ClassNotFoundException e) {
            //
        }
        return arg;
    }
}

實際使用

@RequestMapping("/sayHi")
@ResponseBody
public ResponseVo getFeedback(@Json HelloRequest hello){
    ResponseVo responseVo = new ResponseVo();
    responseVo.setMsg("success");
    responseVo.setData(hello.getHello());
    return responseVo;
}

好處

  • 目前前端頁面調(diào)用后臺接口距误,GET和POST的參數(shù)形式不一樣。GET方式是將參數(shù)拼接在url中扁位,而POST是可以直接傳Json對象的
    后臺通過使用@Json注解准潭,可以實現(xiàn)GET和POST參數(shù)的統(tǒng)一,如果需要切換請求方式域仇,無需重新拼裝參數(shù)
  • 本例采用的為base64加密刑然,實際可以根據(jù)情況自行使用加密方式⊙臭ぃ可以偽裝請求的參數(shù)闰集,增強安全性
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沽讹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子武鲁,更是在濱河造成了極大的恐慌爽雄,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沐鼠,死亡現(xiàn)場離奇詭異挚瘟,居然都是意外死亡,警方通過查閱死者的電腦和手機饲梭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進店門乘盖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人憔涉,你說我怎么就攤上這事订框。” “怎么了兜叨?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵穿扳,是天一觀的道長。 經(jīng)常有香客問我国旷,道長矛物,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任跪但,我火速辦了婚禮履羞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屡久。我一直安慰自己忆首,他們只是感情好,可當我...
    茶點故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布涂身。 她就那樣靜靜地躺著雄卷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蛤售。 梳的紋絲不亂的頭發(fā)上丁鹉,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天,我揣著相機與錄音悴能,去河邊找鬼揣钦。 笑死,一個胖子當著我的面吹牛漠酿,可吹牛的內(nèi)容都是我干的冯凹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宇姚!你這毒婦竟也來了匈庭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浑劳,失蹤者是張志新(化名)和其女友劉穎阱持,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體魔熏,經(jīng)...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡衷咽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒜绽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镶骗。...
    茶點故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖躲雅,靈堂內(nèi)的尸體忽然破棺而出鼎姊,到底是詐尸還是另有隱情,我是刑警寧澤相赁,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布此蜈,位于F島的核電站,受9級特大地震影響噪生,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜东囚,卻給世界環(huán)境...
    茶點故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一跺嗽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧页藻,春花似錦桨嫁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至废境,卻和暖如春畜挨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背噩凹。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工巴元, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人驮宴。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓逮刨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親堵泽。 傳聞我的和親對象是個殘疾皇子修己,可洞房花燭夜當晚...
    茶點故事閱讀 45,446評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理暇矫,服務(wù)發(fā)現(xiàn)贷腕,斷路器,智...
    卡卡羅2017閱讀 134,695評論 18 139
  • 前言 上一篇文章介紹了SpringMvc的RequestMappingHandlerMapping,自定義了Con...
    wcong閱讀 14,795評論 0 9
  • 從三月份找實習(xí)到現(xiàn)在夯接,面了一些公司,掛了不少吩屹,但最終還是拿到小米斋竞、百度、阿里啥刻、京東奸鸯、新浪、CVTE可帽、樂視家的研發(fā)崗...
    時芥藍閱讀 42,272評論 11 349
  • Servlet Interface 是Java Servlet API的核心抽象娄涩。所有的servlets都直接或者...
    Lucky_Micky閱讀 1,702評論 2 2
  • title: Java EE 7 Tutorial分析date: 2016-12-10 16:47:25catag...
    raincoffee閱讀 1,884評論 2 2