3.4 controller接口
@RestController @RequestMapping("/books") public class BookController { @Autowired private BookService service; @PostMapping // @RequestBody注解用于接收JSON格式数据 POST请求的数据用@RequestParam注解接收 public int addBook(@RequestBody Book book) { return service.addBook(book); } @PutMapping public int updateBookById(@RequestBody Book book) { return service.updateBookById(book); } @DeleteMapping("/{id}") public int deleteBookById(@PathVariable Integer id) { return service.deleteBookById(id); } @GetMapping("/{id}") public Book getBookById(@PathVariable Integer id) { return service.getBookById(id); } @GetMapping public List<Book> selectAll() { return service.selectAll(); } }
表现层接口测试:使用Postman进行测试
四、表现层数据封装
因为各种对数据库的增删改查操作返回的结果不一定相同,表现层返回给前端人员的数据可能是int类型,对象类型,数组类型,……这就需要统一格式,通过对象将这些返回值封装在属性里。此外,通过状态码告诉前端人员操作是否成功。
下面是表现层数据封装模型:
/** * 表现层数据封装模型-返回给前端的数据都是Result对象类型 */ public class Result { /** * 返回的状态-成功与失败,何种操作 */ private Integer code; /** * 返回的数据 */ private Object data; /** * 成功或失败的响应信息 */ private String msg; public Result() { } /** * 不带消息 * * @param data * @param code */ public Result(Integer code, Object data) { this.data = data; this.code = code; } /** * 带消息 * * @param data * @param code * @param msg */ public Result(Integer code, Object data, String msg) { this.data = data; this.code = code; this.msg = msg; } // getter setter 已省略
状态码模型:
/** * 定义增删改查操作成功或者失败的状态码-8种 */ public class Code { /** * 结尾1代表成功,0代表失败 */ public static final Integer ADD_OK = 20011; public static final Integer ADD_ERR = 20010; public static final Integer DELETE_OK = 20021; public static final Integer DELETE_ERR = 20020; public static final Integer UPDATE_OK = 20031; public static final Integer UPDATE_ERR = 20030; public static final Integer SELECT_OK = 20041; public static final Integer SELECT_ERR = 20040; }
从而controller层返回的都是Result对象。
五、异常处理器
5.1 异常处理
(1)可能出现异常之处
(2)解决步骤
将所有的异常都抛出到表现层,进行集中处理,但是肯定不能放到表现层控制器
上,因为不同异常处理方案不同,且会让代码臃肿,其实是使用Spring的AOP思想。
(3)异常处理类
@RestControllerAdvice // 将这个类作为异常处理器通知类 public class ProjectExceptionAdvice { @ExceptionHandler({Exception.class}) // 拦截所有异常 public Result doException(Exception e) { System.out.println("error ..."); return new Result(500,null,"error"); } }
5.2 项目异常处理步骤
(1)异常分类及处理方案
业务异常 | 系统异常 | 其他异常 |
用户操作产生的异常 | 项目运行中可预计不可避免的异常(如停电,系统宕机) | 编程人员无法预计的异常 |
发送对应消息给用户,提示规范操作 | 发送固定消息给用户,安抚用户(如您的网络状态不佳,请稍后重试);发送特定消息给运维人员;记录日志 | 和系统异常处理相似 |
(2)具体代码实现
1.新建自定义系统异常和业务异常类,两个类非常相似
public class SystemException extends RuntimeException { /** * 加入异常编号帮助识别是哪一种异常 */ private Integer code; public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public SystemException(Integer code, String message) { super(message); this.code = code; } public SystemException(Integer code, String message, Throwable cause) { super(message, cause); this.code = code; } }
public class BusinessException extends RuntimeException { /** * 加入异常编号帮助识别是哪一种异常 */ private Integer code; public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public BusinessException(Integer code, String message) { super(message); this.code = code; } public BusinessException(Integer code, String message, Throwable cause) { super(message, cause); this.code = code; } }
2.在Code类中增加了几种状态码:
/** * 异常状态码(可以细分) */ public static final Integer SYSTEM_ERR = 50001; public static final Integer SYSTEM_TIMEOUT_ERR = 50002; public static final Integer BUSINESS_ERR = 60002; public static final Integer SYSTEM_UNKNOWN_ERR = 59999;
3.在业务层BookServiceImpl类分别模拟业务异常和系统异常:
@Override public Book getBookById(Integer id) { // 模拟业务异常 if (id == 1) { throw new BusinessException(Code.BUSINESS_ERR, "ban!"); } // 模拟系统异常 try { int i = 1 / 0; } catch (Exception e) { throw new SystemException(Code.SYSTEM_TIMEOUT_ERR, "Time out!", e); // 将可能出现的异常进行包装,转换为自定义异常 } Book book = mapper.getBookById(id); return book; }
4.在异常通知类中添加这两种异常处理方法:
@RestControllerAdvice // 将这个类作为异常处理器通知类 public class ProjectExceptionAdvice { @ExceptionHandler({SystemException.class}) // 拦截系统异常 public Result doSystemException(SystemException e) { // 1.记录日志 // 2.发送消息给运维 // 3.发送邮件给开发人员 System.out.println("SystemException ..."); return new Result(e.getCode(), null, e.getMessage()); } @ExceptionHandler({BusinessException.class}) // 拦截业务异常 public Result doBusinessException(BusinessException e) { System.out.println("BusinessException ..."); return new Result(e.getCode(), null, e.getMessage()); } @ExceptionHandler({Exception.class}) // 拦截未知异常 public Result doException(Exception e) { // 1.记录日志 // 2.发送消息给运维 // 3.发送邮件给开发人员 System.out.println("Exception ..."); return new Result(Code.SYSTEM_UNKNOWN_ERR, null, "System busy ..."); } }
5.重启服务器,使用Postman测试: