# springboot-api
**Repository Path**: miaokela/springboot-api
## Basic Information
- **Project Name**: springboot-api
- **Description**: restapi需要的相关组件
- **Primary Language**: Java
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2024-02-28
- **Last Updated**: 2024-03-07
## Categories & Tags
**Categories**: Uncategorized
**Tags**: SpringBoot, Java
## README
## Spring Boot简易代码
### 整合mybatisplus
##### 引入依赖
```xml
mysql
mysql-connector-java
8.0.25
com.baomidou
mybatis-plus-boot-starter
${mybatis.version}
```
##### 配置文件 application.yml
```yaml
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:6666/springboot_demo
hikari:
minimum-idle: 5
maximum-pool-size: 20
auto-commit: true
idle-timeout: 30000
pool-name: MyHikariCP
max-lifetime: 1800000
connection-timeout: 30000
mybatis-plus:
mapper-locations: classpath*:mappers/*.xml
```
##### 实体类
```java
@Data
@TableName("`user`") // 表注解
public class User {
@TableId(type = IdType.AUTO) // 主键注解
private Long id;
private String name;
private Integer age;
private String email;
}
```
##### mapper接口
```java
// mapper.UserMapper
public interface UserMapper extends BaseMapper {
}
```
##### 直接使用Mapper处理数据
```java
@SpringBootTest(classes = Application.class)
public class SampleTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelect() {
System.out.println("测试...");
List list = userMapper.selectList(null);
System.out.println(list);
list.forEach(item -> {
System.out.println("Name:" + item.getName());
});
}
@Test
public void testInsert() {
User user = new User();
user.setName("John Doe");
user.setAge(30);
user.setEmail("john.doe@example.com");
userMapper.insert(user);
}
@Test
public void testUpdate() {
User userToUpdate = userMapper.selectById(1L);
userToUpdate.setEmail("new.email@example.com");
userMapper.updateById(userToUpdate);
}
@Test
public void testSelectById() {
User user = userMapper.selectById(1L);
System.out.println(user);
}
@Test
public void deleteById() {
userMapper.deleteById(1L);
}
}
```
##### 使用IService接口的方式
* 继承IService接口
```java
public interface UserService extends IService {
}
```
* 继承ServiceImpl接口,实现UserService的实现类
```java
@Service
public class UserServiceImpl extends ServiceImpl implements UserService {
}
```
* 测试IService方式
```java
@Test
public void testInsertService() {
User user = new User();
user.setName("John Doe");
user.setAge(30);
user.setEmail("john.doe@example.com");
userService.save(user);
}
@Test
public void testDeleteService() {
userService.removeById(1L);
}
@Test
public void testUpdateService() {
User userToUpdate = userService.getById(2L);
userToUpdate.setEmail("new.email@example.com");
userService.updateById(userToUpdate);
}
@Test
public void testSelectService() {
List list = userService.list();
System.out.println(list);
list.forEach(item -> {
System.out.println("Name:" + item.getName());
});
}
@Test
public void testSelectByIdService() {
User user = userService.getById(2L);
System.out.println(user);
}
```
##### 复杂的数据处理
```java
@SpringBootTest(classes = Application.class)
public class SampleTest {
@Autowired
private UserMapper userMapper;
/**
* QueryWrapper
*/
@Test
public void testQueryWrapper() {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John Doe")
.between("age", 20, 30)
.isNotNull("email");
List users = userMapper.selectList(queryWrapper);
System.out.println(users);
}
/**
* UpdateWrapper
*/
@Test
public void testUpdateWrapper() {
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.set("email", "new.email@example.com")
.eq("name", "John Doe")
.between("age", 20, 30)
.isNotNull("email");
int rows = userMapper.update(null, updateWrapper);
System.out.println(rows + " rows updated");
}
/**
* Wrapper自定义SQL
*/
@Test
public void testWrapper() {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.apply("name = {0}", "John Doe");
List users = userMapper.selectList(queryWrapper);
System.out.println(users);
}
/**
* LambdaQueryWrapper
*/
@Test
public void testLambdaQueryWrapper() {
LambdaQueryWrapper userLambdaQueryWrapper = Wrappers.lambdaQuery(User.class);
userLambdaQueryWrapper.eq(User::getName, "John Doe")
.between(User::getAge, 20, 30)
.isNotNull(User::getEmail);
List users = userMapper.selectList(userLambdaQueryWrapper);
System.out.println(users);
}
/**
* LambdaUpdateWrapper
*/
@Test
public void testLambdaUpdateWrapper() {
LambdaUpdateWrapper userLambdaUpdateWrapper = Wrappers.lambdaUpdate(User.class);
userLambdaUpdateWrapper.set(User::getEmail, "new.email@example.com")
.eq(User::getName, "John Doe")
.between(User::getAge, 20, 30)
.isNotNull(User::getEmail);
int rows = userMapper.update(null, userLambdaUpdateWrapper);
System.out.println(rows + " rows updated");
}
/**
* 复杂的查询 比如连表
*/
@Test
public void testSelectWithOrder() {
OrderUserDTO orderUserDTO = orderWithUserMapper.selectOrderWithUser(1L);
System.out.println(orderUserDTO);
}
}
```
##### 复杂数据查询
* 定义Mapper接口
```java
public interface OrderWithUserMapper {
OrderUserDTO selectOrderWithUser(Long orderId);
}
```
* 编写mapper映射的xml
```xml
```
* 编写实体类
```java
@Data
public class OrderUserDTO {
private Long orderId;
private String orderDetails;
private Long userId;
private String userName;
}
```
* 测试查询
```java
@SpringBootTest(classes = Application.class)
public class SampleTest {
@Autowired
private OrderWithUserMapper orderWithUserMapper;
/**
* 复杂的查询 比如连表
*/
@Test
public void testSelectWithOrder() {
OrderUserDTO orderUserDTO = orderWithUserMapper.selectOrderWithUser(1L);
System.out.println(orderUserDTO);
}
}
```
### 统一响应格式
```java
// utils.ApiResponse
@Data
public class ApiResponse {
private int code;
private String message;
private T data;
public ApiResponse(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
}
```
### 全局异常处理
```java
// utils.GlobalExceptionHandler
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ApiResponse hanldeException(Exception e) {
return new ApiResponse<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), "服务器内部错误", null);
}
}
```
### Swagger接口文档
##### 引入依赖
```xml
com.github.xiaoymin
knife4j-spring-boot-starter
3.0.2
```
##### 编写配置类
```java
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.quickstart.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API 文档")
.description("API 文档描述")
.version("1.0")
.build();
}
}
```
##### 访问地址
> http://localhost:8080/doc.html
### 基础jwt认证
##### 引入依赖
```xml
org.springframework.boot
spring-boot-starter-security
io.jsonwebtoken
jjwt
0.9.1
```
##### JWT处理工具类
> 生成token,校验token
```java
@Component
public class JwtUtil {
private String secret = "yourSecretKey"; // 用于签名和验证JWT的密钥
private Integer expireTime = 1000 * 60 * 60 * 10;
// 从JWT令牌中提取用户名
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
// 从JWT令牌中提取特定的声明(claim)
public T getClaimFromToken(String token, Function claimsResolver) {
try {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
} catch (Exception e) {
return null;
}
}
// 为获取任何信息而解析JWT令牌
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}
// 验证JWT令牌
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()));
}
// 生成JWT令牌
public String generateToken(UserDetails userDetails) {
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + expireTime)) // 设置过期时间
.signWith(SignatureAlgorithm.HS512, secret).compact();
}
}
```
##### 添加过滤器
```java
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String authToken = request.getHeader("Authorization");
if (authToken != null && authToken.startsWith("Bearer ")) {
authToken = authToken.substring(7);
String username = jwtUtil.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
}
```
##### 注册过滤器
```java
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String authToken = request.getHeader("Authorization");
if (authToken != null && authToken.startsWith("Bearer ")) {
authToken = authToken.substring(7);
String username = jwtUtil.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
}
```
获取用户信息
> 上面提到一个Spring Security的UserDetailsService的实现,用来获取用户信息
```java
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final PasswordEncoder passwordEncoder;
public CustomUserDetailsService(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO 这里仅为示例,实际应用中应该从数据库或其他地方根据用户名查找用户信息
if ("admin".equals(username)) {
return User.builder()
.username("admin")
.password(passwordEncoder.encode("password"))
.roles("ADMIN") // 或者.authorities("ROLE_ADMIN")
.build();
} else {
throw new UsernameNotFoundException("User not found with username: " + username);
}
}
}
```
### 整合redis
##### 引入依赖
```xml
org.springframework.boot
spring-boot-starter-data-redis
io.lettuce
lettuce-core
redis.clients
jedis
```
##### 添加配置
```xml
spring:
redis:
host: localhost
port: 6379
timeout: 1000
jedis:
min-idle: 5
max-idle: 10
max-active: 10
max-wait: 2000
```
##### 创建配置类
```java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
RedisTemplate template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置序列化工具,这里使用JSON序列化
Jackson2JsonRedisSerializer