SpringBoot进阶之Web笔记

Web进阶

一、使用@Vaild表单验证

1.在Girl.java实体中写入的年龄age天界注解@Min(value = 18,message=”未成年”)设计最小年龄验证
@Min(value = 18,message = “未成年”)
private Integer age;
然后在GirlController.java中写入:
@PostMapping(value = “/girls”)
public Girl girlAdd(@Valid Girl girl, BindingResult bindingResult){
//bindingResult用来存放验证结果
if (bindingResult.hasErrors()){ System.out.println(bindingResult.getFieldError().getDefaultMessage());
return null;
}

二、使用AOP统一处理请求日志

1. 什么是AOP?

AOP(面向切面) OOP(面向对象) POP(面向过程)
同一件事(下雨了额,打开伞),不同实现
面向过程:假如下雨了,我打开了伞
面向对象:天气(对象)->下雨(方法) 我(对象)->打伞(方法)
从面向过程到面向对象,就是换个角度看世界,换个姿势处理问题
AOP是一种编程范式,与语言无关,是一种程序设计思想,将通用逻辑藏业务逻辑中分离出来
从上往下看:
这里写图片描述
从左往右看:
这里写图片描述

2. 使用AOP

(1)pom文件中注入依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

(2)往常做法是在启动类GirlApplication的类名上加@SpringBootApplication注解,但是AOP不需要加
(3)在main的java下建立处理文件aspect包,再在报下建立HttpAspect类,对Controller中的方法进行拦截

@Aspect
@Component //将文件引入到Spring容器里去
public class HttpAspect {
    //写逻辑处理代码,我们希望在HTTP请求到方法之前就将他记录下来
    //Before表示在方法执行之前就拦截下来。girlList(..)表示不管里边是什么都会被拦截
    @Before("execution(public * com.demo.girl.controller.GirlController.girlList(..))")
    public void log(){
        System.out.println("**********");
    }
@After("log()")
public void doAfter("execution(public * com.demo.girl.controller.GirlController.girlList(..))"){
    System.out.println("after");
}
}

为简化代码,减少重复的代码多次写,可以利用@Pointcut注解,注解一个公用方法,在随后的After和Before中不再需要多次写,如下

@Pointcut("execution(public * com.demo.girl.controller.GirlController.*(..))")
public void log(){
   System.out.println("Before");
}
public void doBefore(){
    System.out.println("Before");
}
@After("log()")
public void doAfter(){
    System.out.println("after");
}

此外,输出方法也可以由System.out.println(” “)通过
private final static Logger logger = LoggerFactory.getLogger((HttpAspect.class));
语句变成logger.info(“Before”);这样在打印时会将日志的详细信息都打印出来。
(4)将(3)的方法拦截输出变为对HTTP请求的拦截的输出,包括对URL,请求的方法,IP,类方法,参数的拦截,写在doBefore方法中,如下:

@Before("log()")
public void doBefore(JoinPoint joinPoint){  //传入joinPoint以拦截获取方法
    /*System.out.println("Before");
    logger.info("Before");*/
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();//(ServletRequestAttributes强制转换)
    HttpServletRequest request = attributes.getRequest();
    //url
    logger.info("url={}",request.getRequestURL());
    //method
    logger.info("method={}",request.getMethod());
    //ip
    logger.info("ip={}",request.getRemoteAddr());
    //类方法  获取类名+类方法
    logger.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName());
    //参数
    logger.info("args={}",joinPoint.getArgs());
}

结果为:
这里写图片描述
(5)将URL请求得到的数据库中的结果内容输出在控制台
在domain中的Girl.java中写入toString方法

@Override
public String toString() {
    return "Girl{" +
            "id=" + id +
            ", cs='" + cs + '\'' +
            ", age=" + age +
            ", money=" + money +
            '}';
}

再在HttpAspect.java中写入如下方法,
//用来将URL请求得到的数据库中的内容输出在控制台

@AfterReturning(returning = "object",pointcut = "log()")//传入两个参数
public void doAfterReturening(Object object){
    logger.info("response={}",object.toString());
}

结果在控制台打印出来
这里写图片描述

三、统一异常处理

1、添加女生信息时,对数据的非空性进行判断,如果数据正确,返回正确的信息,如果错误则返回错误的信息,信息包括错误码code,错误信息msg,错误的数据data,在domain包中定义Result.java,并加入get和set方法。

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

再建立一个util的包,其中建立ResultUtil.java类,定义成功方法和错误时的方法

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);
        return result;
    }
}

然后在GirlController.java中添加女生信息处加入判断,成功时调用ResultUtil的成功success方法,错误则调用错误error方法.

@PostMapping(value = "/girls")
public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult){
    if (bindingResult.hasErrors()){
       return                    ResultUtil.error(1,bindingResult.getFieldError().getDefaultMessage());
    }
    girl.setCs(girl.getCs());
    girl.setAge(girl.getAge());

  return ResultUtil.success(girlRepository.save(girl));
}
  1. 异常捕获,抛出异常
    GirlServic.java中写逻辑判断,并抛出异常
public void getAge(Integer id) throws Exception{
    Girl  girl = girlRepository.findOne(id);
    Integer age = girl.getAge();
    if(age < 10){
       //返回"你还在上小学 ";
        throw new Exception("你还在上小学吧");
    }else if(age > 10 && age < 16){
        //返回"你可能在上初中 " ;
        throw new Exception("你可能在上初中");
    }
}

创建handle包,其中建立ExceptionHandle.java类,对异常进行捕获

@ControllerAdvice
public class ExceptionHandle {
    @ExceptionHandler(value = Exception.class) //要捕获的类为Exception这个类
    @ResponseBody
    public Result handle(Exception e){ //由handle这个类来处理这些异常
       return ResultUtil.error(100,e.getMessage());
    }
}

此外,在GirlController中调用service时也要抛出异常。

@GetMapping(value = "girls/getAge/{id}")
public void getAge(@PathVariable("id") Integer id)throws Exception{
    girlService.getAge(id);
}

3,为了使小于10岁和小于16岁抛出的异常的code不一样,有所区分,故自定义异常
创建exception包,其中创建GirlException.java

//RuntimeException继承自Exception,Spring框架只对抛出的异常是RuntimeException才会进行事务回滚,若为Exception不回事务回滚
public class GirlException extends RuntimeException {
    private Integer code;
     //写一个构造方法,传入两个参数
    public GirlException(ResultEmum resultEmum){
        super(resultEmum.getMsg());//父类的构造方法本身就会传一个message
        this.code = resultEmum.getCode();
    }

        public Integer getCode() {
        return code;
    }

    public void setCeode(Integer ceode) {
        this.code = ceode;
    }
}

4、 值得学习的是:为了统一管理错误的code,使用枚举统一管理code,和msg,所以创建emums包,在其中创建ResultEmum.java,注意创建的时候类型为枚举型不是类。在其中将其错位类型进行枚举,而且其中的code和msg只需要get方法即可,不需要set方法,因为已经在枚举里枚举了所有可能的类型。之后如第3步一样直接进行调用就可以了。这样的话方便以后修改时,直接修改一个地方就可以,不需要全文进行搜索进行修改。注意枚举时用的是逗号。

public enum ResultEmum
{
    UNKNOM_ERROR(-1,"位置错误"),
    SUCCESS(0,"成功"),
    PRIMARY_SCHOOL(100,"你可能还在上小学"),
    MIDDLE_SCHOOL(101,"你可能在还是那个初中"), ;
    private Integer code;
    private  String  msg;
    ResultEmum (Integer code ,String msg){
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值