首页 > 作文

关于SpringMVC在Controller层方法的参数解析详解

更新时间:2023-04-04 07:17:40 阅读: 评论:0

目录
自定义参数解析器实现效果实现和配置spring提供解析器一些使用tricky总结

使用版本:

spring-boot: 2.1.6.relea

sping: 5.1.8.relea

java: openjdk 11.0.13

自定义参数解析器

为了能够实现自定义参数解析器,只需要实现 handlermethodargumentresolver 并将添加到 webmvcconfigurer#addargumentresolvers 即可。

实现效果

下面以添加一个获取请求头的 client-type 参数为例进行是实现。定义注解 @clienttypemark 以及enum clienttype ,用于注入header中的值。

@target({elementtype.parameter})@retention(retentionpolicy.runtime)@documentedpublic @interface clienttypemark {}
public enum clienttype {    web,    mobile,    unknown    ;}

最终实现的效一个人回家果为在controller的方法中,可以按照如下实现使用。

@restcontroller@requestmapping("/client")public class clienttypeendpoint {    @getmapping("/cur")    public clienttype getcurclienttype(@clienttypemark clienttype clienttype) {        return clienttype;    }}

实现和配置

按照如下方法实现 handlermethodargumentresolver ,用于解析header中的 client-type 并转化为 clienttype 。

