這是我的方法簽名
@RequestMapping(value = {"/article", "/article/{id}", "/article/{name}"}, method = RequestMethod.GET,
consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<JsonNode> get(@PathVariable Map<String, String> pathVarsMap, @RequestParam(value="test") MultiValueMap<String, String> test, @RequestBody(required=false) JsonNode requestBody )
我想把它變成
public ResponseEntity<JsonNode> get( MyStructure mystr)
里面MyStructure 會有@PathVariable Map<String, String> pathVarsMap, @RequestParam(value="test") MultiValueMap<String, String> test, @RequestBody(required=false) JsonNode requestBody什么。
我知道我必須使用自定義決議器并實施resolveArgument. 我看到的一個例子就是這樣做的(Map<String, String>) httpServletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE)。但我不知道如何讓它作業。我可以在 MyString 中創建MultiValueMap和內部嗎?RequestBody
在另一個地方,我看到建議是使用
@Nonnull
protected final Map<String, String> getUriTemplateVariables(NativeWebRequest request) {
@SuppressWarnings("unchecked")
Map<String, String> variables =
(Map<String, String>) request.getAttribute(
URI_TEMPLATE_VARIABLES_ATTRIBUTE, SCOPE_REQUEST);
return (variables != null) ? variables : Collections.<String, String>emptyMap();
}
所以我對我應該如何實作這個有點困惑
uj5u.com熱心網友回復:
all @PathVariable, @RequestParamand@RequestBody只能在方法引數上注解,所以沒有辦法在物件欄位上注解。
決議這些注釋值的現有代碼HandlerMethodArgumentResolver也假定這些注釋在方法引數上進行了注釋,這意味著您也不能簡單地委托給它們來決議您的請求物件的值。
您最好的選擇是簡單地參考HandlerMethodArgumentResolver每個注釋的對應代碼并將相關代碼復制到您的實作中。
- 對于
@PathVariable,它是由PathVariableMapMethodArgumentResolver - 對于
@RequestParamonMultiValueMap,它通過以下方式解決RequestParamMapMethodArgumentResolver - 因為
@RequestBody,它是由 解決的RequestResponseBodyMethodProcessor。在內部,它使用一個串列HttpMessageConverter來讀取 HTTP 請求正文。由于您現在使用 Jackson 來讀取請求正文,因此您只需要專注于MappingJackson2HttpMessageConverter簡單起見。
這比我預期的要容易。以下實作對您來說應該是一個很好的起點。
首先定義MyStructure類:
public class MyStructure {
public Map<String, String> pathVariables;
public MultiValueMap<String, String> queryParameters;
public JsonNode requestBody;
}
并實施MyStructureArgumentResolver:
public class MyStructureArgumentResolver implements HandlerMethodArgumentResolver {
private MappingJackson2HttpMessageConverter messageConverter;
public MyStructureArgumentResolver(MappingJackson2HttpMessageConverter messageConverter) {
super();
this.messageConverter = messageConverter;
}
@Override
public boolean supportsParameter(MethodParameter parameter) {
return MyStructure.class.isAssignableFrom(parameter.getParameterType());
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
MyStructure request = new MyStructure();
request.queryParameters = resolveQueryParameters(webRequest);
request.pathVariables = resolvePathVariables(webRequest);
request.requestBody = resolveRequestBody(webRequest, parameter);
return request;
}
private MultiValueMap<String, String> resolveQueryParameters(NativeWebRequest webRequest) {
// resolve all query parameter into MultiValueMap
Map<String, String[]> parameterMap = webRequest.getParameterMap();
MultiValueMap<String, String> result = new LinkedMultiValueMap<>(parameterMap.size());
parameterMap.forEach((key, values) -> {
for (String value : values) {
result.add(key, value);
}
});
return result;
}
private Map<String, String> resolvePathVariables(NativeWebRequest webRequest) {
Map<String, String> uriTemplateVars = (Map<String, String>) webRequest.getAttribute(
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
if (!CollectionUtils.isEmpty(uriTemplateVars)) {
return new LinkedHashMap<>(uriTemplateVars);
} else {
return Collections.emptyMap();
}
}
private JsonNode resolveRequestBody(NativeWebRequest webRequest, MethodParameter parameter)
throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
HttpInputMessage inputMessage = new ServletServerHttpRequest(servletRequest);
MediaType contentType;
try {
contentType = inputMessage.getHeaders().getContentType();
} catch (InvalidMediaTypeException ex) {
throw new HttpMediaTypeNotSupportedException(ex.getMessage());
}
if (contentType == null) {
contentType = MediaType.APPLICATION_OCTET_STREAM;
}
Class<?> contextClass = parameter.getContainingClass();
JsonNode body = JsonNodeFactory.instance.objectNode();
if (messageConverter.canRead(JsonNode.class, contextClass, contentType)) {
body = (JsonNode) messageConverter.read(JsonNode.class, inputMessage);
}
return body;
}
}
然后注冊MyStructureArgumentResolver:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private MappingJackson2HttpMessageConverter messageConverter;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new MyStructureArgumentResolver(messageConverter));
}
}
并在控制器方法中使用它:
@RequestMapping(value = { "/test/{name}" }, method = RequestMethod.GET)
public ResponseEntity<String> test(MyStructure request) {
}
uj5u.com熱心網友回復:
@PostMapping("/get")
public ResponseEntity<JsonNode> get( @RequestBody MyStructure mystr){...}
呼叫該介面時,在請求體中填寫引數,將body作為application/json發送。參考這個示例:示例專案
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/518078.html
上一篇:如何在SpringBoot中獲取application.prpoperty的值
下一篇:Golang中結構型別之間的轉換
