从0开始搭建jdk-21 springboot项目
idea创建新项目
pom添加依赖
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.glc.client</groupId><artifactId>glc-client</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.5</version><relativePath/></parent><properties><maven.compiler.source>21</maven.compiler.source><maven.compiler.target>21</maven.compiler.target><maven.compiler.encoding>UTF-8</maven.compiler.encoding><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><skipTests>true</skipTests></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version><scope>provided</scope></dependency></dependencies></project>
编写程序入口
packagecom.glc.client;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassGlcClientApplication{publicstaticvoidmain(String[] args){SpringApplication.run(GlcClientApplication.class, args);}}
然后直接启动程序就可以了,启动成功的日志如下
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.1.0)
2023-11-12T15:19:22.634+08:00 INFO 13420 --- [ main] com.glc.client.GlcClientApplication : Starting GlcClientApplication using Java 21.0.1 with PID 13420 (/Users/cgl/codes/glc-client/target/classes started by cgl in /Users/cgl/codes/glc-client)
2023-11-12T15:19:22.635+08:00 INFO 13420 --- [ main] com.glc.client.GlcClientApplication : No active profile set, falling back to 1 default profile: "default"
2023-11-12T15:19:22.948+08:00 INFO 13420 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2023-11-12T15:19:22.952+08:00 INFO 13420 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-11-12T15:19:22.952+08:00 INFO 13420 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.8]
2023-11-12T15:19:22.988+08:00 INFO 13420 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-11-12T15:19:22.989+08:00 INFO 13420 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 333 ms
2023-11-12T15:19:23.116+08:00 INFO 13420 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2023-11-12T15:19:23.120+08:00 INFO 13420 --- [ main] com.glc.client.GlcClientApplication : Started GlcClientApplication in 0.622 seconds (process running for 0.858)
添加yml配置文件
- 在resources目录下添加
application.yml
,application-dev.yml
,application-prod.yml
文件 - 指定一下程序的名称和端口, 在
application.yml
中添加如下配置:
spring:application:name: glc-client
profiles:active: dev
server:port:8077
- 启动程序,可以看到启动日志里面配置生效了:
The following 1 profile is active: "dev"
Tomcat initialized with port(s): 8077 (http)
添加测试类
- 添加test依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency>
2.在
test.java.com.glc.client
下面添加
GlcClientApplicationTest
文件,输入以下测试代码:
packagecom.glc.client;importorg.junit.jupiter.api.Test;importorg.springframework.boot.test.context.SpringBootTest;@SpringBootTestpublicclassGlcClientApplicationTest{@Testvoidmain(){System.out.println("test");}}
- 执行,可以看到输出了test字符串,test功能可以正常运行了
添加并测试home接口
- 创建controller文件夹
- 创建HomeController.java文件
- 编写接口,如下:
packagecom.glc.client.controller;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassHomeController{@GetMapping("/")publicStringhome(){return"Hello World!";}}
- 浏览器访问:http://localhost:8077,可以看到返回了"Hello World!",说明接口生效了。
添加commons lang 依赖
后面会用到StringUtils,这里先导入 apache commons lang依赖
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.13.0</version></dependency>
mysql数据库操作相关
添加musql-connect-java依赖
<!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version><scope>runtime</scope></dependency>
关于这个依赖的解释:
这段代码是一个Maven依赖配置,用于指定项目依赖的MySQL JDBC驱动程序
mysql-connector-java
。在这里,每个标签的含义如下:
<groupId>
: 指定依赖的组织或项目的标识符,在这个例子中是mysql
。这通常指定了开发或维护该依赖的组织。<artifactId>
: 指定具体的依赖名称,在这个例子中是mysql-connector-java
。这是该依赖在组中的唯一标识。<version>
: 指定依赖的版本,这里是8.0.33
。这告诉Maven要下载并使用该特定版本的依赖。<scope>
: 定义依赖的范围。在这个例子中,范围被设置为runtime
,意味着这个依赖只在运行时需要,并不在编译时需要。这是因为JDBC驱动通常在运行时用来建立数据库连接,而在编译代码时不是必须的。
简而言之,这段配置告诉Maven项目在运行时需要使用版本为8.0.33的MySQL JDBC驱动程序。
在yml文件中配置数据库信息
在
application-dev.yml
添加数据库信息,同时本项目使用springboot默认的连接池hikari:
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/glc?useUnicode=true&allowMultiQueries=true&characterEncoding=utf8&serverTimezone=GMT%2B8username: root
password:123456hikari:minimum-idle:5idle-timeout:600000maximum-pool-size:32auto-commit:truepool-name: HikariCorePool
max-lifetime:1800000connection-timeout:30000connection-test-query: select TABLE_NAME from information_schema.tables limit 1
connection-init-sql: SET NAMES utf8mb4
在做完下面的mybatis plus相关的引入之后启动项目并第一次测试数据库查询相关接口之后,可以看到
HikariCorePool - Start completed.
,说明数据库连接池启动成功。
引入mybatis plus
- 添加依赖。最新的版本在mvnrepository查看。
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4.1</version></dependency>
- 添加配置文件 创建config目录,在下面创建MybatisPlusConfig文件,写入以下内容:
packagecom.glc.client.config;importcom.baomidou.mybatisplus.annotation.DbType;importcom.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;importcom.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;importorg.mybatis.spring.annotation.MapperScan;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@Configuration@MapperScan("com.glc.client.mapper*")publicclassMybatisPlusConfig{@BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptor interceptor =newMybatisPlusInterceptor();PaginationInnerInterceptor innerInterceptor =newPaginationInnerInterceptor();
innerInterceptor.setDbType(DbType.MYSQL);
innerInterceptor.setMaxLimit(100000L);
interceptor.addInnerInterceptor(innerInterceptor);return interceptor;}}
引入mybatis plus generator插件
该插件主要用于一键生成表相关的实体类。
- 引入依赖mybatis-plus-generator和velocity-engine-core
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-generator --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.4.1</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity-engine-core --><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.3</version></dependency>
- 创建MybatisPlusGenerator 在com.glc.client下面创建MybatisPlusGenerator文件,写入以下内容:
packagecom.glc.client;importcom.baomidou.mybatisplus.annotation.FieldFill;importcom.baomidou.mybatisplus.annotation.IdType;importcom.baomidou.mybatisplus.generator.FastAutoGenerator;importcom.baomidou.mybatisplus.generator.config.OutputFile;importcom.baomidou.mybatisplus.generator.config.rules.DateType;importcom.baomidou.mybatisplus.generator.config.rules.DbColumnType;importcom.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;importcom.baomidou.mybatisplus.generator.fill.Column;importcom.baomidou.mybatisplus.generator.fill.Property;importorg.apache.commons.lang3.StringUtils;importjava.sql.Types;importjava.util.Collections;publicclassMybatisPlusGenerator{publicstaticvoidmain(String[] args){String tableName ="user";//需要生成的类对应的表名IdType idType =IdType.ASSIGN_ID;//插入数据是默认的主键id的生成算法String userDir =System.getProperty("user.dir");String outputDir =StringUtils.join(userDir,"/src/main/java/");String mapperXmlDir =StringUtils.join(userDir,"/src/main/resources/mapper");//创建代码生成器对象String url ="jdbc:mysql://127.0.0.1:3306/glc?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&failOverReadOnly=false";String username ="root";String password ="123456";FastAutoGenerator.create(url, username, password).globalConfig(builder ->{
builder.author("gulong")// 设置作者.fileOverride()// 覆盖已生成文件.commentDate("yyyy-MM-dd")// 注释里面的日期的格式.dateType(DateType.ONLY_DATE)//定义生成的实体类中日期类型 DateType.ONLY_DATE 默认值: DateType.TIME_PACK.outputDir(outputDir);// 指定输出目录}).dataSourceConfig(builder ->{
builder.schema("glc").typeConvertHandler((globalConfig, typeRegistry, metaInfo)->{int typeCode = metaInfo.getJdbcType().TYPE_CODE;if(typeCode ==Types.SMALLINT){// 自定义类型转换returnDbColumnType.INTEGER;}return typeRegistry.getColumnType(metaInfo);});}).packageConfig(builder ->{
builder.parent("com.glc.client")// 设置父包名// .moduleName("") // 设置父包模块名.controller("controller").entity("entity").service("service").service("service.impl").mapper("mapper").pathInfo(Collections.singletonMap(OutputFile.xml, mapperXmlDir));// 设置mapperXml生成路径}).strategyConfig(builder ->{
builder.addInclude(tableName)// 设置需要生成的表名// .addTablePrefix("t_") // 设置过滤表前缀.serviceBuilder()//service策略配置.formatServiceFileName("%sService")//去掉类名中默认的I前缀.formatServiceImplFileName("%sServiceImpl").entityBuilder()// 实体类策略配置.idType(idType)//主键策略 这里AUTO是数据库自增ID,如果需要雪花算法生成的id可以改成ASSIGN_ID.addTableFills(newColumn("create_time",FieldFill.INSERT))// 自动填充配置.addTableFills(newProperty("update_time",FieldFill.INSERT_UPDATE)).enableLombok()//开启lombok.logicDeleteColumnName("deleted")// 假删除字段.enableTableFieldAnnotation()// 自动添加表字段的注解.controllerBuilder()//controller 策略配置.formatFileName("%sController").enableRestStyle()// 开启RestController注解.mapperBuilder()// mapper策略配置.formatMapperFileName("%sMapper").formatXmlFileName("%sMapper");}).templateEngine(newVelocityTemplateEngine()).execute();}}
- 测试执行MybatisPlusGenerator程序 在上述配置中,我们指定了表为user表,点击执行,看看生成结果:
这样mybatis的代码生成器就配置完成了,之后需要添加新的表只需要改一下MybatisPlusGenerator里的表名就行了,idType看实际需求选择AUTO(自增id)还是ASSIGN_ID(雪花算法生成的id)
添加knife4j 4.0
为了方便调试接口,可以引入knife4j。在knife4j官方文档中,有如下说明:
由于springfox长久未更新,并且Swagger2规范在目前来看,一定程度上也并未升级,规范已经全部往OpenAPI3规范靠拢,因此,在Spring Boot 3.x版本中,开发者应该选择OpenAPI3规范来作为应用框架的开发首选方案。
- 引入依赖
<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.3.0</version></dependency>
- 配置文件 在
application.yml
中,添加如下配置(点此查看官方关于权限控制的说明):
# springdoc-openapi项目配置springdoc:swagger-ui:path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:path: /v3/api-docs
group-configs:-group:'client'paths-to-match:'/**'packages-to-scan: com.glc.client
# knife4j的增强配置,不需要增强可以不配knife4j:enable:truesetting:language: zh_cn
production:false
- 用knife4j官方的例子来测试一下是否成功 首先在controller包里添加BodyController文件:
packagecom.glc.client.controller;importcom.glc.client.model.FileResp;importio.swagger.v3.oas.annotations.Operation;importio.swagger.v3.oas.annotations.Parameter;importio.swagger.v3.oas.annotations.Parameters;importio.swagger.v3.oas.annotations.enums.ParameterIn;importio.swagger.v3.oas.annotations.tags.Tag;importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.*;@RestController@RequestMapping("body")@Tag(name ="body参数")publicclassBodyController{@Operation(summary ="普通body请求")@PostMapping("/body")publicResponseEntity<FileResp>body(@RequestBodyFileResp fileResp){returnResponseEntity.ok(fileResp);}@Operation(summary ="普通body请求+Param+Header+Path")@Parameters({@Parameter(name ="id", description ="文件id", in =ParameterIn.PATH),@Parameter(name ="token", description ="请求token", required =true, in =ParameterIn.HEADER),@Parameter(name ="name", description ="文件名称", required =true, in =ParameterIn.QUERY)})@PostMapping("/bodyParamHeaderPath/{id}")publicResponseEntity<FileResp>bodyParamHeaderPath(@PathVariable("id")String id,@RequestHeader("token")String token,@RequestParam("name")String name,@RequestBodyFileResp fileResp){
fileResp.setName(fileResp.getName()+",receiveName:"+ name +",token:"+ token +",pathID:"+ id);returnResponseEntity.ok(fileResp);}}
其中FileResp如下:
packagecom.glc.client.model;importlombok.Data;@DatapublicclassFileResp{privateString name;privateLong fileSize;privateBoolean deleted;}
然后启动项目,访问:http://127.0.0.1:8077/doc.html, 看到如下界面, 说明成功了:
测试接口结果如下:
至此knife4j就配置完成了,下面来看看knife的增强配置。
knife4j增强配置
首先看看官方说明:
在以前的版本中,开发者需要在配置文件中手动使用@EnableKnife4j来使用增强,自2.0.6版本后,只需要在配置文件中配置knife4j.enable=true即可不在使用注解
- 登录认证
knife4j:# 开启增强配置 enable:true# 开启Swagger的Basic认证功能,默认是falsebasic:enable:true# Basic认证用户名username: test
# Basic认证密码password:123
目前暂时没有其他增强配置的需求。官方文档已经很详细了,有需要的话直接查阅官方文档。
使用mybatis plus进行分页查询
下面我们将使用mybatis自带的分页功能进行分页查询
- 配置分页拦截器 之前其实已经配置过了,就是在MybatisPlusConfig文件里面,具体配置如下所示:
packagecom.glc.client.config;importcom.baomidou.mybatisplus.annotation.DbType;importcom.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;importcom.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;importorg.mybatis.spring.annotation.MapperScan;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@Configuration@MapperScan("com.glc.client.mapper*")publicclassMybatisPlusConfig{@BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptor interceptor =newMybatisPlusInterceptor();PaginationInnerInterceptor innerInterceptor =newPaginationInnerInterceptor();
innerInterceptor.setDbType(DbType.MYSQL);
innerInterceptor.setMaxLimit(100000L);
interceptor.addInnerInterceptor(innerInterceptor);return interceptor;}}
- 编写一个用户表的查询接口 在userController中添加如下接口代码:
packagecom.glc.client.controller;importcom.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;importcom.baomidou.mybatisplus.core.toolkit.Wrappers;importcom.baomidou.mybatisplus.extension.plugins.pagination.Page;importcom.glc.client.entity.User;importcom.glc.client.service.impl.UserService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.http.ResponseEntity;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;/**
* <p>
* 前端控制器
* </p>
*
* @author gulong
* @since 2023-11-12
*/@RestController@RequestMapping("user")publicclassUserController{@AutowiredprivateUserService userService;/**
* 用户列表分页查询
*
* @param current 当前页数
* @param size 每页条数
* @return ResponseEntity<Page<User>>
*/@GetMapping("/page")publicResponseEntity<Page<User>>userPageQuery(@RequestParam("current")Integer current,@RequestParam("size")Integer size){Page<User> pageParam =newPage<>(current, size);LambdaQueryWrapper<User> queryWrapper =Wrappers.lambdaQuery();
queryWrapper.select(User::getId,User::getCreateTime,User::getCreateTime).ge(User::getCreateTime,"2023-11-12");Page<User> pageResult = userService.page(pageParam, queryWrapper);returnResponseEntity.ok(pageResult);}}
- 使用knife4j测试接口 接下来我们使用之前配置好的knife4j来测试
user/page
接口,结果如下:
自定义分页查询
有时候我们可能对一些复杂的查询使用自定义的sql,我们可以用如下的方法进行分页查询。
UserController.java
/**
* 分页查询当天注册的用户信息
*
* @param current 当前页数
* @param size 每页条数
* @return user
*/@GetMapping("/today")publicResponseEntity<Page<User>>todayUserPageQuery(@RequestParam("current")Integer current,@RequestParam("size")Integer size){Page<User> page =newPage<>(current, size);String todayDate =LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
userMapper.selectPageVo(page, todayDate);returnResponseEntity.ok(page);}
UserMapper.java
packagecom.glc.client.mapper;importcom.baomidou.mybatisplus.extension.plugins.pagination.Page;importcom.glc.client.entity.User;importcom.baomidou.mybatisplus.core.mapper.BaseMapper;importorg.apache.ibatis.annotations.Param;/**
* <p>
* Mapper 接口
* </p>
*
* @author gulong
* @since 2023-11-12
*/publicinterfaceUserMapperextendsBaseMapper<User>{Page<User>selectPageVo(@Param("page")Page<User> page,@Param("todayDate")String todayDate);}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.glc.client.mapper.UserMapper"><selectid="selectPageVo"resultType="com.glc.client.entity.User">
select id, create_time as createTime
from user
where create_time >= #{todayDate}
</select></mapper>
这样就实现了自定义的分页查询。
接口返回数据格式的相关配置
设置jackjson的默认时间格式
在上面的接口返回结果中,我们可以看到createTime的格式对前端不友好,我们统一个改成常用的
yyyy-MM-dd HH:mm:ss
格式。本项目暂时未引入fastjson,在springboot中默认使用的是jackjson对接口返回的数据进行序列化,所以我们可以在yml文件中配置全局默认时间序列化格式。
- 在application.yml中添加如下配置:
spring:jackson:date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
- 测试接口返回时间格式 如下图所示,可以看到已经按我们常用的格式返回了:
long类型返回前端的精度丢失问题
在上面的结果中,id的类型为long,这种类型的数据在返回给前端的时候如果数字过大,就会产生精度丢失的问题。
来看看AI智能助手对于这个问题的解释:
JavaScript中的Number类型仅能安全地表示-253到253之间的整数(即安全整数范围),而超出此范围的大整数在JavaScript中可能无法精确表示。
通常对此类问题的处理方法就是把这个long序列为string。
本项目默认使用jackjson序列化,所以可以使用如下注解来解决:
@JsonSerialize(using =ToStringSerializer.class)privateLong id;
如果是使用fastjson序列化,则用如下注解:
@JSONField(serializeUsing =ToStringSerializer.class)privateLong id;
添加redis相关
web开发中,redis相关的操作是基本离不开的,下面将添加redis相关的一些依赖
引入spring-boot-starter-data-redis
经过对比,目前使用spring-boot-starter-data-redis是最合适的,下面开始引入。
拓展:点进依赖可以看到spring-boot-starter-data-redis是引入了spring-data-redis和lettuce-core,其默认使用lettuce-core客户端,线程安全
- 添加依赖,
其中commons-pool2是为了使用连接池。许多Redis客户端库,如Jedis、Lettuce等,在实现其连接池功能时依赖于commons-pool2。这些库使用commons-pool2来管理Redis连接的创建、借用、返回和销毁。
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>
- 添加redis配置信息 在
application-dev.yml
配置redis信息:
spring:data:redis:host: localhost
port:6379password:123456database:0connect-timeout:30000timeout:10000lettuce:pool:min-idle:16max-idle:32max-active:128max-wait:30000
- 关于redis的序列化
- 如果不进行配置,直接使用redisTemplate,则默认使用的jdk序列化,可读性很差,而且其他程序比如python就无法读取。
- 可以自定义序列化配置,但是注意最好不要使用
GenericJackson2JsonRedisSerializer
,这种会在redis里面存储类的信息,对于其他项目读取该数据非常不友好, 而且如果其他项目比如python项目设置了一个值,该项目将无法读取。 - 本项目选择采用stringRedisTemplate,这种就是key和value都存储为字符串,在序列化和反序列化的时候自己手动使用jackjson或者fastjson就行了
- 测试 在test.java.com.glc.client下创建RedisTest文件,输入如下测试代码并执行
packagecom.glc.client;importcom.fasterxml.jackson.core.JsonProcessingException;importcom.fasterxml.jackson.core.type.TypeReference;importcom.fasterxml.jackson.databind.ObjectMapper;importcom.glc.client.model.FileResp;importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.data.redis.core.StringRedisTemplate;importjava.util.Arrays;importjava.util.List;importjava.util.stream.Collectors;@SpringBootTestpublicclassRedisTest{@AutowiredStringRedisTemplate stringRedisTemplate;@TestvoidtestString(){//存储/读取字符串
stringRedisTemplate.opsForValue().set("test-string","redis-value");String value = stringRedisTemplate.opsForValue().get("test-string");System.out.printf(value);
stringRedisTemplate.delete("test-string");}@TestvoidtestJsonString()throwsJsonProcessingException{FileResp afile =newFileResp("afile",123l,true);FileResp bfile =newFileResp("bfile",123l,false);List<FileResp> list =Arrays.asList(afile, bfile);
stringRedisTemplate.opsForValue().set("test-json-string",newObjectMapper().writeValueAsString(list));String jsonValue = stringRedisTemplate.opsForValue().get("test-json-string");System.out.printf(jsonValue);List<FileResp> fromRedis =newObjectMapper().readValue(jsonValue,newTypeReference<>(){});for(FileResp item : fromRedis){System.out.println(item);}
stringRedisTemplate.delete("test-json-string");}@TestvoidtestHash()throwsJsonProcessingException{FileResp afile =newFileResp("afile",123l,true);FileResp bfile =newFileResp("bfile",123l,false);
stringRedisTemplate.opsForHash().put("test-hash","hash-1",newObjectMapper().writeValueAsString(afile));
stringRedisTemplate.opsForHash().put("test-hash","hash-2",newObjectMapper().writeValueAsString(bfile));String value =(String) stringRedisTemplate.opsForHash().get("test-hash","hash-2");System.out.println(value);FileResp fileResp =newObjectMapper().readValue(value,FileResp.class);System.out.println(fileResp);
stringRedisTemplate.delete("test-hash");}@TestvoidtestList(){FileResp afile =newFileResp("afile",123l,true);FileResp bfile =newFileResp("bfile",123l,false);List<FileResp> list =Arrays.asList(afile, bfile);//数组里面只能是stringObjectMapper objectMapper =newObjectMapper();List<String> jsonStrings = list.stream().map(fileResp ->{try{return objectMapper.writeValueAsString(fileResp);}catch(JsonProcessingException e){thrownewRuntimeException(e);}}).collect(Collectors.toList());
stringRedisTemplate.opsForList().rightPushAll("test-list", jsonStrings);List<String> range = stringRedisTemplate.opsForList().range("test-list",0,-1);System.out.println(range);
stringRedisTemplate.delete("test-list");}}
测试结果发现序列化和反系列化都正常,至此,redis的普通操作都完成了。接下去引入redisson实现分布式锁
引入redisson
由于redisson提供了比较好的分布式锁解决方案,所以直接在项目中引入redisson
- 添加依赖
<!-- https://mvnrepository.com/artifact/org.redisson/redisson-spring-boot-starter --><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.24.3</version></dependency>
- 配置文件
- 测试
引入webflux用于请求外部接口
有时候我们需要请求第三方接口,我们有多种选择,具体选择哪个比较好,我们来看看AI智能助手的回答:
在Spring Boot中发送HTTP请求可以使用多种框架,每个框架都有其特点和适用场景。以下是几个常用的选项:
- Spring’s
RestTemplate
: Spring Boot内置支持,易于集成和使用。RestTemplate
提供了丰富的方法来消费RESTful服务。它包括了多种便捷的方法来远程调用HTTP服务,并可以轻松地将响应绑定到POJOs上。但从Spring 5开始,RestTemplate
被标记为不推荐使用(deprecated),Spring团队推荐使用WebClient
。- Spring’s
WebClient
:WebClient
是Spring 5中引入的,它是一个更现代的、功能更全面的替代RestTemplate
的选项。WebClient
支持同步和异步请求,并且提供了更灵活的错误处理机制。WebClient
是在Spring WebFlux中引入的,但也可以在Spring MVC应用程序中使用。- OkHttp: OkHttp是一个高效的HTTP客户端,支持同步和异步请求,提供了快速的性能和广泛的功能,如连接池、GZIP压缩和响应缓存。OkHttp适用于需要精细控制HTTP通信的场景,但它不是Spring的一部分,需要单独添加依赖和配置。
- Apache HttpClient: 这是另一个流行的HTTP客户端库。它提供了丰富的功能,如连接管理、认证机制、缓存支持等。与OkHttp类似,Apache HttpClient不是Spring框架的一部分,需要额外配置。
选择哪个框架取决于您的具体需求:
- 如果您需要与Spring生态系统紧密集成,并且不介意使用反应式编程模型,可以选择
WebClient
。- 如果您需要更精细的控制和高性能,并且不介意添加额外的依赖和配置,可以选择OkHttp或Apache HttpClient。
- 如果您的项目已经使用了Spring 5以下的版本,
RestTemplate
仍然是一个可行的选项,尽管它已被标记为不推荐使用。总的来说,OkHttp是一个非常好的选择,特别是在需要高性能和定制HTTP请求的场景中。但如果您希望与Spring更紧密地集成,并利用Spring的反应式编程功能,那么
WebClient
可能是更好的选择。
基于上面的信息,本项目决定使用webflux,有以下几点考虑:
- 我们目前使用的是Spring最新版, spring webflux集成度更好
- 本项目想要接入gpt,获取流式响应,webflux最适合
下面开始具体步骤:
- 引入依赖:
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webflux --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>
- controller
未完待续…
版权归原作者 GL_C 所有, 如有侵权,请联系我们删除。