Springboot中前后端数据交互问题
技术概述
在使用Springboot进行前后端分离时,测试前后端数据的交互情况、交互过程出现的明确各种问题及其解决方法。学习该技术原因是为了应对各种情况下前后端的数据交互,避免因为Content-Type发送信息至服务器时内容编码类型不一致造成问题。技术难点是不协调一致容易出现接口数据交互出错,比较细节容易踩坑。
前后端数据交互问题和容易踩坑的地
①
前端请求:
Content-Type:application/x-www-form-urlencoded
@RequestParam或者无注释后端响应:
//添加一个用户
@PostMapping(value = "/user/create")
public HashMap<String, Object> user_Create(@RequestParam("userName") String userName,@RequestParam("sex") Integer sex,
@RequestParam("age") Integer age,@RequestParam("phone") String phone,
@RequestParam("address") String address,@RequestParam("password") String password,
@RequestParam("root") Integer root){
return userService.userCreate(userName,sex,age,phone,address,password,root);
}
@RequestBody后端无法响应:
/*修改个人信息
* 成功返回true
* */
@ResponseBody
@PostMapping(value = "/user/update")
public HashMap<String,Object> update(@RequestBody User user){
return userService.updateCheck(user);
}
结论:当前端以application/x-www-form-urlencoded格式上传数据时,后台可以使用@RequestParam或者不使用任何注解来获取参数。 后台不可以使用@RquestBody来获取参数,使用的话会报错误。
②
前端请求:
Content-Type:application/json
@RequestParam或者无注释后端无法响应:
//添加一个用户
@PostMapping(value = "/user/create")
public HashMap<String, Object> user_Create(@RequestParam("userName") String userName,@RequestParam("sex") Integer sex,
@RequestParam("age") Integer age,@RequestParam("phone") String phone,
@RequestParam("address") String address,@RequestParam("password") String password,
@RequestParam("root") Integer root){
return userService.userCreate(userName,sex,age,phone,address,password,root);
}
参数添加@RequestBody注解无法响应:
/*修改个人信息
* 成功返回true
* */
@ResponseBody
@PostMapping(value = "/user/update")
public HashMap<String,Object> update(@RequestBody String userName
@RequestBody String address){
return userService.updateCheck(userName,address);
}
参数用@RequestBody注解,是一个Java bean,响应:
/*修改个人信息
* 成功返回true
* */
@ResponseBody
@PostMapping(value = "/user/update")
public HashMap<String,Object> update(@RequestBody User user){//区别
return userService.updateCheck(user);
}
参数用@RequestBody注解,是一个Map,响应:
/*修改个人信息
* 成功返回true
* */
@ResponseBody
@PostMapping(value = "/user/update")
public HashMap<String,Object> update(@RequestBody Map<String,Object> map){//区别
return userService.updateCheck(map);
}
结论:当前端使用application/json来传递数据的时候,后端只能使用 @RequestBody 以及 Java bean或者 map 的方式来接收数据。
输出接口日志来发现问题
//引入日志配置
private static final Log LOG = LogFactory.getLog(LogAspect.class);
/**
* 定义一个切入点 只拦截controller.
* 解释下:
* ~ 第一个 * 代表任意修饰符及任意返回值.
* ~ 第二个 * 定义在web包或者子包
* ~ 第三个 * 任意方法
* ~ .. 匹配任意数量的参数.
*/
@Pointcut("execution(* com.manager.system.controller..*.*(..))")
public void logPointcut() {
}
//around(和上面的方法名一样)
@org.aspectj.lang.annotation.Around("logPointcut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
LOG.info("=====================================Method start====================================");
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
long start = System.currentTimeMillis();
try {
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
LOG.info("请求地址:" + request.getRequestURI());
LOG.info("用户IP:" + request.getRemoteAddr());
LOG.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
LOG.info("参数: " + Arrays.toString(joinPoint.getArgs()));
LOG.info("执行时间: " + (end - start) + " ms!");
LOG.info("=====================================Method End====================================");
return result;
} catch (Throwable e) {
long end = System.currentTimeMillis();
LOG.info("URL:" + request.getRequestURI());
LOG.info("IP:" + request.getRemoteAddr());
LOG.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
LOG.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
LOG.info("执行时间: " + (end - start) + " ms!");
LOG.info("=====================================Method End====================================");
throw e;
}
}