Skip to Content

lombok

功能

  • 通过注解的方式在定义类的时候减少样板代码,并可以自动化生成日志变量

使用

  • @Getter/@Setter:为所有的属性提供get/set方法
  • @ToString:会给类自动生成易阅读的toString方法
  • @EqualsAndHashCode:根据类所拥有的非静态字段自动重写equals方法和hashCode方法
  • @Data:提供了更综合的生成代码功能(@Getter+@Setter+@ToString+@EqualsAndHashCode)
  • @NoArgsConstructor:为实体类生成无参的构造器方法
  • @AllArgsConstructor:为实体类生成除了static修饰的字段之外带有各参数的构造器方法

mybatis-plus

功能

  • 进行了增强的 ORM 框架(对象关系映射),提供了 自动映射 功能,不再需要写 resultMap
  • 内置了 BaseMapper 接口,提供了很多常用的 CRUD 操作,支持自动生成 SQL 语句
  • 内置了分页功能
  • 内置了逻辑删除功能(通过在数据库表中添加一个表示删除状态的字段,而不是直接从数据库中删除记录)
  • 提供了自动填充功能(创建时间、更新时间…)
  • 提供了性能分析插件
  • 提供了代码生成器,可以根据数据库表自动生成实体类、Mapper、Service 等代码

使用

  1. 添加依赖
<dependencies> <!-- MyBatis-Plus 依赖 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.0</version> <!-- 请根据实际需要选择版本 --> </dependency> <!-- MyBatis 和 Spring Boot Starter 依赖(如果没有的话)--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> </dependencies>
  1. 配置yml文件
mybatis-plus: type-aliases-package: com.example.demo.entity # 实体类包路径
  1. 创建实体类
  • @TableName:指定实体类映射的数据库表名
  • @TableId:指定实体类的主键字段 (如果没有该注解,MyBatis-Plus 会默认认为 id 字段是主键)
    • value:指定主键对应的字段名
    • type:指定主键策略
      • IdType.AUTO:自增主键(MySQL)
      • IdType.INPUT:用户输入主键(如 UUID)
      • IdType.ID_WORKER:雪花算法生成主键(适合分布式系统)
  • @TableField:指定实体类字段与数据库表列的映射关系
    • value:指定数据库表字段名(默认为字段名)
    • exist:是否是数据库表中的字段,默认为 true,如果该字段不映射到数据库,则设置为 false
    • fill:设置字段的自动填充策略 (需要实现MetaObjectHandler接口)
      • FieldFill.DEFAULT:默认不处理,即不进行自动填充
      • FieldFill.INSERT:插入时自动填充字段
      • FieldFill.UPDATE:更新时自动填充字段
      • FieldFill.INSERT_UPDATE:插入和更新时都自动填充字段
    • update:指定更新时字段的策略
    • select:指定是否需要在查询时被映射
    • condition:指定字段在 SQL 语句中的条件
      • SqlCondition.LIKE:使用 SQL 中的 LIKE 条件进行模糊查询
      • SqlCondition.EQ:默认,表示使用等于条件
      • 自定义字符串:可以提供一个自定义的字符串条件
  • @TableLogic:用于指定实体类的逻辑删除字段,支持自动填充逻辑删除值
  • @Version:更新时检查数据版本,如果检测到数据版本在读取后已经被其他事务修改,当前事务将拒绝更新,从而防止数据不一致
@TableName("user") // 表示该实体类映射到数据库中的 "user" 表 public class User { @TableId(value = "id", type = IdType.AUTO) // 主键自增 private Long id; @TableField(value = "user_name", fill = FieldFill.INSERT,condition = SqlCondition.LIKE) // 插入时自动填充 private String name; @Version // 乐观锁版本字段 private Integer age; @TableLogic // 逻辑删除字段 private Integer deleted; @TableField(exist = false) // 表示该字段不对应数据库表中的字段 private String tempField; @TableField(select = false) // 在查询时不查询该字段 private String password; }
  1. 创建Mapper接口
  • BaseMapper:继承基本接口,并传入实体类,获得该类常用的CRUD基本方法
    • insert:插入一条记录
      • int insert(T entity)
    • insertOrUpdate:根据实体类的主键值判断,如果主键存在则执行更新操作,如果主键不存在则执行插入操作
      • boolean insertOrUpdate(T entity)
    • updateById:根据主键 ID 更新相应实体类的所有字段
      • int updateById(T entity)
    • update:根据条件更新记录
      • int update(T entity, Wrapper<T> updateWrapper)
    • selectById:根据主键 ID 查询单条记录
      • T selectById(Serializable id)
    • selectBatchIds:根据 ID 列表查询多条记录
      • List<T> selectBatchIds(Collection<? extends Serializable> idList)
    • selectOne:根据条件查询单条记录。如果查询结果有多条,抛出异常
      • T selectOne(Wrapper<T> queryWrapper)
    • selectList:根据条件查询多条记录
      • List<T> selectList(Wrapper<T> queryWrapper)
    • selectPage:进行分页查询
      • IPage<T> selectPage(Page<T> page, Wrapper<T> queryWrapper)
    • delete:根据条件删除记录
      • int delete(Wrapper<T> queryWrapper)
    • deleteById:根据主键 ID 删除一条记录
      • int deleteById(Serializable id)
    • deleteBatchIds:
      • int deleteBatchIds(Collection<? extends Serializable> idList)
    • selectCount:根据条件查询记录的总数
      • int selectCount(Wrapper<T> queryWrapper)
    • exists:判断是否存在符合条件的记录
      • boolean exists(Wrapper<T> queryWrapper)
