完成后端全部内容,等待后续修补

This commit is contained in:
柏码の讲师 2023-08-06 00:31:38 +08:00
parent b91c790f8c
commit 0320a79e33
8 changed files with 180 additions and 19 deletions

View File

@ -2,6 +2,17 @@
采用SpringBoot3 + Vue3编写的前后端分离模版项目集成多种技术栈使用JWT校验方案。
***
### 后端功能与技术点
* 用户注册、用户登录、重置密码
用户注册、用户登录、重置密码等基础功能以及对应接口
* 采用Mybatis-Plus作为持久层框架使用更便捷
* 采用Redis存储注册/重置操作验证码,带过期时间控制
* 采用RabbitMQ积压短信发送任务再由监听器统一处理
* 采用SpringSecurity作为权限校验框架手动整合Jwt校验方案
* 采用Redis进行IP地址限流处理防刷接口
* 视图层对象和数据层对象分离,编写工具方法利用反射快速互相转换
* 错误和异常页面统一采用JSON格式返回前端处理响应更统一
* 手动处理跨域,采用过滤器实现
* 使用Swagger作为接口文档自动生成已自动配置登录相关接口
* 采用过滤器实现对所有请求自动生成雪花ID方便线上定位问题
* 项目整体结构清晰,职责明确,注释全面,开箱即用
### 前端功能与技术点

View File

@ -88,6 +88,12 @@
<artifactId>java-jwt</artifactId>
<version>4.3.0</version>
</dependency>
<!-- Swagger文档生成框架 -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
<profiles>

View File

@ -53,8 +53,8 @@ public class SecurityConfiguration {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(conf -> conf
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/error").permitAll()
.requestMatchers("/api/auth/**", "/error").permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.anyRequest().hasAnyRole(Const.ROLE_DEFAULT)
)
.formLogin(conf -> conf

View File

@ -0,0 +1,113 @@
package com.example.config;
import com.example.entity.RestBean;
import com.example.entity.vo.response.AuthorizeVO;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.parameters.QueryParameter;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Swagger开发文档相关配置
*/
@Configuration
@SecurityScheme(type = SecuritySchemeType.HTTP, scheme = "Bearer",
name = "Authorization", in = SecuritySchemeIn.HEADER)
@OpenAPIDefinition(security = { @SecurityRequirement(name = "Authorization") })
public class SwaggerConfiguration {
/**
* 配置文档介绍以及详细信息
* @return OpenAPI
*/
@Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info().title("示例项目 API 文档")
.description("欢迎来到本示例项目API测试文档在这里可以快速进行接口调试")
.version("1.0")
.license(new License()
.name("项目开源地址")
.url("https://github.com/Ketuer/SpringBoot-Vue-Template-Jwt")
)
)
.externalDocs(new ExternalDocumentation()
.description("我们的官方网站")
.url("https://itbaima.net")
);
}
/**
* 配置自定义的OpenApi相关信息
* @return OpenApiCustomizer
*/
@Bean
public OpenApiCustomizer customerGlobalHeaderOpenApiCustomizer() {
return api -> this.authorizePathItems().forEach(api.getPaths()::addPathItem);
}
/**
* 登录接口和退出登录接口手动添加一下
* @return PathItems
*/
private Map<String, PathItem> authorizePathItems(){
Map<String, PathItem> map = new HashMap<>();
map.put("/api/auth/login", new PathItem()
.post(new Operation()
.tags(List.of("登录校验相关"))
.summary("登录验证接口")
.addParametersItem(new QueryParameter()
.name("username")
.required(true)
)
.addParametersItem(new QueryParameter()
.name("password")
.required(true)
)
.responses(new ApiResponses()
.addApiResponse("200", new ApiResponse()
.description("OK")
.content(new Content().addMediaType("*/*", new MediaType()
.example(RestBean.success(new AuthorizeVO()).asJsonString())
))
)
)
)
);
map.put("/api/auth/logout", new PathItem()
.get(new Operation()
.tags(List.of("登录校验相关"))
.summary("退出登录接口")
.responses(new ApiResponses()
.addApiResponse("200", new ApiResponse()
.description("OK")
.content(new Content().addMediaType("*/*", new MediaType()
.example(RestBean.success())
))
)
)
)
);
return map;
}
}

