掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
環(huán)境:springboot2.2.10.RELEASE

希望根據(jù)請(qǐng)求中header['x-token']的不同值調(diào)用不同的接口。接口請(qǐng)求地址相同,根據(jù)不同的header信息調(diào)用不同的執(zhí)行方法。
在SpringMVC中可以通過(guò)自定義
RequestMappingHandlerMapping#getCustomMethodCondition來(lái)實(shí)現(xiàn)此功能。
自定義請(qǐng)求匹配通過(guò)實(shí)現(xiàn)RequestCondition接口自定義規(guī)則
系統(tǒng)默認(rèn)提供了以下RequestCondition實(shí)現(xiàn)
- public class CustomRequestCondition implements RequestCondition
{ - private static final String X_TOKEN_NAME = "x-token" ;
- private Method method ;
- public CustomRequestCondition(Method method) {
- this.method = method ;
- }
- // 當(dāng)接口上有多個(gè)匹配規(guī)則時(shí),進(jìn)行合并操作
- @Override
- public CustomRequestCondition combine(CustomRequestCondition other) {
- return new CustomRequestCondition(other.method) ;
- }
- // 核心方法:根據(jù)匹配的條件進(jìn)行判斷是否匹配,如果匹配則返回當(dāng)前的對(duì)象,不匹配則返回null
- @Override
- public CustomRequestCondition getMatchingCondition(HttpServletRequest request) {
- AKF akf = method.getAnnotation(AKF.class) ;
- return akf != null ? buildToken(request, akf) : null ;
- }
- // 當(dāng)有多個(gè)都滿足條件的時(shí)候,進(jìn)行比較具體使用哪個(gè)
- @Override
- public int compareTo(CustomRequestCondition other, HttpServletRequest request) {
- return 0 ;
- }
- // 判斷請(qǐng)求header中的信息與注解中配置的信息是否一致
- private CustomRequestCondition buildToken(HttpServletRequest request, AKF akf) {
- String xToken = request.getHeader(X_TOKEN_NAME) ;
- if (xToken == null || xToken.length() == 0) {
- return null ;
- }
- return xToken.equals(akf.value()) ? this : null ;
- }
- }
- public class CustomMethodConditionRequestHandlerMapping extends RequestMappingHandlerMapping {
- @Override
- protected RequestCondition> getCustomMethodCondition(Method method) {
- return new CustomRequestCondition(method) ;
- }
- }
- @Configuration
- public class CustomEndpointConfig extends WebMvcConfigurationSupport {
- @Override
- protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
- return new CustomMethodConditionRequestHandlerMapping() ;
- }
- }
注冊(cè)HandlerMapping我們也可以通過(guò)@Bean的方式,但是這種方式會(huì)使得你在定義多個(gè)相同接口地址的時(shí)候容器啟動(dòng)就會(huì)報(bào)錯(cuò)
而且@Bean的方式是向容器中注冊(cè)一個(gè)HandlerMapping對(duì)象;而通過(guò)上面的方式就是替換系統(tǒng)默認(rèn)的
RequestMappingHandlerMapping對(duì)象。兩種方式是不一樣的,一個(gè)是增加一個(gè)HandlerMapping,一個(gè)是替換系統(tǒng)默認(rèn)的。
- @RestController
- @RequestMapping("/conditions")
- public class CustomMethodConditionController {
- @GetMapping("/index")
- public Object index() {
- return "custom method condition success" ;
- }
- @GetMapping("/index")
- @AKF
- public Object x() {
- return "x method invoke" ;
- }
- @GetMapping("/index")
- @AKF("x1")
- public Object x1() {
- return "x1 method invoke" ;
- }
- @GetMapping("/index")
- @AKF("x2")
- public Object x2() {
- return "x2 method invoke" ;
- }
- }
上面的接口地址完全相關(guān),只是有些有@AKF注解,有些沒(méi)有。
如果通過(guò)@Bean注冊(cè)一個(gè)HandlerMapping后,多個(gè)請(qǐng)求路徑相同會(huì)報(bào)如下錯(cuò)誤:
- Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'customMethodConditionController' method
- com.pack.controller.CustomMethodConditionController#x()
- to {GET /conditions/index}: There is already 'customMethodConditionController' bean method
- com.pack.controller.CustomMethodConditionController#index() mapped.
- at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.validateMethodMapping(AbstractHandlerMethodMapping.java:636) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
- at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.register(AbstractHandlerMethodMapping.java:603) ~[spring-webmvc-5.2.9.RELEASE.jar:5.2.9.RELEASE]
在以上的請(qǐng)求中如果請(qǐng)求中沒(méi)有攜帶x-token信息或者是value值不被匹配那么請(qǐng)求會(huì)是404。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流