springboot2.0-統一處理返回結果和異常情況
一、統一處理返回結果和異常處理的原因:
1、在springboot專案裡我們希望介面返回的資料包含至少三個屬性:
a、code:請求介面的返回碼,成功或者異常等返回編碼,例如定義請求成功,code = "0000",查詢結果為null,code = "0001";
b、msg:請求介面的描述,也就是對返回編碼的描述,"0000":就表示請求成功,"0001":表示結果為null;
c、data:請求介面成功,返回的結果。
{
"data": {
"id": 1,
"studentId": "13240115",
"name": "Tiger",
"age": 25,
"famillyAddress": "北京",
"createdDate": "2018-10-08T05:45:49.000+0000",
"updatedDate": "2018-10-09T03:15:33.000+0000"
},
"code": "0000",
"msg": "請求成功"
}
2、在springboot專案裡我們希望請求結果失敗之後,通過返回碼和返回描述來告訴前端介面請求異常。
{
"code": "0001",
"msg": "學號不存在"
}
二、案例
1、建一張學生資訊表,包含學生的學號、姓名、年齡、家庭住址等
CREATE TABLE student_info (
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增',
student_id varchar(20) NOT NULL COMMENT '學號',
name varchar(64) NOT NULL COMMENT '姓名',
age int(2) NOT NULL COMMENT '年齡',
familly_address varchar(256) NOT NULL COMMENT '家庭地址',
created_date datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
updated_date datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新時間',
PRIMARY KEY (student_id),
KEY id (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
2、pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.43</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.9.1</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
</dependencies>
3、案例中使用redis進行快取,可以不需要
4、建立實體類:StudentInfo
package com.dl.cn.message.bean;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* Created by Tiger on 2018/10/8.
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StudentInfo implements Serializable{
private static final long serialVersionUID = 2597547944454691103L;
private Long id;
private String studentId;
private String name;
private Integer age;
private String famillyAddress;
private Date createdDate;
private Date updatedDate;
}
5、建立Mapper:StudentInfoMapper
package com.dl.cn.message.mapper;
import com.dl.cn.message.bean.StudentInfo;
import org.apache.ibatis.annotations.*;
/**
* Created by Tiger on 2018/10/8.
*/
@Mapper
public interface StudentInfoMapper {
@Insert("insert into student_info(student_id,name,age,familly_address)" +
" values(#{studentId},#{name},#{age},#{famillyAddress})")
/**
* 通過bean儲存實體類是,建議不要通過@Param註解,負責實體類的屬性都在@Param中找
* */
void saveStudentInfo(StudentInfo studentInfo);
@Select("select * from student_info where student_id = #{studentId}")
StudentInfo findByStudentId(@Param("studentId") String studentId);
@Update("update student_info set familly_address = #{famillyAddress},updated_date = now() ")
void updateFamillyAddress(@Param("studentId") String studentId,@Param("famillyAddress") String famillyAddress);
}
6、建立service:StudentInfoService
package com.dl.cn.message.service;
import com.dl.cn.message.bean.StudentInfo;
import com.dl.cn.message.mapper.StudentInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
* Created by Tiger on 2018/10/8.
*/
@Service
@CacheConfig(cacheNames = "studentInfo")
@Slf4j
public class StudentInfoService {
@Autowired
StudentInfoMapper studentInfoMapper;
/**
* 儲存學生資訊
* @param studentInfo
* */
public void saveStudentInfo(StudentInfo studentInfo){
studentInfoMapper.saveStudentInfo(studentInfo);
}
/**
* 根據學號查學生資訊
* @param studentId
* @return
* */
@Cacheable(key = "#studentId",unless = "#result == null")
public StudentInfo findByStudentId(String studentId){
log.info("查詢資訊:{}",studentId);
return studentInfoMapper.findByStudentId(studentId);
}
/**
* 根據學號更新家庭地址
* @param studentId
* @param famillyAddress
* */
//刪除對應key的快取
@CacheEvict(key = "#studentId")
public void updateFamillyAddress(String studentId,String famillyAddress){
studentInfoMapper.updateFamillyAddress(studentId,famillyAddress);
}
}
7、建立統一返回結果類:Response
package com.dl.cn.message.response;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* 請求返回類
* Created by Tiger on 2018/10/9.
*/
@Getter
@Setter
@JsonSerialize(include= JsonSerialize.Inclusion.NON_NULL)
public class Response<T> implements Serializable {
private static final long serialVersionUID = -4505655308965878999L;
//請求成功返回碼為:0000
private static final String successCode = "0000";
//返回資料
private T data;
//返回碼
private String code;
//返回描述
private String msg;
public Response(){
this.code = successCode;
this.msg = "請求成功";
}
public Response(String code,String msg){
this();
this.code = code;
this.msg = msg;
}
public Response(String code,String msg,T data){
this();
this.code = code;
this.msg = msg;
this.data = data;
}
public Response(T data){
this();
this.data = data;
}
}
8、建立異常編碼和描述類:ErrorCodeAndMsg
package com.dl.cn.message.enums;
/**
* Created by Tiger on 2018/10/9.
*/
public enum ErrorCodeAndMsg {
Student_number_does_not_exist("0001","學號不存在"),
Insufficient_student_number("0002","學號長度不足"),
Student_number_is_empty("0003","學號為空"),
Network_error("9999","網路錯誤,待會重試"),
;
private String code;
private String msg;
ErrorCodeAndMsg(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
9、建立統一異常處理類:StudentException
package com.dl.cn.message.exception;
import com.dl.cn.message.enums.ErrorCodeAndMsg;
import java.io.Serializable;
/**
* 統一異常捕獲類
* Created by Tiger on 2018/10/9.
*/
public class StudentException extends RuntimeException{
private static final long serialVersionUID = -6370612186038915645L;
private final ErrorCodeAndMsg response;
public StudentException(ErrorCodeAndMsg response) {
this.response = response;
}
public ErrorCodeAndMsg getResponse() {
return response;
}
}
10、建立異常處理的全域性配置類:ExceptionHandler
package com.dl.cn.message.exception;
import com.dl.cn.message.enums.ErrorCodeAndMsg;
import com.dl.cn.message.response.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
/**
* Created by Tiger on 2018/10/9.
*/
@ControllerAdvice
@Slf4j
public class ExceptionHandler {
@org.springframework.web.bind.annotation.ExceptionHandler(StudentException.class)
@ResponseBody
public Response handleStudentException(HttpServletRequest request, StudentException ex) {
Response response;
log.error("StudentException code:{},msg:{}",ex.getResponse().getCode(),ex.getResponse().getMsg());
response = new Response(ex.getResponse().getCode(),ex.getResponse().getMsg());
return response;
}
@org.springframework.web.bind.annotation.ExceptionHandler(Exception.class)
@ResponseBody
public Response handleException(HttpServletRequest request, Exception ex) {
Response response;
log.error("exception error:{}",ex);
response = new Response(ErrorCodeAndMsg.Network_error.getCode(),
ErrorCodeAndMsg.Network_error.getMsg());
return response;
}
}
11、建立controler類:StudentInofController
package com.dl.cn.message.controller;
import com.dl.cn.message.enums.ErrorCodeAndMsg;
import com.dl.cn.message.exception.StudentException;
import com.dl.cn.message.response.Response;
import com.dl.cn.message.service.StudentInfoService;
import com.dl.cn.message.bean.StudentInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by Tiger on 2018/10/8.
*/
@RestController
@RequestMapping("/student")
@Slf4j
public class StudentInofController {
@Autowired
StudentInfoService studentInfoService;
/**
* 儲存學生資訊
* @param studentId
* @param name
* @param age
* @param famillyAddress
* */
@PostMapping("/save")
public void saveStudentInfo(@RequestParam("student_id") String studentId,
@RequestParam("name") String name,
@RequestParam("age") Integer age,
@RequestParam("familly_address") String famillyAddress){
StudentInfo studentInfo = StudentInfo.builder()
.studentId(studentId)
.name(name)
.age(age)
.famillyAddress(famillyAddress)
.build();
studentInfoService.saveStudentInfo(studentInfo);
}
/**
* 根據學號查學生資訊
* @param studentId
* @return
* */
@PostMapping("/findByStudentId")
public Response findByStudentId(@RequestParam("student_id") String studentId){
try{
log.info("Get student information based on student number:{}",studentId);
if(studentId == null){
throw new StudentException(ErrorCodeAndMsg.Student_number_is_empty);
}
//學號固定為8位
if(studentId.length() != 8){
throw new StudentException(ErrorCodeAndMsg.Insufficient_student_number);
}
StudentInfo studentInfo = studentInfoService.findByStudentId(studentId);
if(studentInfo == null){
throw new StudentException(ErrorCodeAndMsg.Student_number_does_not_exist);
}
return new Response(studentInfo);
}catch (Exception e){
if(e instanceof StudentException){
throw e;
}else {
log.error("findByStudentId error:",e);
throw new StudentException(ErrorCodeAndMsg.Network_error);
}
}
}
@PostMapping("/updateFamillyAddress")
public Response updateFamillyAddress(@RequestParam("student_id") String studentId,
@RequestParam("familly_address") String famillyAddress){
studentInfoService.updateFamillyAddress(studentId,famillyAddress);
Response response = new Response();
System.out.println(response.toString());
return response;
}
}
12、application.properties配置
#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=tiger
#mybatis
#開啟mybatis駝峰命名,這樣可以將mysql中帶有下劃線的對映成駝峰命名的欄位
mybatis.configuration.map-underscore-to-camel-case=true
#datasource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tiger?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&generateSimpleParameterMetadata=true
spring.datasource.username=tiger
spring.datasource.password=tiger
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.max-idle=10
spring.datasource.max-wait=60000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validationQuery=select 'x'
三、說明
1、controller層使用註解@RestController,這樣返回結果就是json格式,而@Controller返回結果是字串
2、throw 異常
如果exception型別是自定義的異常StudentException,直接丟擲,如果是其它異常統一丟擲網路錯誤
try{
}catch (Exception e){
if(e instanceof StudentException){
throw e;
}else {
log.error("findByStudentId error:",e);
throw new StudentException(ErrorCodeAndMsg.Network_error);
}
}
3、在返回結果類新增了註解@JsonSerialize(include= JsonSerialize.Inclusion.NON_NULL)
是因為更新或者刪除操作,一般沒有返回值,我只需要知道是否更新成功或者刪除成功就OK了,如果不加這個註解
我們返回的結果中data為null!!!
{
"data": null,
"code": "0000",
"msg": "請求成功"
}
加上註解再更新資料,返回結果:
{
"code": "0000",
"msg": "請求成功"
}
因此這個註解的作用就是:返回結果中有null值,幹掉它!
四、測試結果
mysql資料庫中有一條學號為13240115的資料:
1、student_id = "13240115"時
{
"data": {
"id": 1,
"studentId": "13240115",
"name": "Tiger",
"age": 25,
"famillyAddress": "北京",
"createdDate": "2018-10-08T05:45:49.000+0000",
"updatedDate": "2018-10-09T05:36:36.000+0000"
},
"code": "0000",
"msg": "請求成功"
}
2、student_id = "13240114"時
{
"code": "0001",
"msg": "學號不存在"
}
3、student_id = "1324011",不足8位時
{
"code": "0002",
"msg": "學號長度不足"
}
4、student_id = "13240115",然後在介面中加上一行程式碼,System.out.println(1/0);
返回結果:
{
"code": "9999",
"msg": "網路錯誤,待會重試"
}
控制檯日誌:
java.lang.ArithmeticException: / by zero
at com.dl.cn.message.controller.StudentInofController.findByStudentId(StudentInofController.java:54) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) [spring-web-5.0.8.RELEASE.jar:5.0.8.RELEASE]
通過測試,發現這個小案例滿足剛開始我們提出的需求,一定還有很多其它問題,暫時沒有發現,我會及時修改,不知道有人是否看我的部落格?我只是想把自己的學習成果總結記錄下來。人可以成長為芳草,也可以長成雜莠!!!
相關文章
- 統一返回物件和異常處理(一)物件
- 統一返回物件和異常處理(二)物件
- ?laravel8 中介軟體對處理返回結果或異常進行格式統一處理Laravel
- springboot統一異常處理及返回資料的處理Spring Boot
- 反除錯:異常情況除錯
- Json序列化字串異常情況JSON字串
- 處理mysql無法啟動且啟動時服務沒報錯的異常情況MySql
- 求解!laravel配置https後的異常情況!LaravelHTTP
- springboot返回結果包裝統一返回格式Spring Boot
- 全域性統一返回結果類
- Linux學習教程-Linux下命令的一些異常情況Linux
- SpringBoot統一異常處理Spring Boot
- SpringMVC 統一異常處理SpringMVC
- python使用flask接收前端資料,處理後返回結果PythonFlask前端
- go 如何處理資料庫返回的多結果集Go資料庫
- iOS FMDB有返回結果集和無返回結果集iOS
- Solon 統一的返回結果調整
- AOP的具體實踐-簡化結果返回的處理
- spring boot 統一異常處理Spring Boot
- 統一返回結果狀態資訊類
- 封裝ResultVO實現統一返回結果封裝
- 只需一步,在Spring Boot中統一Restful API返回值格式與統一處理異常Spring BootRESTAPI
- spring中的統一異常處理Spring
- SpringBoot實現統一異常處理Spring Boot
- SpringBoot處理全域性統一異常Spring Boot
- C#自定義異常 統一異常處理C#
- SpringMVC(三)處理器方法形參繫結(繫結陣列、集合)、異常處理器、controller方法返回值SpringMVC陣列Controller
- 尋找寫程式碼感覺(六)之列表查詢介面開發及返回結果的統一處理
- spring boot配置跨域、全域性異常處理、page分頁配置、統一返回MessageResultSpring Boot跨域
- 介面異常狀態統一處理方案:優先業務端處理,再按需統一處理。
- Java程式異常處理的特殊情況Java
- SpringBoot 實戰 (十四) | 統一處理異常Spring Boot
- Spring @ControllerAdvice+@ExceptionHandler統一異常處理SpringControllerException
- SpringBoot系列——自定義統一異常處理Spring Boot
- Python錯誤處理和異常處理(二)Python
- NetCore實現全域性模型繫結異常資訊統一處理NetCore模型
- MyBatis 返回結果MyBatis
- 前端錯誤收集以及統一異常處理前端