美文网首页
Spring Boot学习进阶(https://www.imoo

Spring Boot学习进阶(https://www.imoo

作者: wbpailxt | 来源:发表于2019-02-15 21:22 被阅读2次

    1、表单验证

    现在先来看看程序存在什么设计不合理的点

       @PostMapping(value = "/girls")
        public Girl girlAdd(@RequestParam("cupSize") String cupSize,
                            @RequestParam("age") Integer age){
            Girl girl = new Girl();
            girl.setAge(age);
            girl.setCupSize(cupSize);
            return girlRepository.save(girl);
        }
    

    若一个女生有很多种属性,在方法参数上就得加很多种参数。

    @PostMapping(value = "/girls")
        public Girl girlAdd(Girl girl){
            girl.setAge(girl.getAge());
            girl.setCupSize(girl.getCupSize());
            return girlRepository.save(girl);
        }
    

    修改成如上。Hibernate会看包的body里携带的参数是否和Girl类的私有变量同名,同名则调用setter为实例化的girl赋值。
    进入正题:怎么实现表单验证?
    Girl类的私有变量添加@Min注解,value为最低值,message为不符合最低值时返回的错误信息。

    @Min(value = 18,message = "未成年少女不许进入数据库")
        private Integer age;
    

    为形参添加@Valid注解,验证结果会返回给bindingResult

     @PostMapping(value = "/girls")
        public Girl girlAdd(@Valid Girl girl,BindingResult bindingResult){
            if(bindingResult.hasErrors()){
                System.out.println(bindingResult.getFieldError().getDefaultMessage());
                return null;
            }
            girl.setAge(girl.getAge());
            girl.setCupSize(girl.getCupSize());
            return girlRepository.save(girl);
        }
    

    2使用AOP处理请求

    什么是AOP?
    AOP是一种编程范式,与语言无关,是一种程序设计思想。
    面向对象关注的是将需求功能垂直划分为不同的、并且相对独立的,它会封装成良好的类,并且它们有属于自己的行为。
    面向切面技术则恰恰相反。
    它利用的是一种横切的技术,将面向对象构建的庞大的类的体系进行水平的切割,并且会将那些影响了多个类的公共行为封装成一个可重用的模块,这个模块称为切面。
    AOP的关键思想是将通用逻辑从业务逻辑中分离出来。
    AOP讲解例子:AOP统一处理请求日志

    • 添加依赖


      图片.png
    • 新建包含通用逻辑的HttpAspect 类
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class HttpAspect {
    
        @Before("execution(public * com.imooc.controller.GirlController.*(..))")
        public void log(){
            System.out.println(1111111111);
        }
    
        @After("execution(public * com.imooc.controller.GirlController.*(..))")
        public void doAfter(){
            System.out.println(222222222);
        }
    }
    

    @Before注解的方法在切面方法执行之前就已经执行了。
    @After注解的方法在切面方法执行之后执行。
    ..表示只要是这个方法,任何参数都会被拦截

    • HttpAspect类代码再精简一下。
    package com.imooc.aspect;
    
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class HttpAspect {
    
        @Pointcut("execution(public * com.imooc.controller.GirlController.*(..))")//指明切面
        public void log(){//切面别名叫log()
        }
    
        @Before("log()")//在名叫log()的切面之前执行
        public void doBefore(){
            System.out.println(111111111);
        }
    
        @After("log()")//在名叫log()的切面之后执行
        public void doAfter(){
            System.out.println(222222222);
        }
    }
    
    • 换作使用log打印
    package com.imooc.aspect;
    
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    
    @Aspect
    @Component
    public class HttpAspect {
    
        private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
    
        @Pointcut("execution(public * com.imooc.controller.GirlController.*(..))")//指明切面
        public void log(){//切面别名叫log()
        }
    
        @Before("log()")//在名叫log()的切面之前执行
        public void doBefore(){
            logger.info("111111111");
        }
    
        @After("log()")//在名叫log()的切面之后执行
        public void doAfter(){
            logger.info("222222222");
        }
    }
    
    • 在切面方法内也用logger打印
    @RestController
    public class GirlController {
    
        private final static Logger logger = LoggerFactory.getLogger(GirlController.class);
    
        @Autowired
        private GirlRepository girlRepository;
    
        @Autowired
        private GirlService girlService;
    
        /**
         * 查询所有女生列表
         * @return
         */
        @GetMapping(value = "/girls")
        public List<Girl> girlList(){
            logger.info("girlList");
            return girlRepository.findAll();
        }
    
    • 改造@Before注解的方法,使其记录Http请求。
    package com.imooc.aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    
    
    @Aspect
    @Component
    public class HttpAspect {
    
        private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
    
        @Pointcut("execution(public * com.imooc.controller.GirlController.*(..))")//指明切面
        public void log(){//切面别名叫log()
        }
    
        @Before("log()")//在名叫log()的切面之前执行
        public void doBefore(JoinPoint joinPoint){
            ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    
            //url
            logger.info("url={}",request.getRequestURI());
    
            //请求method
            logger.info("method={}",request.getMethod());
    
            //ip
            logger.info("ip={}",request.getRemoteAddr());
    
            //类方法
            logger.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName() + "\\" + joinPoint.getSignature().getName());//getDeclaringTypeName得到包名,getName得到方法名
    
            //传过来的参数
            logger.info("args={}",joinPoint.getArgs());
        }
    
        @After("log()")//在名叫log()的切面之后执行
        public void doAfter(){
            logger.info("222222222");
        }
    }
    

    效果示例


    图片.png
    2019-02-15 13:52:53.819  INFO 12712 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : url=/girls/14
    2019-02-15 13:52:53.819  INFO 12712 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : method=GET
    2019-02-15 13:52:53.819  INFO 12712 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : ip=0:0:0:0:0:0:0:1
    2019-02-15 13:52:53.819  INFO 12712 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : class_method=com.imooc.controller.GirlController\girlFindOne
    2019-02-15 13:52:53.819  INFO 12712 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : args=14
    Hibernate: select girl0_.id as id1_0_0_, girl0_.age as age2_0_0_, girl0_.cup_size as cup_size3_0_0_ from girl girl0_ where girl0_.id=?
    2019-02-15 13:52:53.832  INFO 12712 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : 222222222
    
    • 获取返回的内容

      即获取 图片.png
    package com.imooc.aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    
    
    @Aspect
    @Component
    public class HttpAspect {
    
        private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
    
        @Pointcut("execution(public * com.imooc.controller.GirlController.*(..))")//指明切面
        public void log(){//切面别名叫log()
        }
        @AfterReturning(returning = "object",pointcut = "log()")//名叫log()的切面若有返回值,则作为实参传给object形参
        public void doAgterReturning(Object object){
            logger.info("response={}",object);
        }
    }
    

    效果示例:
    没有返回值的切面(public void girlDelete(@PathVariable("id") Integer id))


    图片.png
    2019-02-15 14:27:46.127  INFO 9120 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : url=/girls/14
    2019-02-15 14:27:46.127  INFO 9120 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : method=DELETE
    2019-02-15 14:27:46.127  INFO 9120 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : ip=0:0:0:0:0:0:0:1
    2019-02-15 14:27:46.127  INFO 9120 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : class_method=com.imooc.controller.GirlController\girlDelete
    2019-02-15 14:27:46.127  INFO 9120 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : args=14
    Hibernate: select girl0_.id as id1_0_0_, girl0_.age as age2_0_0_, girl0_.cup_size as cup_size3_0_0_ from girl girl0_ where girl0_.id=?
    Hibernate: delete from girl where id=?
    2019-02-15 14:27:46.245  INFO 9120 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : 222222222
    2019-02-15 14:27:46.246  INFO 9120 --- [nio-8080-exec-5] com.imooc.aspect.HttpAspect              : response=null
    

    由于删除方法girlDelete没有返回值,故@doAfterReturning注解的doAfterReturning方法没有被传参,Object是null,所以response=null
    有返回值的切面(public Girl girlFindOne(@PathVariable("id") Integer id))


    图片.png
    2019-02-15 14:36:17.723  INFO 9120 --- [nio-8080-exec-8] com.imooc.aspect.HttpAspect              : url=/girls/2
    2019-02-15 14:36:17.723  INFO 9120 --- [nio-8080-exec-8] com.imooc.aspect.HttpAspect              : method=GET
    2019-02-15 14:36:17.723  INFO 9120 --- [nio-8080-exec-8] com.imooc.aspect.HttpAspect              : ip=0:0:0:0:0:0:0:1
    2019-02-15 14:36:17.723  INFO 9120 --- [nio-8080-exec-8] com.imooc.aspect.HttpAspect              : class_method=com.imooc.controller.GirlController\girlFindOne
    2019-02-15 14:36:17.723  INFO 9120 --- [nio-8080-exec-8] com.imooc.aspect.HttpAspect              : args=2
    Hibernate: select girl0_.id as id1_0_0_, girl0_.age as age2_0_0_, girl0_.cup_size as cup_size3_0_0_ from girl girl0_ where girl0_.id=?
    2019-02-15 14:36:17.730  INFO 9120 --- [nio-8080-exec-8] com.imooc.aspect.HttpAspect              : 222222222
    2019-02-15 14:36:17.730  INFO 9120 --- [nio-8080-exec-8] com.imooc.aspect.HttpAspect              : response={"id":2,"cupSize":"B","age":13}
    

    3、统一异常处理

    视频中Girl类(表)多了一个私有变量money(字段),Girl类改动如下

    import javax.validation.constraints.NotNull;
    public class Girl {
        ···
        @NotNull(message = "金额必传")
        private Double money;
        ···
    }
    
    • 先来看看这个程序抛出的系统异常 图片.png

      返回的错误:

    2019-02-15 16:14:11.774 ERROR 9880 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
    
    java.lang.NullPointerException: null
    
    • 将错误信息返回给前端
      增加一个女生报错时,错误信息是显示在空值台的
    2019-02-15 17:03:19.598  INFO 9880 --- [nio-8080-exec-4] com.imooc.controller.GirlController      : 金额必传
    

    现要将错误信息返回给前端,将girlAdd方法改动如下

    /**
        * 添加一个女生
        * @return
        */
       @PostMapping(value = "/girls")
       public Object girlAdd(@Valid Girl girl,BindingResult bindingResult){
           if(bindingResult.hasErrors()){
               return (bindingResult.getFieldError().getDefaultMessage());
           }
           girl.setAge(girl.getAge());
           girl.setCupSize(girl.getCupSize());
           return girlRepository.save(girl);
       }
    

    成功添加时返回给前端的信息


    图片.png

    金额为空时不能添加一行数据进girl表


    图片.png

    虽然把错误信息返回给前端了,但是又出现了一个问题,成功信息和错误信息的格式不一致。

    • 将成功信息和错误信息的格式一致


      图片.png

      http请求返回的最外层对象

    package com.imooc.domain;
    
    /**
     * http请求返回的最外层对象
     */
    public class Result<T> {
    
        /** 错误码 */
        private Integer code;
    
        /** 提示信息 */
        private String msg;
    
        /** 具体的内容 */
        private T data;
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    }
    

    改造girlAdd方法

    @PostMapping(value = "/girls")
        public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult){
            if(bindingResult.hasErrors()){
                Result result = new Result();
                result.setCode(1);
                result.setMsg(bindingResult.getFieldError().getDefaultMessage());
                result.setData(null);
                return result;
            }
            girl.setAge(girl.getAge());
            girl.setCupSize(girl.getCupSize());
    
            Result result = new Result();
            result.setCode(0);
            result.setMsg("成功");
            result.setData(girlRepository.save(girl));
            return result;
        }
    

    money为空时返回给前端的信息


    图片.png

    成功添加一行数据进入girl表时返回给前端的信息


    图片.png
    • 写一个工具类ResultUtil,将返回结果逻辑封装起来
    package com.imooc.utils;
    
    import com.imooc.domain.Result;
    
    public class ResultUtil {
        public static Result success(Object object){
            Result result = new Result();
            result.setCode(0);
            result.setMsg("成功");
            result.setData(object);
            return result;
        }
    
        public static Result success(){
            return success(null);
        }
        public static Result error(Integer code,String msg){
            Result result = new Result();
            result.setCode(code);
            result.setMsg(msg);
            result.setData(null);
            return result;
        }
    }
    

    修改girlAdd方法

    @PostMapping(value = "/girls")
        public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult){
            if(bindingResult.hasErrors()){
                return  ResultUtil.error(1,bindingResult.getFieldError().getDefaultMessage());
            }
            girl.setAge(girl.getAge());
            girl.setCupSize(girl.getCupSize());
    
            return ResultUtil.success(girlRepository.save(girl));
        }
    
    • 一个运用统一异常处理的例子 图片.png
      逻辑在设计规范中都是放在service的
    package com.imooc.service;
    
    import com.imooc.domain.Girl;
    import com.imooc.repository.GirlRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    @Service
    public class GirlService {
    
        @Autowired
        private GirlRepository girlRepository;
    
        @Transactional
        public void insertTwo(){
            Girl girlA = new Girl();
            girlA.setAge(18);
            girlA.setCupSize("A");
            girlRepository.save(girlA);
    
            Girl girlB = new Girl();
            girlB.setAge(19);
            girlB.setCupSize("B");
            girlRepository.save(girlB);
        }
    演示效果及流程解释
    ![图片.png](https://img.haomeiwen.com/i4031144/b4f70d9ab4b5296c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
        public void getAge(Integer id) throws Exception{
            Girl girl = girlRepository.findById(id).get();
            Integer age = girl.getAge();
            if(age<10){
                //返回“你还在上小学吧”
                throw new Exception("你还在上小学吧");
            }else if (age > 10 && age < 16){
                //返回“你可能在上初中吧”
                throw new Exception("你可能在上初中吧");
            }
        }
    }
    

    GirlController类中添加getAge方法

    package com.imooc.controller;
    
    import com.imooc.domain.Girl;
    import com.imooc.domain.Result;
    import com.imooc.repository.GirlRepository;
    import com.imooc.service.GirlService;
    import com.imooc.utils.ResultUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.validation.BindingResult;
    import org.springframework.web.bind.annotation.*;
    
    import javax.validation.Valid;
    import java.util.List;
    
    @RestController
    public class GirlController {
    
        private final static Logger logger = LoggerFactory.getLogger(GirlController.class);
    
        @Autowired
        private GirlRepository girlRepository;
    
        @Autowired
        private GirlService girlService;
    
        /**
         * 查询所有女生列表
         * @return
         */
        @GetMapping(value = "/girls")
        public List<Girl> girlList(){
            logger.info("girlList");
            return girlRepository.findAll();
        }
    
        /**
         * 添加一个女生
         * @return
         */
        @PostMapping(value = "/girls")
        public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult){
            if(bindingResult.hasErrors()){
                return  ResultUtil.error(1,bindingResult.getFieldError().getDefaultMessage());
            }
            girl.setAge(girl.getAge());
            girl.setCupSize(girl.getCupSize());
    
            return ResultUtil.success(girlRepository.save(girl));
        }
    
        //查询一个女生
        @GetMapping(value = "/girls/{id}")
        public Girl girlFindOne(@PathVariable("id") Integer id){
            Girl girl = null;
            try {
                girl = girlRepository.findById(id).get();
                return girl;
            }
            catch (Exception e){
                return girl;
            }
        }
    
        //更新
        @PutMapping(value = "/girls/{id}")
        public Girl girlUpdate(@PathVariable("id") Integer id,
                               @RequestParam("cupSize") String cupSize,
                               @RequestParam("age") Integer age){
            Girl girl = new Girl();
            girl.setId(id);
            girl.setCupSize(cupSize);
            girl.setAge(age);
    
            return girlRepository.save(girl);
        }
    
        //删除
        @DeleteMapping(value = "/girls/{id}")
        public void girlDelete(@PathVariable("id") Integer id){
            girlRepository.deleteById(id);
        }
    
        //通过年龄查询女生列表
        @GetMapping(value = "/girls/age/{age}")
        public List<Girl> girlListByAge(@PathVariable("age") Integer age){
            return girlRepository.findByAge(age);
        }
    
        @PostMapping(value = "/girls/two")
        public void girlTwo(){
            girlService.insertTwo();
        }
    
        @GetMapping(value = "/girls/getAge/{id}")
        public void getAge(@PathVariable("id") Integer id) throws Exception{
            girlService.getAge(id);
        }
    }
    

    演示效果及流程解释


    图片.png

    现在还是会有返回给前端的数据不一致的问题,我们依旧希望是code,msg,data的格式。
    直接往外抛出错误会出现上图中的结果,其实我们可以对这个异常进行一个捕获,然后取到我们希望拿到的内容,再给它封装返回给浏览器。

    • 新建一个捕获异常的ExceptionHandle类
    package com.imooc.Handle;
    
    import com.imooc.domain.Result;
    import com.imooc.utils.ResultUtil;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * 最外层捕获
     */
    @ControllerAdvice//捕获异常的类需要添加这个注解
    public class ExceptionHandle{
    
        //写一个捕获异常,且捕获后返回给浏览的方法,返回给浏览器Result类型的数据
        @ExceptionHandler(value = Exception.class)//声明捕获哪个异常类
        @ResponseBody//由于我们返回给浏览器那边是一个json格式。类上又没有RestController注解,所以这个地方需要写明@ResponseBody
        public Result handle(Exception e){
            return ResultUtil.error(100,e.getMessage());
        }
    
    }
    
    图片.png

    “你还在上小学吧”和“可能在上初中吧”错误应该是不同的code,但现在都是100


    图片.png

    因为GirlService类往外抛Exception错误时只能传String message,


    图片.png
    在最外层捕获ExceptionHandle类里也就只能把code写死100了。
    图片.png
    • 这时候需要我们自己来写一个自己的Exception类:GirlException
    package com.imooc.exception;
    
    public class GirlException extends RuntimeException{//注意需要继承一个runtimeException,因为Spring框架只会对你抛出的runtimeException才会进行事物回滚,如果抛出Exception是不会进行事物回滚的
        private Integer code;
    
        public GirlException(Integer code,String message){
            super(message);
            this.code = code;
        }
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    }
    

    修改GirlService类的getAge方法在抛出异常时的类型为GirlException

    public void getAge(Integer id) throws Exception{
            Girl girl = girlRepository.findById(id).get();
            Integer age = girl.getAge();
            if(age<10){
                //返回“你还在上小学吧”
                throw new GirlException(100,"你还在上小学吧");
            }else if (age > 10 && age < 16){
                //返回“你可能在上初中吧”
                throw new GirlException(101,"你可能在上初中吧");
            }
        }
    

    修改最外层捕获类ExceptionHandle的handle方法

    /**
     * 最外层捕获
     */
    @ControllerAdvice//捕获异常的类需要添加这个注解
    public class ExceptionHandle{
    
        //写一个捕获异常,且捕获后返回给浏览的方法,返回给浏览器Result类型的数据
        @ExceptionHandler(value = Exception.class)//声明捕获哪个异常类
        @ResponseBody//由于我们返回给浏览器那边是一个json格式。类上又没有RestController注解,所以这个地方需要写明@ResponseBody
        public Result handle(Exception e){//抛出的异常作为实参传给形参e
            if(e instanceof GirlException){
                GirlException girlException = (GirlException)e;
                return ResultUtil.error(girlException.getCode(),girlException.getMessage());
            }else{
                return ResultUtil.error(-1,"系统的错误,不在GirlServce预期之内的异常");
            }
    
        }
    }
    

    效果演示:
    在“你可能在上初中吧”该种类型的错误的情况时,其code是101


    图片.png

    getAge没有抛出错误(age为18)->getAge没有抛出错误->执行doAgterReturning方法->null.toString报错->被最外层ExceptionHandle捕获->返回Reslut


    图片.png
    • 将系统类型的错误打印在控制台以便排除错误
    /**
     * 最外层捕获
     */
    @ControllerAdvice//捕获异常的类需要添加这个注解
    public class ExceptionHandle{
    
        private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
    
        //写一个捕获异常,且捕获后返回给浏览的方法,返回给浏览器Result类型的数据
        @ExceptionHandler(value = Exception.class)//声明捕获哪个异常类
        @ResponseBody//由于我们返回给浏览器那边是一个json格式。类上又没有RestController注解,所以这个地方需要写明@ResponseBody
        public Result handle(Exception e){//抛出的异常作为实参传给形参e
            if(e instanceof GirlException){
                GirlException girlException = (GirlException)e;
                return ResultUtil.error(girlException.getCode(),girlException.getMessage());
            }else{
                logger.error("【系统异常】{}",e);
                return ResultUtil.error(-1,"系统的错误,不在GirlServce预期之内的异常");
            }
    
        }
    }
    

    效果演示:
    在控制台打印出了异常

    2019-02-15 20:45:47.638 ERROR 9516 --- [nio-8080-exec-1] com.imooc.Handle.ExceptionHandle         : 【系统异常】{}
    
    java.lang.NullPointerException: null
        at com.imooc.aspect.HttpAspect.doAgterReturning(HttpAspect.java:52) ~[classes/:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:626) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.aop.aspectj.AspectJAfterReturningAdvice.afterReturning(AspectJAfterReturningAdvice.java:66) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:56) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.4.RELEASE.jar:5.1.4.RELEASE]
        at ...(部分)
    
    • 用枚举维护错误类型列表
      定义枚举
    package com.imooc.enums;
    
    public enum ResultEnum {
        UNKNOWN_ERROR(-1,"位置错误"),
        SUCCESS(0,"成功"),
        PRIMARY_SCHOOL(100,"你可能还在上小学"),
        MIDDLE_SCHOOL(101,"你可能在上初中"),
        ;
        private Integer code;
    
        private String msg;
    
        ResultEnum(Integer code,String msg){
            this.code = code;
            this.msg = msg;
        }
    
        public Integer getCode() {
            return code;
        }
    
        public String getMsg() {
            return msg;
        }
    }
    

    修改GirlService的getAge方法

     public void getAge(Integer id) throws Exception{
            Girl girl = girlRepository.findById(id).get();
            Integer age = girl.getAge();
            if(age<10){
                //返回“你还在上小学吧”
                throw new GirlException(ResultEnum.PRIMARY_SCHOOL);
            }else if (age > 10 && age < 16){
                //返回“你可能在上初中吧”
                throw new GirlException(ResultEnum.MIDDLE_SCHOOL);
            }
        }
    

    修改GirlException类构造方法

    package com.imooc.exception;
    
    import com.imooc.enums.ResultEnum;
    
    public class GirlException extends RuntimeException{//注意需要继承一个runtimeException,因为Spring框架只会对你抛出的runtimeException才会进行事物回滚,如果抛出Exception是不会进行事物回滚的
        private Integer code;
    
        public GirlException(ResultEnum resultEnum){
            super(resultEnum.getMsg());
            this.code = resultEnum.getCode();
        }
    
        public Integer getCode() {
            return code;
        }
    
        public void setCode(Integer code) {
            this.code = code;
        }
    }
    

    相关文章

      网友评论

          本文标题:Spring Boot学习进阶(https://www.imoo

          本文链接:https://www.haomeiwen.com/subject/nrtpeqtx.html