package io.github.donespeak.springbootsamples.web.common;import org.apache.commons.lang3.stringutils;import org.springframework.core.methodparameter;import org.springframework.web.bind.support.webdatabinderfactory;import org.springframework.web.context.request.nativewebrequest;import org.springframework.web.method.support.handlermethodargumentresolver;import org.springframework.web.method.support.modelandviewcontainer;public class curclienttypemethodargumentresolver implements handlermethodargumentresolver {    private final string[] client_type_header_names = {"client-type", "client-type", "client-type"};    // 选择要被注入的参数:判断参数是否符合解析的条件    @override    public boolean supportsparameter(methodparameter param) {        return param.hasparameterannotation(clienttypemark.class)                && clienttype.class.isassignablefrom(param.getparametertype());    }    // 返回值将被注入到被选中参数中    @override    public object resolveargument(methodparameter methodparameter, modelandviewcontainer modelandviewcontainer,            nativewebrequest nativewebrequest, webdatabinderfactory webdatabinderfactory) throws exception {        string clienttype = null;        for (string clienttypeheader: client_type_header_names) {            clienttype = nativewebrequest.getheader(clienttypeheader);            if (stringutils.isnotblank(clienttype)) {                break;            }        }        try {            return stringutils.isblank(clienttype) ? clienttype.unknown : clienttype.valueof(clienttype.toupperca());        } catch (exception e) {            return clienttype.unknown;        }    }}

为了使得配置能够生效,可以按照如下的方法添加解析器。

@configurationpublic class webmvcconfig implements webmvcconfigurer {    @override    public void addargumentresolver西安财经学院行知学院官网s(list<handlermethodargumentresolver> argumentresolvers) {        // 解析@cururid注解的参数        argumentresolvers.add(new curclienttypemethodargumentresolver());    }}

至此,自定义参数解析器的工作就完成了。

spring提供解析器

当你完成上面的自定义解析器的时候,大体就能知道spring在controller层的其他参数解析都是怎么实现的了。

如下是spring mvc默认的一些参数解析器。

package org.springframework.web.rvlet.mvc.method.annotation;public class requestmappinghandleradapter extends abstracthandlermethodadapter        implements beanfactoryaware, initializingbean {    ...    /**     * return the list of argument resolvers to u including built-in resolvers     * and custom resolvers provided via {@link #tcustomargumentresolvers}.     */    private list<handlermethodargumentresolver> getdefaultargumentresolvers() {        list<handlermethodargumentresolver> resolvers = new arraylist<>();        // annotation-bad argument resolution        // 解析:@requestparam(required = fal)        resolvers.add(new requestparammethodargumentresolver(getbeanfactory(), fal));        // 解析:@requestparam map        resolvers.add(new requestparammapmethodargumentresolver());        // 解析:@pathvariable        resolvers.add(new pathvariablemethodargumentresolver());        // 解析:@pathvariable map        resolvers.add(new pathvariablemapmethodargumentresolver());        // 解析:@matrixvariable        resolvers.add(new matrixvariablemethodargumentresolver());        // 解析:@matrixvariable map        resolvers.add(new matrixvariablemapmethodargumentresolver());        // 解析:@modelattribute(required = fal)        resolvers.add(春秋是谁写的new rvletmodelattributemethodprocessor(fal));        // 解析:@requestbody        resolvers.add(new requestresponbodymethodprocessor(getmessageconverters(), this.requestresponbodyadvice));        // 解析:@requestpart        resolvers.add(new requestpartmethodargumentresolver(getmessageconverters(), this.requestresponbodyadvice));        // 解析:@requestheader        resolvers.add(new requestheadermethodargumentresolver(getbeanfactory()));        // 解析:@requestheader map        resolvers.add(new requestheadermapmethodargumentresolver());        // 解析:@cookievalue        resolvers.add(new rvletcookievaluemethodargumentresolver(getbeanfactory()));        // 解析:@value        resolvers.add(new expressionvaluemethodargumentresolver(getbeanfactory()));        // 解析:@ssionattribute        resolvers.add(new ssionattributemethodargumentresolver());        // 解析:@requestattribute        resolvers.add(new requestattributemethodargumentresolver());        // type-bad argument resolution        // 解析:webrequest、rvletrequest、multipartrequest、httpssion、        //      principal、locale、timezone、java.time.zoneid、inputstream        //      java.io.reader、org.springframework.http.httpmethod        resolvers.add(new rvletrequestmethodargumentresolver());        // 解析:rvletrespon、outputstream、writer        resolvers.add(new rvletresponmethodargumentresolver());        // 解析:@httpentity、@requestentity        resolvers.add(new httpentitymethodprocessor(getmessageconverters(), this.requestresponbodyadvice));        // 解析:redirectattributes        resolvers.add(new redirectattributesmethodargumentresolver());        // 解析:org.springframework.ui.model, 值为modelandviewcontainer#getmodel        resolvers.add(new modelmethodprocessor());        // 解析:map, 值为modelandviewcontainer#getmodel        resolvers.add(new mapmethodprocessor());        // 解析:org.springframework.validation.errors        resolvers.add(new errorsmethodargumentresolver());        // 解析:org.springframework.web.bind.support.ssionstatus        resolvers.add(new ssionstatusmethodargumentresolver());        // 解析:uricomponentsbuilder 或者 rvleturicomponentsbuilder        resolvers.add(new uricomponentsbuildermethodargumentresolver());        // custom arguments        if (getcustomargumentresolvers() != null) {            resolvers.addall(getcustomargumentresolvers());        }        // catch-all        // 解析:@requestparam(required = true)        resolvers.add(new requestparammethodargumentresolver(getbeanfactory(), true));        // 解析:@modelattribute(required = true)        resolvers.add(new rvletmodelattributemethodprocessor(true));        return resolvers;    }    ...}

一些使用tricky

调整解析器的顺序

在一次使用spring curity的开发中,定义的 urdetia英语学习计划作文ls 实现类在实现 urdetails 的同时还是实现了一个 account 接口,在使用时,希望实现如下的效果。

public void dosomething(@authenticationprincipal account accout) {}

但因为同时使用了,spring-data,spring-data提供的 proxyinghandlermethodargumentresolver 会在 authenticationprincipalargumentresolver 前面对account进行注入处理。proxyinghandlermethodargumentresolver 会拦截掉所有非org.springframework中定义的 接口 ,并尝试赋值。为了能够正常赋值给account,需要调整两者的位置。实现如下:

import java.util.linkedlist;import java.util.list;import org.springframework.beans.beanxception;import org.springframework.beans.factory.config.beanpostprocessor;import org.springframework.curity.web.method.annotation.authenticationprincipalargumentresolver;import org.springframework.stereotype.component;import org.springframework.web.method.support.handlermethodargumentresolver;import org.springframework.web.rvlet.mvc.method.annotation.requestmappinghandleradapter;/** * 将 authenticationprincipalargumentresolver 移到最前面,如果不做调整, * 会因为proxyinghandlermethodargumentresolver在authenticationprincipalargumentresolver前面, * 导致 @authenticationprincipal account account 无法注入 */public class argumentresolverbeanpostprocessor implements beanpostprocessor {    private static final string bean_request_mapping_handler_adapter = "requestmappinghandleradapter";    @override    public object postprocessafterinitialization(object bean, string beanname) throws beanxception {        if (beanname.equals(bean_request_mapping_handler_adapter)) {            requestmappinghandleradapter adapter = (requestmappinghandleradapter)bean;            list<handlermethodargumentresolver> argumentresolvers = adapter.getargumentresolvers();            linkedlist<handlermethodargumentresolver> resolversadjusted = new linkedlist<>(argumentresolvers);            argumentresolvers.stream().foreach(r -> {                if (authenticationprincipalargumentresolver.class.isinstance(r)) {                    resolversadjusted.addfirst(r);                } el {                    resolversadjusted.add(r);                }            });adapter.targumentresolvers(resolversadjusted);        }        return bean;    }化学反应方程式} 

总结

到此这篇关于springmvc在controller层方法的参数解析的文章就介绍到这了,更多相关springmvc在controller层方法参数内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 07:17:38,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/022f82671956b3c2a947e2ef4fa986c1.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:关于SpringMVC在Controller层方法的参数解析详解.doc

本文 PDF 下载地址:关于SpringMVC在Controller层方法的参数解析详解.pdf

标签:参数   自定义   方法   赋值
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图