您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么自定義@RequestBody注解獲取JSON數據”,在日常操作中,相信很多人在怎么自定義@RequestBody注解獲取JSON數據問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么自定義@RequestBody注解獲取JSON數據”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Spring MVC 的 @RequestBody 注解只能將請求體中的 JSON 數據封裝成 Bean,而無法對單一字段實施管理(例如 required、name 等屬性)。
首先思考,我們需要這個注解做什么?
設置該字段的必選性(required)
設置該字段在請求體 JSON 中的 key 值(name、value)
設置該字段的默認值(defaultValue)
于是我們的注解類 @JsonArg 至少應該長這樣:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface JsonArg { @AliasFor("name") String value() default ""; @AliasFor("value") String name() default ""; boolean required() default true; String defaultValue() default ValueConstants.DEFAULT_NONE; }
其中:
@Retention(RetentionPolicy.RUNTIME)
聲明我們需要在運行期動態地獲取它地信息
@Target(ElementType.PARAMETER)
聲明這個注解只能作用在方法參數
是的,它和 Spring MVC 自帶的 @RequestParam 注解非常像,但 @RequestParam 只能作用于 query parameters 和 form data。
單純的定義注解類程序是無法知道我們要它做什么的,所以我們要告訴程序在遇到這個注解時該做什么。
public class JsonArgMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver { /** * 表示關于 namedValue 的信息,包括名稱、是否需要它以及默認值。 * * @param parameter 待處理的方法參數 * @return {@link JsonArgNamedValueInfo} */ @Override protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) { JsonArg ann = parameter.getParameterAnnotation(JsonArg.class); return (ann != null ? new JsonArgNamedValueInfo(ann) : new JsonArgNamedValueInfo()); } /** * 解析方法 * * @param name 待解析的 JSON 的 key * @param parameter 待處理的方法參數 * @return 解析出來的值 */ @Override protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { ContentCachingRequestWrapper contentCachingRequestWrapper = request.getNativeRequest(ContentCachingRequestWrapper.class); String body; assert contentCachingRequestWrapper != null; byte[] contentAsByteArray = contentCachingRequestWrapper.getContentAsByteArray(); if (contentAsByteArray.length == 0) { try (BufferedReader reader = contentCachingRequestWrapper.getReader()) { body = reader.lines().collect(Collectors.joining("")); } } else { body = new String(contentAsByteArray); } return JSONObject.parseObject(body).get(name); } /** * 是否支持該方法參數 * * @param parameter 待處理的方法參數 */ @Override public boolean supportsParameter(MethodParameter parameter) { return true; } private static class JsonArgNamedValueInfo extends NamedValueInfo { public JsonArgNamedValueInfo() { super("", false, ValueConstants.DEFAULT_NONE); } public JsonArgNamedValueInfo(JsonArg annotation) { super(annotation.name(), annotation.required(), annotation.defaultValue()); } } }
注意到在 resolveName() 方法中我們獲取的 request 類型是 ContentCachingRequestWrapper。
這是因為默認的 request 只能讀取一次請求體,而我們的解析器在解析每個方法參數時都需要讀取一次請求體。
添加過濾器將我們的請求轉換為所需要的 ContentCachingRequestWrapper。
/* 將request包裝成ContentCachingRequest,以反復讀取請求體 */ @Component public class CachingRequestBodyFilter extends GenericFilterBean { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { if (servletRequest instanceof HttpServletRequest) { filterChain.doFilter(new ContentCachingRequestWrapper((HttpServletRequest) servletRequest), servletResponse); } else { filterChain.doFilter(servletRequest, servletResponse); } } }
最后,將自定義的解析器注冊到 Spring MVC。
@Configuration public class SpringMvcConfig implements WebMvcConfigurer { @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(new JsonArgMethodArgumentResolver()); } }
和 @RequestParam 的用法相似。
public CommonResult<Object> signUp( @JsonArg(name = "uname") String username, @JsonArg(required = false, name = "pwd", defaultValue = "123") String password ) { log.info("[Username]: {}, [Password]: {}", username, password); return null; }
到此,關于“怎么自定義@RequestBody注解獲取JSON數據”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。