[Blog]后端代码分析

本文分析了一个Spring Boot后端项目的代码结构,主要涉及`src/main/java`下的`common`、`exception`、`lang`、`util`、`config`、`shiro`、`entity`、`mapper`、`controller`、`service`目录。重点讲解了全局异常处理类的使用,包括如何处理Shiro认证授权、数据校验和其他运行时异常。此外,还介绍了Shiro配置、JWT工具类以及数据传输对象(DTO)的角色。
摘要由CSDN通过智能技术生成

项目结构

  • 打包后的代码结构如图所示

在这里插入图片描述

  • .idea目录.存放项目的配置信息,包括历史记录,版本控制信息等
    在这里插入图片描述
    • 其中 libraries目录中存放的都是maven依赖
      在这里插入图片描述

src目录源码分析

在这里插入图片描述

main目录

在这里插入图片描述

java目录

包com/markerhub下
在这里插入图片描述

common

在这里插入图片描述

dto
  • LoginDto.java

  • DTO(Data Transfer Object,数据传送对象)

  • DTO是一个普通的Java类,它封装了要传送的批量的数据。当客户端需要读取服务器端的数据的时候,服务器端将数据封装在DTO中,这样客户端就可以在一个网络调用中获得它需要的所有数据
    在这里插入图片描述

  • LoginDto用来封装登录用户的信息用以传输给客户端

      package com.markerhub.common.dto;
      import lombok.Data;
      
      import javax.validation.constraints.NotBlank;
      import java.io.Serializable;
      
      @Data
          public class LoginDto implements Serializable {
    
          @NotBlank(message = "昵称不能为空")
          private String username;
    
          @NotBlank(message = "密码不能为空")
          private String password;
      }
    
exception
  • 全局异常处理类,用来捕捉全局异常
    在这里插入图片描述

      package com.markerhub.common.exception;
      
      import com.markerhub.common.lang.Result;
      import lombok.extern.slf4j.Slf4j;
      import org.apache.shiro.ShiroException;
      import org.springframework.http.HttpStatus;
      import org.springframework.validation.BindingResult;
      import org.springframework.validation.ObjectError;
      import org.springframework.web.bind.MethodArgumentNotValidException;
      import org.springframework.web.bind.annotation.ExceptionHandler;
      import org.springframework.web.bind.annotation.ResponseStatus;
      import org.springframework.web.bind.annotation.RestControllerAdvice;
    
      @Slf4j
      @RestControllerAdvice
      public class GlobalExceptionHandler {
    
          @ResponseStatus(HttpStatus.UNAUTHORIZED)
          //此处ExceptionHandlerd的value指定的类是org.apache.shiro.ShiroException所提供的而不是自定义的
          @ExceptionHandler(value = ShiroException.class)
          public Result handler(ShiroException e) {
              log.error("运行时异常:----------------{}", e);
              return Result.fail(401, e.getMessage(), null);
          }
    
          @ResponseStatus(HttpStatus.BAD_REQUEST)
          @ExceptionHandler(value = MethodArgumentNotValidException.class)
          public Result handler(MethodArgumentNotValidException e) {
              log.error("实体校验异常:----------------{}", e);
              BindingResult bindingResult = e.getBindingResult();
              ObjectError objectError = bindingResult.getAllErrors().stream().findFirst().get();
    
              return Result.fail(objectError.getDefaultMessage());
          }
    
          @ResponseStatus(HttpStatus.BAD_REQUEST)
          @ExceptionHandler(value = IllegalArgumentException.class)
          public Result handler(IllegalArgumentException e) {
              log.error("Assert异常:----------------{}", e);
              return Result.fail(e.getMessage());
          }
    
          @ResponseStatus(HttpStatus.BAD_REQUEST)
          @ExceptionHandler(value = RuntimeException.class)
          public Result handler(RuntimeException e) {
              log.error("运行时异常:----------------{}", e);
              return Result.fail(e.getMessage());
          }
    

    }

  • 因为有日志输出,所以在集成了Slf4j进项目后,在这个全局异常处理类上加上 @Slf4j注解

  • @RestControllerAdvice注解,全局Controller用来捕捉全局异常

  • @ResponseStatus,带有@ResponseStatus注解的异常类会被ResponseStatusExceptionResolver 解析。可以实现自定义的一些异常,同时在页面上进行显示。有两个参数

    • code:对应枚举HttpStatus的值,此值对应相应404,403,500
    • reason:界面提示文字