View File

@ -4,15 +4,14 @@ import com.example.entity.RestBean;
import com.example.entity.vo.request.EmailRegisterVO;
import com.example.entity.vo.request.EmailResetVO;
import com.example.service.AccountService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Email;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.function.Supplier;
@ -22,6 +21,7 @@ import java.util.function.Supplier;
@Validated
@RestController
@RequestMapping("/api/auth")
@Tag(name = "登录校验相关", description = "包括用户登录、注册、验证码请求等操作。")
public class AuthorizeController {
@Resource
@ -34,6 +34,7 @@ public class AuthorizeController {
* @return 是否请求成功
*/
@PostMapping("/ask-code")
@Operation(summary = "请求邮件验证码")
public RestBean<Void> askVerifyCode(@RequestParam @Email String email,
HttpServletRequest request){
return this.messageHandle(() ->
@ -46,7 +47,8 @@ public class AuthorizeController {
* @return 是否注册成功
*/
@PostMapping("/register")
public RestBean<Void> register(@Valid EmailRegisterVO vo){
@Operation(summary = "用户注册操作")
public RestBean<Void> register(@RequestBody @Valid EmailRegisterVO vo){
return this.messageHandle(() ->
accountService.registerEmailAccount(vo));
}
@ -57,7 +59,8 @@ public class AuthorizeController {
* @return 是否操作成功
*/
@PostMapping("/reset-password")
public RestBean<Void> reset(@Valid EmailResetVO vo){
@Operation(summary = "密码重置操作")
public RestBean<Void> reset(@RequestBody @Valid EmailResetVO vo){
return this.messageHandle(() ->
accountService.resetEmailAccountPassword(vo));
}

View File

@ -17,6 +17,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingResponseWrapper;
import java.io.IOException;
import java.util.Set;
/**
* 请求日志过滤器用于记录所有用户请求信息
@ -28,14 +29,32 @@ public class RequestLogFilter extends OncePerRequestFilter {
@Resource
SnowflakeIdGenerator generator;
private final Set<String> ignores = Set.of("/swagger-ui", "/v3/api-docs");
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
long startTime = System.currentTimeMillis();
this.logRequestStart(request);
ContentCachingResponseWrapper wrapper = new ContentCachingResponseWrapper(response);
filterChain.doFilter(request, wrapper);
this.logRequestEnd(wrapper, startTime);
wrapper.copyBodyToResponse();
if(this.isIgnoreUrl(request.getServletPath())) {
filterChain.doFilter(request, response);
} else {
long startTime = System.currentTimeMillis();
this.logRequestStart(request);
ContentCachingResponseWrapper wrapper = new ContentCachingResponseWrapper(response);
filterChain.doFilter(request, wrapper);
this.logRequestEnd(wrapper, startTime);
wrapper.copyBodyToResponse();
}
}
/**
* 判定当前请求url是否不需要日志打印
* @param url 路径
* @return 是否忽略
*/
private boolean isIgnoreUrl(String url){
for (String ignore : ignores) {
if(url.startsWith(ignore)) return true;
}
return false;
}
/**

View File

@ -1,4 +1,8 @@
# 开发环境配置
springdoc:
paths-to-match: /api/**
swagger-ui:
operations-sorter: alpha
spring:
mail:
host: smtp.163.com
@ -29,12 +33,9 @@ spring:
mail-limit: 60
flow:
period: 3
limit: 10
limit: 50
block: 30
cors:
origin: '*'
credentials: false
methods: '*'
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

View File

@ -1,4 +1,12 @@
#生产环境配置
server:
port: 80
springdoc:
api-docs:
enabled: false
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
mail:
host: smtp.163.com