純流量卡免費申請入口seo優(yōu)化幾個關(guān)鍵詞
常用注解
- @PathVariable:用于從URL路徑中提取變量。
- @RequestHeader:用于從HTTP請求頭中獲取數(shù)據(jù)。
- @ModelAttribute:用于獲取請求參數(shù)(包括URL參數(shù)和POST請求的表單數(shù)據(jù)),也可以用于將數(shù)據(jù)綁定到對象上。
- @RequestParam:用于獲取URL參數(shù)。
- @CookieValue:用于獲取請求中的Cookie值。
- @RequestBody:用于獲取請求體中的數(shù)據(jù),通常用于處理POST請求中的JSON或XML數(shù)據(jù)。
java代碼示例(普通)
import org.springframework.web.bind.annotation.*;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;@RestController
@RequestMapping("/api")
public class DataController {// 使用 @PathVariable 從URL路徑中獲取變量@GetMapping("/path/{userId}/profile")public String getPathVariable(@PathVariable String userId) {return "User ID from Path Variable: " + userId;}// 使用 @RequestHeader 從請求頭中獲取數(shù)據(jù)@GetMapping("/header")public String getRequestHeader(@RequestHeader("X-Request-ID") String requestId) {return "Request ID from Header: " + requestId;}// 使用 @ModelAttribute 獲取請求參數(shù)并綁定到對象@PostMapping("/modelAttribute")public String handleModelAttribute(@ModelAttribute User user) {return "User Name: " + user.getName() + ", Age: " + user.getAge();}// 使用 @RequestParam 獲取URL參數(shù)@GetMapping("/params")public String getRequestParam(@RequestParam("name") String name, @RequestParam("age") int age) {return "Name: " + name + ", Age: " + age;}// 使用 @CookieValue 獲取Cookie值@GetMapping("/cookie")public String getCookieValue(@CookieValue("session") String sessionCookie) {return "Session Cookie: " + sessionCookie;}// 使用 @RequestBody 獲取請求體中的數(shù)據(jù)@PostMapping("/body")public String handleRequestBody(@RequestBody User user) {return "User Name from Body: " + user.getName() + ", Age: " + user.getAge();}static class User {private String name;private int age;// Getters and setterspublic String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
}
測試示例(普通)
- @PathVariable 測試路徑:
GET /api/path/123/profile
- @RequestHeader 測試路徑:
GET /api/header
請求頭中需要包含 X-Request-ID: 12345。
- @ModelAttribute 測試路徑:
POST /api/modelAttribute
{"name": "John Doe","age": 30
}
- @RequestParam 測試路徑:
GET /api/params?name=John&age=30
- @CookieValue 測試路徑:
GET /api/cookie
Cookie: session=abc123
- @RequestBody 測試路徑:
POST /api/body
{"name": "Jane Doe","age": 25
}
特殊(傳數(shù)組)
- 使用 @RequestBody 傳遞JSON數(shù)組
- 如果你使用POST請求并通過請求體傳遞一個JSON數(shù)組,你可以使用@RequestBody注解來接收這個數(shù)組。在Spring Boot中,你可以使用HttpEntity或者直接使用@RequestBody來接收數(shù)組。
@RestController @RequestMapping("/api") public class ListController {// 使用 @RequestBody 接收J(rèn)SON數(shù)組@PostMapping("/list")public String handleRequestBodyList(@RequestBody List<User> users) {return "Received " + users.size() + " users";} }
- 測試路徑和請求體
POST /api/list [{"name": "John Doe", "age": 30},{"name": "Jane Doe", "age": 25} ]
- 使用 @RequestParam 傳遞多個相同參數(shù)
- 如果你使用GET請求并通過URL參數(shù)傳遞多個相同名稱的參數(shù),你可以使用@RequestParam注解來接收這些參數(shù),并將其轉(zhuǎn)換為列表。
@RestController @RequestMapping("/api") public class ListController {// 使用 @RequestParam 接收多個相同參數(shù)@GetMapping("/params")public String getRequestParamList(@RequestParam("userId") List<String> userIds) {return "Received user IDs: " + Arrays.toString(userIds.toArray());} }
- 測試路徑和參數(shù):
GET /api/params?userId=1&userId=2&userId=3
- 使用 @ModelAttribute 傳遞表單數(shù)據(jù)
- 如果你使用POST請求并通過表單數(shù)據(jù)傳遞一個列表,你可以使用@ModelAttribute注解來接收這個列表。這通常用于處理表單提交。
@RestController @RequestMapping("/api") public class ListController {// 使用 @ModelAttribute 接收表單數(shù)據(jù)@PostMapping("/form")public String handleModelAttribute(@ModelAttribute List<User> users) {return "Received " + users.size() + " users";} }
- 測試路徑和請求體:
POST /api/form 請求體中包含表單數(shù)據(jù)(使用application/x-www-form-urlencoded): userId=1&userId=2&userId=3 或者,如果你使用JSON格式的請求體,你需要自定義一個包裝類來接收這個列表。
- 使用自定義包裝類
- 對于復(fù)雜的數(shù)據(jù)結(jié)構(gòu),你可以創(chuàng)建一個自定義的包裝類來接收列表。
public class UserListWrapper {private List<User> users;// Getters and setterspublic List<User> getUsers() {return users;}public void setUsers(List<User> users) {this.users = users;} }@RestController @RequestMapping("/api") public class ListController {// 使用自定義包裝類接收J(rèn)SON數(shù)組@PostMapping("/custom")public String handleCustomList(@RequestBody UserListWrapper wrapper) {return "Received " + wrapper.getUsers().size() + " users";} }
- 測試路徑和請求體:
POST /api/custom {"users": [{"name": "John Doe", "age": 30},{"name": "Jane Doe", "age": 25}] }
原理分析
主要是DispatcherServlet 的doDispatch方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {// 獲取當(dāng)前請求的HandlerMappedHandler mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// 獲取HandlerAdapterHandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 執(zhí)行前置攔截器if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 調(diào)用Handler(包含參數(shù)解析器處理參數(shù)過程)ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());}
在handle方法內(nèi)部,HandlerAdapter會使用一系列的參數(shù)解析器(HandlerMethodArgumentResolver)來處理Controller方法的參數(shù)。這些解析器負(fù)責(zé)從請求中提取數(shù)據(jù),并將其轉(zhuǎn)換為Controller方法所需的參數(shù)類型。
參數(shù)解析的主要代碼位于RequestMappingHandlerAdapter的handleInternal方法中
protected ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ModelAndView mav;checkRequest(request);// 如果synchronizeOnSession為true且能從request獲取會話對象,則以同步方式執(zhí)行handlerif (this.synchronizeOnSession) {HttpSession session = request.getSession(false);if (session != null) {Object mutex = WebUtils.getSessionMutex(session);synchronized (mutex) {mav = invokeHandlerMethod(request, response, handlerMethod);}} else {mav = invokeHandlerMethod(request, response, handlerMethod);}} else {mav = invokeHandlerMethod(request, response, handlerMethod);}if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {return null;}applyDefaultViewName(request, mav);MappedHandler mappedHandler = getHandlerExecutionChain(handlerMethod);mappedHandler.applyPostHandle(request, response, mav);return mav;
}
在invokeHandlerMethod方法中,會遍歷所有的參數(shù)解析器,尋找能夠解析當(dāng)前參數(shù)的解析器,并將其緩存。然后,通過參數(shù)解析器將需要的參數(shù)從請求中獲取出來,并進行類型轉(zhuǎn)換和數(shù)據(jù)綁定。
public Object invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);invocableMethod.invokeAndHandle(request, response);return invocableMethod.getReturnValue();
}
在ServletInvocableHandlerMethod的invokeAndHandle方法中,會調(diào)用getMethodArgumentValues方法來獲取參數(shù)值,這個方法會遍歷所有的參數(shù)解析器,使用它們來解析參數(shù)。
public Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {MethodParameter[] parameters = getMethodParameters();if (ObjectUtils.isEmpty(parameters)) {return EMPTY_ARGS;}Object[] args = new Object[parameters.length];for (int i = 0; i < parameters.length; i++) {MethodParameter parameter = parameters[i];parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);args[i] = findProvidedArgument(parameter, providedArgs);if (args[i] == null) {HandlerMethodArgumentResolver resolver = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);args[i] = resolver.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);}}return args;
}
在這個方法中,resolvers.resolveArgument會調(diào)用具體的參數(shù)解析器來解析參數(shù)。這些解析器主要有:
- RequestParamMethodArgumentResolver:處理@RequestParam注解的參數(shù)。
- PathVariableMethodArgumentResolver:處理@PathVariable注解的參數(shù)。
- RequestBodyMethodArgumentResolver:處理@RequestBody注解的參數(shù),通常用于接收J(rèn)SON或XML格式的請求體。
- RequestHeaderMethodArgumentResolver:處理@RequestHeader注解的參數(shù)。
- CookieValueMethodArgumentResolver:處理@CookieValue注解的參數(shù)。
每個解析器都實現(xiàn)了HandlerMethodArgumentResolver接口,它們負(fù)責(zé)從請求中提取數(shù)據(jù),并將其轉(zhuǎn)換為Controller方法所需的參數(shù)類型。