全局异常处理类的处理逻辑:捕捉全局异常并进行处理

  1. shiro认证授权时抛出的异常,在异常处理handler中先做日志输出,然后用封装的给前端返回信息的处理类Result做返回信息封装
    Result.fail(401, e.getMessage(), null),同时会返回一个code为UNAUTHORIZED(放在返回头中的)

  2. 后端数据校验时出错抛出异常,在异常处理类中做日志输出,取出异常中绑定的错误信息(从ObjectError对象中拿到)封装进前端返回信息处理类Result.fail(objectError.getDefaultMessage(),同时会返回一个code
    HttpStatus.BAD_REQUEST

    • 注意这里后端使用的数据校验(使用SpringBoot集成的Hibernate Validation)现在实体类加@NotNull类注解的一个value为message为提示信息如下
      在这里插入图片描述

    • 在contoller在需要此实体类的地方加上@Valid 注解
      在这里插入图片描述

    • 校验数据出现的异常假设捕捉到e,e.getBindingResult()得到的绑定结果就是校验标签上的message

  3. Assert异常时抛出异常(有断言时出错的地方抛出此异常),做日志输出后,拿到异常信息e.getMessage()封装进前端返回信息处理类Result.fail(e.getMessage()),同时将HttpStatus.BAD_REQUEST的code封装进返回头中

  4. 其他运行时异常全部捕捉起来,做日志输出,拿到异常信息e.getMessage()封装进前端返回信息处理类Result.fail(e.getMessage()),同时将HttpStatus.BAD_REQUEST的code封装进返回头中

lang

在这里插入图片描述

package com.markerhub.common.lang;

import lombok.Data;

import java.io.Serializable;

@Data
public class Result implements Serializable {

    private int code; // 200是正常,非200表示异常
    private String msg;
    private Object data;

    public static Result succ(Object data) {
        return succ(200, "操作成功", data);
    }

    public static Result succ(int code, String msg, Object data) {
        Result r = new Result();
        r.setCode(code);
        r.setMsg(msg);
        r.setData(data);
        return r;
    }

    public static Result fail(String msg) {
        return fail(400, msg, null);
    }

    public static Result fail(String msg, Object data) {
        return fail(400, msg, data);
    }

    public static Result fail(int code, String msg, Object data) {
        Result r = new Result();
        r.setCode(code);
        r.setMsg(msg);
        r.setData(data);
        return r;
    }

}
  • 定义该异常类,三个成员变量,code(200正常,非200异常),msg状态信息,data表示数据(Object类型)

  • Result中实现了两种构造自定义Result对象的方法(其实就是将错误操作,成功信息封装进同一个类型对象Result),同时还实现了函数重载

Result类的处理逻辑

  1. 成功操作则调用Result的静态方法succ(Object data),底层为调用重载后的succ(200, “操作成功”, data);此时将三个参数封装进一个Result对象并返回
  2. 错误操作逻辑为,调用Result的静态方法,只传入错误信息fail(String msg),则调用 return fail(400, msg, null);如果传入错误信息和数据则调用 return fail(400, msg, data);统一由fail(int code, String msg, Object data) 实现Result的构造
  3. 可见正确操作给前端返回的信息是一定code为200,由正确信息和数据的,而错误操作状态码为400有错误信息,但可能没有数据的
util

在这里插入图片描述

JwtUtils.java
package com.markerhub.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * jwt工具类
 */
@Slf4j
@Data
@Component
@ConfigurationProperties(prefix = "
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值