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;
}
}