使用版本:
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在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; } ...}
调整解析器的顺序
在一次使用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 条评论) |