基于注解的Controller接口這些高級(jí)功能,你都知道嗎?
環(huán)境:SpringBoot2.7.18
1. 簡(jiǎn)介
基于注解的Controller接口,你可以使用 @RequestMapping 注解將請(qǐng)求映射到控制器方法。它有多種屬性,可根據(jù) URL、HTTP 方法、請(qǐng)求參數(shù)、頭和媒體類型進(jìn)行匹配。該注解可以在類上使用它來(lái)表達(dá)共享映射,也可以在方法級(jí)使用它來(lái)縮小特定接口映射的范圍。
@RequestMapping 還有 HTTP 方法特定的快捷方式變體:
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
通過(guò)上面的注解,我們能更加具體的去匹配我們的Controller接口方法。這些注解在開(kāi)發(fā)中都是些基本的操作,并且在絕大多數(shù)情況下使用這些接口完全夠用了。接下來(lái)將介紹幾個(gè)高級(jí)用法。
2. 實(shí)戰(zhàn)案例
2.1 HEAD、OPTIONS請(qǐng)求
對(duì)于head,options請(qǐng)求Spring并沒(méi)有提供對(duì)應(yīng)的快捷注解,我們只能通過(guò)@RequestMapping注解來(lái)指定method屬性。
@GetMapping (和 @RequestMapping(method=HttpMethod.GET))支持 HTTP HEAD 透明請(qǐng)求映射。控制器方法無(wú)需更改。在 javax.servlet.http.HttpServlet 中應(yīng)用的響應(yīng)封裝器可確保 Content-Length 標(biāo)頭被設(shè)置為寫(xiě)入的字節(jié)數(shù)(而不會(huì)實(shí)際寫(xiě)入響應(yīng))。如下示例:
@GetMapping("/h")
public Object h() {
System.out.println("header....") ;
return "h method..." ;
}
當(dāng)上面的接口以head方式請(qǐng)求時(shí),也是可以成功進(jìn)入該方法的只是并不會(huì)輸出內(nèi)容到客戶端,而僅僅是通過(guò)Content-Leng告知有多少個(gè)字節(jié)內(nèi)容。
圖片
響應(yīng)header中有Content-Length
圖片
對(duì)應(yīng)HEAD請(qǐng)求我們完全可以通過(guò)GET方式來(lái)解決。
默認(rèn)情況下,HTTP OPTIONS 的處理方式是將 Allow 響應(yīng)頭設(shè)置為具有匹配 URL 模式的所有 @RequestMapping 方法中列出的 HTTP 方法列表。簡(jiǎn)單說(shuō)當(dāng)你通過(guò)OPTIONS請(qǐng)求一個(gè)URL時(shí),Allow的響應(yīng)頭會(huì)設(shè)置為你@RequestMapping(method = ...)這里你method設(shè)置的列表+OPTIONS,如下示例:
@RequestMapping(value = "/o", method = {RequestMethod.DELETE, RequestMethod.HEAD})
public Object o() {
System.out.println("o....") ;
return "h method..." ;
}
當(dāng)上面的接口通過(guò)OPTIONS請(qǐng)求時(shí),那么響應(yīng)header Allow將設(shè)置為如下:
圖片
如果你的@RequestMapping沒(méi)有指定method屬性值,那么Allow 頭信息會(huì)被設(shè)置為 GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS。上面的即可刪除method屬性再次請(qǐng)求如下:
圖片
2.2 自定義請(qǐng)求注解
在某些場(chǎng)景下你可能需要自定義自己的一些注解來(lái)配置通用的匹配模式,那么這時(shí)候通過(guò)自定義請(qǐng)求注解的方式是非常合適的,而不用你對(duì)每一個(gè)請(qǐng)求都去做重復(fù)的事。
自定義請(qǐng)求注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping
public @interface PackMapping {
@AliasFor(annotation = RequestMapping.class)
String name() default "";
@AliasFor(annotation = RequestMapping.class)
String[] value() default {};
@AliasFor(annotation = RequestMapping.class)
// 配置只能是GET或POST方法
RequestMethod[] method() default {RequestMethod.GET, RequestMethod.POST} ;
@AliasFor(annotation = RequestMapping.class)
String[] path() default {};
@AliasFor(annotation = RequestMapping.class)
String[] params() default {};
// 設(shè)置請(qǐng)求header必須包含X-API-Version并且值必須是v1
@AliasFor(annotation = RequestMapping.class)
String[] headers() default {"X-API-Versinotallow=v1"};
@AliasFor(annotation = RequestMapping.class)
String[] consumes() default {};
@AliasFor(annotation = RequestMapping.class)
String[] produces() default {};
}
測(cè)試Controller接口
@PackMapping("/v")
public Object v() {
System.out.println("自定義請(qǐng)求注解....") ;
return "PackMapping method..." ;
}
輸出結(jié)果
圖片
請(qǐng)求中必須攜帶X-API-Version請(qǐng)求header。
2.3 動(dòng)態(tài)顯示注冊(cè)接口
你可以通過(guò)編程方式注冊(cè)處理程序方法,這些方法可以用于動(dòng)態(tài)注冊(cè)或高級(jí)情況,例如不同URL下的同一處理程序的不同實(shí)例,如下示例:
@Configuration
public class CustomWebConfig {
@Autowired
public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserService handler)
throws NoSuchMethodException {
BuilderConfiguration options = new BuilderConfiguration() ;
options.setPatternParser(new PathPatternParser()) ;
RequestMappingInfo info = RequestMappingInfo.paths("/api/user/{id}").methods(RequestMethod.GET).options(options ).build();
Method method = UserHandler.class.getMethod("getUser", Integer.class) ;
mapping.registerMapping(info, handler, method);
}
}
UserService
@Component
public class UserHandler {
@ResponseBody
public User getUser(@PathVairable("id")Integer id) {
User user = new User() ;
user.setId(id) ;
user.setName("張三") ;
return user ;
}
}
輸出結(jié)果
圖片
以上是本篇文章的全部?jī)?nèi)容,如對(duì)你有幫助就請(qǐng)作者吃個(gè)棒棒糖??。