您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“SpringBoot如何自定義參數(shù)解析器”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“SpringBoot如何自定義參數(shù)解析器”吧!
SpringMVC提供了各種姿勢的http參數(shù)解析支持,從前面的GET/POST參數(shù)解析篇也可以看到,加一個@RequsetParam
注解就可以將方法參數(shù)與http參數(shù)綁定,看到這時自然就會好奇這是怎么做到的,我們能不能自己定義一種參數(shù)解析規(guī)則呢?
本文將介紹如何實現(xiàn)自定義的參數(shù)解析,并讓其生效
<!-- more -->
首先得搭建一個web應(yīng)用才有可能繼續(xù)后續(xù)的測試,借助SpringBoot搭建一個web應(yīng)用屬于比較簡單的活;
創(chuàng)建一個maven項目,pom文件如下
<parent> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-parent</artifactid> <version>2.1.7</version> <relativepath /> <!-- lookup parent from update --> </parent> <properties> <project.build.sourceencoding>UTF-8</project.build.sourceencoding> <project.reporting.outputencoding>UTF-8</project.reporting.outputencoding> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency> </dependencies> <build> <pluginmanagement> <plugins> <plugin> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-maven-plugin</artifactid> </plugin> </plugins> </pluginmanagement> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
對于如何自定義參數(shù)解析器,一個較推薦的方法是,先搞清楚springmvc接收到一個請求之后完整的處理鏈路,然后再來看在什么地方,什么時機(jī),來插入自定義參數(shù)解析器,無論是從理解還是實現(xiàn)都會簡單很多。遺憾的是,本篇主要目標(biāo)放在的是使用角度,所以這里只會簡單的提一下參數(shù)解析的鏈路,具體的深入留待后續(xù)的源碼解析
http請求流程圖,來自 SpringBoot是如何解析HTTP參數(shù)的
既然是參數(shù)解析,所以肯定是在方法調(diào)用之前就會被觸發(fā),在Spring中,負(fù)責(zé)將http參數(shù)與目標(biāo)方法參數(shù)進(jìn)行關(guān)聯(lián)的,主要是借助org.springframework.web.method.support.HandlerMethodArgumentResolver
類來實現(xiàn)
/** * Iterate over registered {@link HandlerMethodArgumentResolver}s and invoke the one that supports it. * @throws IllegalStateException if no suitable {@link HandlerMethodArgumentResolver} is found. */ @Override @Nullable public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception { HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter); if (resolver == null) { throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]"); } return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory); }
上面這段核心代碼來自org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#resolveArgument
,主要作用就是獲取一個合適的HandlerMethodArgumentResolver
,實現(xiàn)將http參數(shù)(webRequest
)映射到目標(biāo)方法的參數(shù)上(parameter
)
所以說,實現(xiàn)自定義參數(shù)解析器的核心就是實現(xiàn)一個自己的HandlerMethodArgumentResolver
實現(xiàn)一個自定義的參數(shù)解析器,首先得有個目標(biāo),我們在get參數(shù)解析篇里面,當(dāng)時遇到了一個問題,當(dāng)傳參為數(shù)組時,定義的方法參數(shù)需要為數(shù)組,而不能是List,否則無法正常解析;現(xiàn)在我們則希望能實現(xiàn)這樣一個參數(shù)解析,以支持上面的場景
為了實現(xiàn)上面這個小目標(biāo),我們可以如下操作
定義這個注解,主要就是用于表明,帶有這個注解的參數(shù),希望可以使用我們自定義的參數(shù)解析器來解析;
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ListParam { /** * Alias for {@link #name}. */ @AliasFor("name") String value() default ""; /** * The name of the request parameter to bind to. * * @since 4.2 */ @AliasFor("value") String name() default ""; }
接下來就是自定義的參數(shù)解析器了,需要實現(xiàn)接口HandlerMethodArgumentResolver
public class ListHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(ListParam.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { ListParam param = parameter.getParameterAnnotation(ListParam.class); if (param == null) { throw new IllegalArgumentException( "Unknown parameter type [" + parameter.getParameterType().getName() + "]"); } String name = "".equalsIgnoreCase(param.name()) ? param.value() : param.name(); if ("".equalsIgnoreCase(name)) { name = parameter.getParameter().getName(); } String ans = webRequest.getParameter(name); if (ans == null) { return null; } String[] cells = StringUtils.split(ans, ","); return Arrays.asList(cells); } }
上面有兩個方法:
supportsParameter
就是用來表明這個參數(shù)解析器適不適用
實現(xiàn)也比較簡單,就是看參數(shù)上有沒有前面定義的ListParam
注解
resolveArgument
這個方法就是實現(xiàn)將http參數(shù)粗轉(zhuǎn)換為目標(biāo)方法參數(shù)的具體邏輯
上面主要是為了演示自定義參數(shù)解析器的過程,實現(xiàn)比較簡單,默認(rèn)只支持List<string>
上面雖然實現(xiàn)了自定義的參數(shù)解析器,但是我們需要把它注冊到HandlerMethodArgumentResolver
才能生效,一個簡單的方法如下
@SpringBootApplication public class Application extends WebMvcConfigurationSupport { @Override protected void addArgumentResolvers(List<handlermethodargumentresolver> argumentResolvers) { argumentResolvers.add(new ListHandlerMethodArgumentResolver()); } public static void main(String[] args) { SpringApplication.run(Application.class); } }
為了驗證我們的自定義參數(shù)解析器ok,我們開兩個對比的rest服務(wù)
@RestController @RequestMapping(path = "get") public class ParamGetRest { /** * 自定義參數(shù)解析器 * * @param names * @param age * @return */ @GetMapping(path = "self") public String selfParam(@ListParam(name = "names") List<string> names, Integer age) { return names + " | age=" + age; } @GetMapping(path = "self2") public String selfParam2(List<string> names, Integer age) { return names + " | age=" + age; } }
演示demo如下,添加了ListParam
注解的可以正常解析,沒有添加注解的會拋異常
到此,相信大家對“SpringBoot如何自定義參數(shù)解析器”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。