请求报文封装
请求报文问题描述
框架基于spring-web实现的REST服务接口,接口调用时可基于HTTP的url传递调用参数,也可以通过post方法在HTTP的body中传递参数。
如果基于url传递参数,可以使用spirng-web的@PathVariable注解获取参数,如下所示:
@DeleteMapping(value = "/users/{id}")
public Result delete(@PathVariable String id) {
如果基于body传递参数,在后端可以基于@RequestParam来获取参数,如下所示:
@GetMapping("/users")
public PageResult<User> findUsers(@RequestParam Map<String, Object> params) {
如果body传递的参数为一个对象的Json数据结构,则可以使用@RequestBody直接转换为一个对象,如下所示:
public Result saveOrUpdate(@RequestBody User sysUser) throws Exception {
return appUserService.saveOrUpdateUser(sysUser);
以上基于不同的参数获取方式,提供了太多的注解方式,来基于不同的场景获取数据做数据类型转换。
解决思路
扩展一个注解,如:@HouyiRequest,该注解使用在方法参数上,注解有两个属性:
一个name属性可以指定参数名称,name属性默认值为参数名称。
一个type属性可以指定参数对应的数据类型,type属性默认值为参数类型。
则以上的请求就可以改为:
@DeleteMapping(value = "/users/{id}")
public Result delete(@HouyiRequest(name="id", type=String.class)String id) {
@GetMapping("/users")
public PageResult<User> findUsers(@HouyiRequest Map params) {
public Result saveOrUpdate(@HouyiRequest User sysUser) throws Exception {
实现
在common-core中扩展一个注解@HouyiRequest
实现在common-web中实现Spring-web包中的HandlerMethodArgumentResolver接口
/**
* Strategy interface for resolving method parameters into argument values in
* the context of a given request.
*
* @author Arjen Poutsma
* @since 3.1
* @see HandlerMethodReturnValueHandler
*/
public interface HandlerMethodArgumentResolver {
/**
* Whether the given {@linkplain MethodParameter method parameter} is
* supported by this resolver.
* @param parameter the method parameter to check
* @return {@code true} if this resolver supports the supplied parameter;
* {@code false} otherwise
*/
boolean supportsParameter(MethodParameter parameter);
/**
* Resolves a method parameter into an argument value from a given request.
* A {@link ModelAndViewContainer} provides access to the model for the
* request. A {@link WebDataBinderFactory} provides a way to create
* a {@link WebDataBinder} instance when needed for data binding and
* type conversion purposes.
* @param parameter the method parameter to resolve. This parameter must
* have previously been passed to {@link #supportsParameter} which must
* have returned {@code true}.
* @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @param binderFactory a factory for creating {@link WebDataBinder} instances
* @return the resolved argument value, or {@code null} if not resolvable
* @throws Exception in case of errors with the preparation of argument values
*/
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}
扩展Spring-web的WebMvcConfigurationSupport类,添加springmvc对扩展注解的支持,如下是基于SpringBoot的示例。
@Configuration
public class ClientResourcesConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
// super.addArgumentResolvers(argumentResolvers);
argumentResolvers.add(new JsonPathArgumentResolver());
}
返回报文封装
返回报文问题描述
框架可用于单体应用或微服务网关开发时,前端应用调用后端接口需要获取一个统一的返回报文,方便前端作结果展示及展示逻辑处理。
比如:
一个REST-API的接口查询指定用户信息。
http://ip:port/app/user/${userName}
如果正常访问会返回一个用户的Json结构的数据信息,如:
{
"accountNonExpired": true,
"accountNonLocked": true,
"attributes": {},
"authorityIds": [],
"credentialsNonExpired": true,
"enabled": true,
"id": "admin",
"password": "",
"permissions": [],
"username": ""
}
但如果该用户不存在,可以返回一个空的Json结构,如:
{
"accountNonExpired": true,
"accountNonLocked": true,
"attributes": {},
"authorityIds": [],
"credentialsNonExpired": true,
"enabled": true,
"id": "", //user id is empty
"password": "",
"permissions": [],
"username": ""
}
或直接返回一条业务异常的消息提示:
{
"code": "999",
"error_mssage": "admin用户不存在"
}
这些返回结果都不方便前端封装展示逻辑。
解决思路
通过统一返回一个接口报文,如下所示:
{
"resp_code": "",
"resp_msg": "",
"datas": ...
}
报文中有统一的状态码 "resp_code",前端可以根据状态码判断接口调用是成功还是失败,比如resp_code值不为“200”则为异常,前端只要判断状态码不为“200”,则可以将resp_msg属性中的异常信息直接做异常提醒展示。
{
"resp_code": "401",
"resp_msg": "用户未授权",
"datas": ...
}
如果返回的状态码为“200”,则可以将datas中取出的约定好的数据格式进行解析并做相关的展示逻辑处理。
{
"resp_code": "200",
"resp_msg": "请求成功",
"datas": [
{
"createTime": "",
"enabled": true,
"id": "",
"mobile": "",
"newPassword": "",
"oldPassword": "",
"password": "",
"updateTime": "",
"username": ""
}
]
}
实现
在common-core包中定义扩展注解@HouyiResponse,该注解可以使用在方法的返回类型上。
在common-web包中实现spring-web包中接口HandlerMethodReturnValueHandler
/**
* Strategy interface to handle the value returned from the invocation of a
* handler method .
*
* @author Arjen Poutsma
* @since 3.1
* @see HandlerMethodArgumentResolver
*/
public interface HandlerMethodReturnValueHandler {
/**
* Whether the given {@linkplain MethodParameter method return type} is
* supported by this handler.
* @param returnType the method return type to check
* @return {@code true} if this handler supports the supplied return type;
* {@code false} otherwise
*/
boolean supportsReturnType(MethodParameter returnType);
/**
* Handle the given return value by adding attributes to the model and
* setting a view or setting the
* {@link ModelAndViewContainer#setRequestHandled} flag to {@code true}
* to indicate the response has been handled directly.
* @param returnValue the value returned from the handler method
* @param returnType the type of the return value. This type must have
* previously been passed to {@link #supportsReturnType} which must
* have returned {@code true}.
* @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @throws Exception if the return value handling results in an error
*/
void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
}
扩展Spring-web的WebMvcConfigurerAdapter类,添加springmvc对扩展注解的支持,如下是基于SpringBoot的示例。
public class ApplicationConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
super.addReturnValueHandlers(returnValueHandlers);
returnValueHandlers.add(new Example());
网友评论