@Mapper @Repository public interface UserMapper extends BaseMapper<User> { // 继承 BaseMapper 后,自动获得 CRUD 操作方法 // 不需要编写基本的插入、删除、更新、查询方法 }
  1. CRUD
  • 查询
    • 条件查询
      1. 构造条件查询对象
        • QueryWrapper:构建查询条件,用于生成 WHERE 子句
          • QueryWrapper<MyEntity> queryWrapper = new QueryWrapper<>()
        • LambdaQueryWrapper:使用 Lambda 表达式构建查询条件
          • LambdaQueryWrapper<MyEntity> lambdaQuery = new LambdaQueryWrapper<>()
      2. 添加查询条件(对象方法)
        • eq (equals):等于查询条件
        • ne (not equals):不等于查询条件
        • gt (greater than):大于查询条件
        • ge (greater than or equals to):大于或等于查询条件
        • lt (less than):小于查询条件
        • le (less than or equals to):小于或等于查询条件
        • like:模糊查询条件,可以包含通配符 %
        • likeLeft:左模糊查询条件,通配符 % 在字符串的左侧
        • likeRight:右模糊查询条件,通配符 % 在字符串的右侧
        • in:在给定列表中的查询条件
        • notIn:不在给定列表中的查询条件
        • orderByAsc:升序排序
        • orderByDesc:降序排序
        • groupBy:分组查询
        • select:指定查询的字段
        • distinct:去重查询
        • nested:嵌套查询条件
        • or:逻辑或
        • and:逻辑与
      /** * 查找price>30000并且star=4的记录或者price<1000的记录,记录只显示id、name、price、star字段 */ @Test public void testSelectByPriceAndStar() { QueryWrapper<Goods> queryWrapper = new QueryWrapper<>(); queryWrapper.select("id", "name", "price", "star") .and(i -> i.gt("price", 30000).eq("star", 4)) .or(i -> i.lt("price", 1000)); List<Goods> goods = goodsMapper.selectList(queryWrapper); goods.forEach(System.out::println); System.out.println("测试成功"); }
    • 分页查询
      1. 配置分页查询插件:通过 PaginationInterceptor 插件拦截所有的查询语句,在其上添加分页逻辑
      @Configuration @EnableTransactionManagement public class MybatisPlusConfig{ @Bean // Spring容器会调用这个方法,并把返回值当作一个bean的实例 public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 创建拦截器 PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); // 创建分页插件 paginationInnerInterceptor.setOptimizeJoin(true); // 设置分页插件的联表查询优化 paginationInnerInterceptor.setDbType(DbType.MYSQL); // 设置数据库类型为MySQL paginationInnerInterceptor.setOverflow(true); // 设置分页插件的物理分页参数溢出时的处理策略 interceptor.addInnerInterceptor(paginationInnerInterceptor); // 将分页插件添加到拦截器 OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor(); //创建乐观锁插件 interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor); // 将乐观锁插件添加到拦截器 return interceptor; // 返回拦截器 }

} 2. 创建分页对象:`Page` 类表示分页的请求参数(如当前页和每页的记录数),`IPage` 是分页查询返回的结果。 - `Page<MyEntity> page = new Page<>(pageNo, pageSize)` - `IPage<User> userPage = userMapper.selectPage(page, queryWrapper);` java @Service public class UserService {

@Autowired private UserMapper userMapper; public IPage<User> getUsersByPage(int pageNo, int pageSize) { // 创建分页对象 Page<User> page = new Page<>(pageNo, pageSize); // 当前页和每页的记录数 // 创建查询条件 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("status", "active"); // 查询条件:status = 'active' // 执行分页查询,返回分页查询结果对象 IPage<User> userPage = userMapper.selectPage(page, queryWrapper); return userPage; } } ``` 3. 分析返回结果:`IPage` 接口提供了很多分页信息 - `getRecords()`:获取当前页的数据(一个 `List`,包含查询的实体类对象) - `getTotal()`:获取总记录数 - `getPages()`:获取总页数 - `getCurrent()`:获取当前页码 - `getSize()`:获取每页的记录数 ```java @Controller public class UserController { @Autowired private UserService userService; public void getUsers() { // 调用查询方法,返回分页结果 IPage<User> userPage = userService.getUsersByPage(1, 10); // 获取分页数据 List<User> users = userPage.getRecords(); // 获取当前页的数据 long total = userPage.getTotal(); // 总记录数 long totalPages = userPage.getPages(); // 总页数 long currentPage = userPage.getCurrent(); // 当前页码 long pageSize = userPage.getSize(); // 每页记录数 // 处理分页数据... } } ```

细节

  • 下划线转驼峰,默认情况下mybatis-plus是开启的,而mybatis是关闭的

mybatis-flex

功能

  • 相比于mybatis-plus,性能更强,功能更全面

使用

  • @Table
  • @Id

JWT令牌

功能

  • 使用JSON  Web  Token进行身份认证,进行访问控制
  • 解决 Web 应用中的无状态认证问题,可以安全地传输用户身份信息和权限等数据

特点

  • JWT是自包含的,服务器不需要存储会话信息,所有信息都在令牌中

构成

  • Header:头部,通常包含令牌类型(如 JWT)和加密算法(如 HS256)。
  • Payload:有效负载,包含要传输的声明(如用户信息、权限等)。有效负载部分并不加密,敏感信息请避免放在这里。
  • Signature:签名,用于确保数据没有被篡改。由 Header 和 Payload 通过加密算法进行签名生成。

使用

  1. 引入依赖
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.11.5</version> </dependency> <!-- Spring Security(如果你需要进行安全控制) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
  1. 创建 JWT 工具类
public class JwtUtil { // 密钥,生产环境中需要保密,注意不能过短,否则会引起异常 private static final String SECRET_KEY = "mysecretkey"; // 生成 JWT 令牌 public static String generateToken(String username) { return Jwts.builder() .setSubject(username) // 设置主题(通常是用户名) .setIssuedAt(new Date()) // 设置签发时间 .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 设置过期时间(1小时) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 使用 HMAC SHA256 算法进行签名 .compact(); // 将令牌转为字符串 } // 解析 JWT 令牌 public static Claims extractClaims(String token) { return Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); } // 从 JWT 令牌中获取用户名(或者其他信息) public static String extractUsername(String token) { return extractClaims(token).getSubject(); } // 检查 JWT 是否过期 public static boolean isTokenExpired(String token) { return extractClaims(token).getExpiration().before(new Date()); } // 验证 JWT 令牌 public static boolean validateToken(String token, String username) { return (username.equals(extractUsername(token)) && !isTokenExpired(token)); } }
  1. 创建过滤器:进行拦截请求并验证JWT
    • 流程:拦截->处理->放行->返回
@WebFilter("/*") // 配置拦截资源的路径,该配置是拦截所有请求 public class JwtFilter implements Filter { @Override // 拦截请求后调用,调用多次 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 将ServletRequest类型转换为HttpServletRequest,这样可以访问HTTP请求特有的方法和属性 HttpServletRequest httpRequest = (HttpServletRequest) request; // 从请求头中获取 JWT String token = httpRequest.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); // 去掉 "Bearer " 前缀 String username = JwtUtil.extractUsername(token); // 从token中提取用户名 if (username != null && JwtUtil.validateToken(token, username)) { // 如果token验证通过,将用户名设置到请求属性中,这样后续的代码可以通过请求对象获取到用户名。 httpRequest.setAttribute("username", username); } } // 放行请求(调用FilterChain的doFilter方法,将请求传递给过滤器链中的下一个过滤器或目标资源) chain.doFilter(request, response); // 资源访问后处理逻辑... } @Override // 初始化方法,只调用一次,用默认实现方法,可以不实现 public void init(FilterConfig filterConfig) throws ServletException { } @Override // //销毁方法,只调用一次,用默认实现方法,可以不实现 public void destroy() { } }
  1. 注册过滤器:对创建好的过滤器进行基本配置,添加到Spring容器中
@Configuration public class FilterConfig { @Bean public FilterRegistrationBean<JwtFilter> loggingFilter() { FilterRegistrationBean<JwtFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new JwtFilter()); registrationBean.addUrlPatterns("/api/*"); // 配置哪些接口需要进行 JWT 认证 return registrationBean; } }
Last updated on