赞
踩
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="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>
package com.glc.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GlcClientApplication {
public static void main(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)
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)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
2.在test.java.com.glc.client
下面添加GlcClientApplicationTest
文件,输入以下测试代码:
package com.glc.client;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class GlcClientApplicationTest {
@Test
void main() {
System.out.println("test");
}
}
package com.glc.client.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@GetMapping("/")
public String home(){
return "Hello World!";
}
}
后面会用到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 -->
<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驱动程序。
在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%2B8 username: root password: 123456 hikari: minimum-idle: 5 idle-timeout: 600000 maximum-pool-size: 32 auto-commit: true pool-name: HikariCorePool max-lifetime: 1800000 connection-timeout: 30000 connection-test-query: select TABLE_NAME from information_schema.tables limit 1 connection-init-sql: SET NAMES utf8mb4
在做完下面的mybatis plus相关的引入之后启动项目并第一次测试数据库查询相关接口之后,可以看到HikariCorePool - Start completed.
,说明数据库连接池启动成功。
<!-- 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>
package com.glc.client.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @MapperScan("com.glc.client.mapper*") public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); PaginationInnerInterceptor innerInterceptor = new PaginationInnerInterceptor(); innerInterceptor.setDbType(DbType.MYSQL); innerInterceptor.setMaxLimit(100000L); interceptor.addInnerInterceptor(innerInterceptor); return interceptor; } }
该插件主要用于一键生成表相关的实体类。
<!-- 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>
package com.glc.client; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.FastAutoGenerator; import com.baomidou.mybatisplus.generator.config.OutputFile; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.DbColumnType; import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine; import com.baomidou.mybatisplus.generator.fill.Column; import com.baomidou.mybatisplus.generator.fill.Property; import org.apache.commons.lang3.StringUtils; import java.sql.Types; import java.util.Collections; public class MybatisPlusGenerator { public static void main(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) { // 自定义类型转换 return DbColumnType.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(new Column("create_time", FieldFill.INSERT)) // 自动填充配置 .addTableFills(new Property("update_time", FieldFill.INSERT_UPDATE)) .enableLombok() //开启lombok .logicDeleteColumnName("deleted")// 假删除字段 .enableTableFieldAnnotation()// 自动添加表字段的注解 .controllerBuilder() //controller 策略配置 .formatFileName("%sController") .enableRestStyle() // 开启RestController注解 .mapperBuilder()// mapper策略配置 .formatMapperFileName("%sMapper") .formatXmlFileName("%sMapper"); }) .templateEngine(new VelocityTemplateEngine()) .execute(); } }
这样mybatis的代码生成器就配置完成了,之后需要添加新的表只需要改一下MybatisPlusGenerator里的表名就行了,idType看实际需求选择AUTO(自增id)还是ASSIGN_ID(雪花算法生成的id)
为了方便调试接口,可以引入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: true setting: language: zh_cn production: false
package com.glc.client.controller; import com.glc.client.model.FileResp; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("body") @Tag(name = "body参数") public class BodyController { @Operation(summary = "普通body请求") @PostMapping("/body") public ResponseEntity<FileResp> body(@RequestBody FileResp fileResp) { return ResponseEntity.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}") public ResponseEntity<FileResp> bodyParamHeaderPath(@PathVariable("id") String id, @RequestHeader("token") String token, @RequestParam("name") String name, @RequestBody FileResp fileResp) { fileResp.setName(fileResp.getName() + ",receiveName:" + name + ",token:" + token + ",pathID:" + id); return ResponseEntity.ok(fileResp); } }
其中FileResp如下:
package com.glc.client.model;
import lombok.Data;
@Data
public class FileResp {
private String name;
private Long fileSize;
private Boolean deleted;
}
然后启动项目,访问:http://127.0.0.1:8077/doc.html, 看到如下界面, 说明成功了:
测试接口结果如下:
至此knife4j就配置完成了,下面来看看knife的增强配置。
首先看看官方说明:
在以前的版本中,开发者需要在配置文件中手动使用@EnableKnife4j来使用增强,自2.0.6版本后,只需要在配置文件中配置knife4j.enable=true即可不在使用注解
knife4j:
# 开启增强配置
enable: true
# 开启Swagger的Basic认证功能,默认是false
basic:
enable: true
# Basic认证用户名
username: test
# Basic认证密码
password: 123
目前暂时没有其他增强配置的需求。官方文档已经很详细了,有需要的话直接查阅官方文档。
下面我们将使用mybatis自带的分页功能进行分页查询
package com.glc.client.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @MapperScan("com.glc.client.mapper*") public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); PaginationInnerInterceptor innerInterceptor = new PaginationInnerInterceptor(); innerInterceptor.setDbType(DbType.MYSQL); innerInterceptor.setMaxLimit(100000L); interceptor.addInnerInterceptor(innerInterceptor); return interceptor; } }
package com.glc.client.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.glc.client.entity.User; import com.glc.client.service.impl.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * <p> * 前端控制器 * </p> * * @author gulong * @since 2023-11-12 */ @RestController @RequestMapping("user") public class UserController { @Autowired private UserService userService; /** * 用户列表分页查询 * * @param current 当前页数 * @param size 每页条数 * @return ResponseEntity<Page<User>> */ @GetMapping("/page") public ResponseEntity<Page<User>> userPageQuery(@RequestParam("current") Integer current, @RequestParam("size") Integer size) { Page<User> pageParam = new Page<>(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); return ResponseEntity.ok(pageResult); } }
user/page
接口,结果如下:有时候我们可能对一些复杂的查询使用自定义的sql,我们可以用如下的方法进行分页查询。
UserController.java
/**
* 分页查询当天注册的用户信息
*
* @param current 当前页数
* @param size 每页条数
* @return user
*/
@GetMapping("/today")
public ResponseEntity<Page<User>> todayUserPageQuery(@RequestParam("current") Integer current,
@RequestParam("size") Integer size) {
Page<User> page = new Page<>(current, size);
String todayDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
userMapper.selectPageVo(page, todayDate);
return ResponseEntity.ok(page);
}
UserMapper.java
package com.glc.client.mapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.glc.client.entity.User; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Param; /** * <p> * Mapper 接口 * </p> * * @author gulong * @since 2023-11-12 */ public interface UserMapper extends BaseMapper<User> { Page<User> selectPageVo(@Param("page") Page<User> page, @Param("todayDate") String todayDate); }
UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.glc.client.mapper.UserMapper">
<select id="selectPageVo" resultType="com.glc.client.entity.User">
select id, create_time as createTime
from user
where create_time >= #{todayDate}
</select>
</mapper>
这样就实现了自定义的分页查询。
在上面的接口返回结果中,我们可以看到createTime的格式对前端不友好,我们统一个改成常用的yyyy-MM-dd HH:mm:ss
格式。本项目暂时未引入fastjson,在springboot中默认使用的是jackjson对接口返回的数据进行序列化,所以我们可以在yml文件中配置全局默认时间序列化格式。
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
在上面的结果中,id的类型为long,这种类型的数据在返回给前端的时候如果数字过大,就会产生精度丢失的问题。
来看看AI智能助手对于这个问题的解释:
JavaScript中的Number类型仅能安全地表示-253到253之间的整数(即安全整数范围),而超出此范围的大整数在JavaScript中可能无法精确表示。
通常对此类问题的处理方法就是把这个long序列为string。
本项目默认使用jackjson序列化,所以可以使用如下注解来解决:
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
如果是使用fastjson序列化,则用如下注解:
@JSONField(serializeUsing = ToStringSerializer.class)
private Long id;
web开发中,redis相关的操作是基本离不开的,下面将添加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>
application-dev.yml
配置redis信息:spring:
data:
redis:
host: localhost
port: 6379
password: 123456
database: 0
connect-timeout: 30000
timeout: 10000
lettuce:
pool:
min-idle: 16
max-idle: 32
max-active: 128
max-wait: 30000
GenericJackson2JsonRedisSerializer
,这种会在redis里面存储类的信息,对于其他项目读取该数据非常不友好,package com.glc.client; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.glc.client.model.FileResp; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.StringRedisTemplate; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @SpringBootTest public class RedisTest { @Autowired StringRedisTemplate stringRedisTemplate; @Test void testString() { //存储/读取字符串 stringRedisTemplate.opsForValue().set("test-string", "redis-value"); String value = stringRedisTemplate.opsForValue().get("test-string"); System.out.printf(value); stringRedisTemplate.delete("test-string"); } @Test void testJsonString() throws JsonProcessingException { FileResp afile = new FileResp("afile", 123l, true); FileResp bfile = new FileResp("bfile", 123l, false); List<FileResp> list = Arrays.asList(afile, bfile); stringRedisTemplate.opsForValue().set("test-json-string", new ObjectMapper().writeValueAsString(list)); String jsonValue = stringRedisTemplate.opsForValue().get("test-json-string"); System.out.printf(jsonValue); List<FileResp> fromRedis = new ObjectMapper().readValue(jsonValue, new TypeReference<>() { }); for (FileResp item : fromRedis) { System.out.println(item); } stringRedisTemplate.delete("test-json-string"); } @Test void testHash() throws JsonProcessingException { FileResp afile = new FileResp("afile", 123l, true); FileResp bfile = new FileResp("bfile", 123l, false); stringRedisTemplate.opsForHash().put("test-hash", "hash-1", new ObjectMapper().writeValueAsString(afile)); stringRedisTemplate.opsForHash().put("test-hash", "hash-2", new ObjectMapper().writeValueAsString(bfile)); String value = (String) stringRedisTemplate.opsForHash().get("test-hash", "hash-2"); System.out.println(value); FileResp fileResp = new ObjectMapper().readValue(value, FileResp.class); System.out.println(fileResp); stringRedisTemplate.delete("test-hash"); } @Test void testList() { FileResp afile = new FileResp("afile", 123l, true); FileResp bfile = new FileResp("bfile", 123l, false); List<FileResp> list = Arrays.asList(afile, bfile); //数组里面只能是string ObjectMapper objectMapper = new ObjectMapper(); List<String> jsonStrings = list.stream() .map(fileResp -> { try { return objectMapper.writeValueAsString(fileResp); } catch (JsonProcessingException e) { throw new RuntimeException(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
<!-- 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>
有时候我们需要请求第三方接口,我们有多种选择,具体选择哪个比较好,我们来看看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,有以下几点考虑:
下面开始具体步骤:
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webflux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
未完待续…
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。