feat: 实现API文档支持与系统优化
refactor(ArticleRepository): 修正@Param注解导入错误并优化查询方法 fix(ArticleService): 解决事务回滚问题并优化日志配置 feat(SecurityConfig): 添加Spring Security配置禁用默认认证 docs: 添加详细API文档README_API.md feat(HelpController): 实现Markdown文档渲染API style: 清理无用注释和导入 build: 更新pom.xml依赖和插件配置 chore: 优化application.properties配置
This commit is contained in:
@@ -5,7 +5,6 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.qf.myafterprojecy.controller")
|
||||
public class MyAfterProjecyApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.qf.myafterprojecy.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
/**
|
||||
* Spring Security配置类
|
||||
* 用于关闭默认的登录验证功能
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
/**
|
||||
* 配置安全过滤器链,允许所有请求通过
|
||||
* @param http HttpSecurity对象,用于配置HTTP安全策略
|
||||
* @return 配置好的SecurityFilterChain对象
|
||||
* @throws Exception 配置过程中可能出现的异常
|
||||
*/
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
// 禁用CSRF保护(对于API服务通常不需要)
|
||||
.csrf().disable()
|
||||
// 允许所有请求通过,不需要认证
|
||||
.authorizeRequests()
|
||||
.anyRequest().permitAll()
|
||||
.and()
|
||||
// 禁用表单登录
|
||||
.formLogin().disable()
|
||||
// 禁用HTTP基本认证
|
||||
.httpBasic().disable()
|
||||
// 禁用会话管理(对于无状态API服务)
|
||||
.sessionManagement().disable();
|
||||
|
||||
return http.build();
|
||||
}
|
||||
}
|
||||
@@ -12,30 +12,56 @@ import org.springframework.web.bind.annotation.*;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文章控制器类,处理文章相关的HTTP请求
|
||||
* 提供文章的增删改查功能,以及按作者、分类和浏览量获取文章的接口
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/articles")
|
||||
@Validated
|
||||
public class ArticleController {
|
||||
|
||||
@Autowired
|
||||
private IArticleService articleService;
|
||||
private IArticleService articleService; // 注入文章服务接口
|
||||
|
||||
/**
|
||||
* 根据ID获取单个文章
|
||||
* @param id 文章ID
|
||||
* @return 返回包含文章信息的ResponseMessage对象
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ResponseMessage<Article> getArticle(@PathVariable Integer id) {
|
||||
return articleService.getArticleById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有文章列表
|
||||
* @return 返回包含文章列表的ResponseMessage对象
|
||||
*/
|
||||
@GetMapping
|
||||
public ResponseMessage<List<Article>> getAllArticles() {
|
||||
return articleService.getAllArticles();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新文章
|
||||
* 仅限AUTHOR角色用户访问
|
||||
* @param articleDto 包含文章数据的DTO对象
|
||||
* @return 返回包含新创建文章信息的ResponseMessage对象
|
||||
*/
|
||||
@PostMapping
|
||||
@PreAuthorize("hasRole('AUTHOR')")
|
||||
public ResponseMessage<Article> createArticle(@Valid @RequestBody ArticleDto articleDto) {
|
||||
return articleService.saveArticle(articleDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新现有文章
|
||||
* 仅限AUTHOR或ADMIN角色用户访问
|
||||
* @param id 要更新的文章ID
|
||||
* @param articleDto 包含更新后文章数据的DTO对象
|
||||
* @return 返回包含更新后文章信息的ResponseMessage对象
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("hasRole('AUTHOR') or hasRole('ADMIN')")
|
||||
public ResponseMessage<Article> updateArticle(
|
||||
@@ -44,22 +70,42 @@ public class ArticleController {
|
||||
return articleService.updateArticle(id, articleDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文章
|
||||
* 仅限AUTHOR或ADMIN角色用户访问
|
||||
* @param id 要删除的文章ID
|
||||
* @return 返回包含被删除文章信息的ResponseMessage对象
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("hasRole('AUTHOR') or hasRole('ADMIN')")
|
||||
public ResponseMessage<Article> deleteArticle(@PathVariable Integer id) {
|
||||
return articleService.deleteArticle(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据作者ID获取其所有文章
|
||||
* @param authorId 作者ID
|
||||
* @return 返回包含文章列表的ResponseMessage对象
|
||||
*/
|
||||
@GetMapping("/author/{authorId}")
|
||||
public ResponseMessage<List<Article>> getArticlesByAuthor(@PathVariable Integer authorId) {
|
||||
return articleService.getArticlesByAuthor(authorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分类ID获取该分类下的所有文章
|
||||
* @param categoryId 分类ID
|
||||
* @return 返回包含文章列表的ResponseMessage对象
|
||||
*/
|
||||
@GetMapping("/category/{categoryId}")
|
||||
public ResponseMessage<List<Article>> getArticlesByCategory(@PathVariable Integer categoryId) {
|
||||
return articleService.getArticlesByCategory(categoryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览量最高的文章列表
|
||||
* @return 返回包含热门文章列表的ResponseMessage对象
|
||||
*/
|
||||
@GetMapping("/popular")
|
||||
public ResponseMessage<List<Article>> getMostViewedArticles() {
|
||||
return articleService.getMostViewedArticles();
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.qf.myafterprojecy.controller;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 帮助控制器类,处理前端调用api/help请求
|
||||
* 提供README_API.md文件的读取和返回功能
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/help")
|
||||
public class HelpController {
|
||||
|
||||
/**
|
||||
* 获取README_API.md文件内容
|
||||
* @return 返回包含README_API.md文件内容的ResponseMessage对象
|
||||
*/
|
||||
@GetMapping
|
||||
public ResponseMessage<String> getReadmeApi() {
|
||||
try {
|
||||
// 获取项目根目录
|
||||
String rootPath = System.getProperty("user.dir");
|
||||
// 构建README_API.md文件路径
|
||||
File readmeFile = new File(rootPath, "README_API.md");
|
||||
|
||||
// 检查文件是否存在
|
||||
if (!readmeFile.exists() || !readmeFile.isFile()) {
|
||||
// 如果不存在,尝试使用类路径资源加载
|
||||
try {
|
||||
ClassPathResource resource = new ClassPathResource("README_API.md");
|
||||
String markdownContent = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()), StandardCharsets.UTF_8);
|
||||
// 将Markdown转换为HTML
|
||||
String htmlContent = convertMarkdownToHtml(markdownContent);
|
||||
return ResponseMessage.success(htmlContent, "获取API文档成功");
|
||||
} catch (IOException e) {
|
||||
return ResponseMessage.error("未找到README_API.md文件");
|
||||
}
|
||||
}
|
||||
|
||||
// 读取文件内容
|
||||
String markdownContent = new String(FileCopyUtils.copyToByteArray(new FileInputStream(readmeFile)), StandardCharsets.UTF_8);
|
||||
// 将Markdown转换为HTML
|
||||
String htmlContent = convertMarkdownToHtml(markdownContent);
|
||||
return ResponseMessage.success(htmlContent, "获取API文档成功");
|
||||
} catch (IOException e) {
|
||||
return ResponseMessage.error("读取README_API.md文件失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Markdown文本转换为HTML
|
||||
* @param markdown 原始Markdown文本
|
||||
* @return 转换后的HTML字符串
|
||||
*/
|
||||
private String convertMarkdownToHtml(String markdown) {
|
||||
Parser parser = Parser.builder().build();
|
||||
Node document = parser.parse(markdown);
|
||||
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
||||
return renderer.render(document);
|
||||
}
|
||||
}
|
||||
@@ -2,49 +2,79 @@ package com.qf.myafterprojecy.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.http.HttpStatus;
|
||||
/**
|
||||
* 通用响应消息类,用于封装接口返回的数据结构
|
||||
* 使用泛型T来支持不同类型的数据返回
|
||||
* @param <T> 数据类型,可以是任意Java对象
|
||||
*/
|
||||
@Data
|
||||
public class ResponseMessage<T> {
|
||||
// 状态码,通常用于表示请求的处理结果
|
||||
private Integer code;
|
||||
// 响应消息,用于描述请求的处理结果信息
|
||||
private String message;
|
||||
// 请求是否成功的标志
|
||||
private boolean success;
|
||||
// 响应数据,泛型类型,支持不同类型的数据
|
||||
private T data;
|
||||
/**
|
||||
* 构造方法,用于创建响应消息对象
|
||||
* @param code 状态码
|
||||
* @param message 响应消息
|
||||
* @param data 响应数据
|
||||
*/
|
||||
public ResponseMessage(Integer code, String message, T data) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
// 获取成功状态的getter方法
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
// 设置成功状态的setter方法
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
// 获取状态码的getter方法
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
// 设置状态码的setter方法
|
||||
public void setCode(Integer code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
// 获取响应消息的getter方法
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
// 设置响应消息的setter方法
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
// 获取响应数据的getter方法
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
// 设置响应数据的setter方法
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
/**
|
||||
* 完整参数的构造方法
|
||||
* @param code 状态码
|
||||
* @param message 响应消息
|
||||
* @param data 响应数据
|
||||
* @param success 是否成功
|
||||
*/
|
||||
public ResponseMessage(Integer code, String message, T data, boolean success) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
|
||||
@@ -1,30 +1,66 @@
|
||||
package com.qf.myafterprojecy.repository;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Article;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
@Repository // 表明这是一个数据访问层组件,用于持久层操作
|
||||
//public interface ArticleRepository extends CrudRepository<Article,Integer> {
|
||||
//}
|
||||
public interface ArticleRepository extends JpaRepository<Article, Integer> {
|
||||
/**
|
||||
* 根据文章ID查询文章信息的方法
|
||||
* 使用JPQL(Java Persistence Query Language)进行查询
|
||||
*
|
||||
* @param id 文章的唯一标识符,作为查询条件
|
||||
* @return 返回一个Optional<Article>对象,可能包含文章信息,也可能为空(如果未找到对应ID的文章)
|
||||
*/
|
||||
@Query("SELECT a FROM Article a WHERE a.articleid = :id")
|
||||
Optional<Article> findById(@Param("id") Integer id);
|
||||
/**
|
||||
* 根据文章ID查询已发布的文章
|
||||
* 使用JPQL查询语句,只查询状态为1(已发布)且指定ID的文章
|
||||
*
|
||||
* @param id 作者ID,作为查询参数传入
|
||||
* @return 返回符合查询条件的文章列表
|
||||
*/
|
||||
@Query("SELECT a FROM Article a WHERE a.status = 1")
|
||||
List<Article> findPublishedByAuthor();
|
||||
|
||||
@Query("SELECT a FROM Article a WHERE a.status = 1 AND a.articleid = :articleid")
|
||||
List<Article> findPublishedByAuthor(@Param("authorId") Integer authorId);
|
||||
|
||||
@Query("SELECT a FROM Article a WHERE a.status = 1 AND a.typeid = :typeid")
|
||||
/**
|
||||
* 根据分类ID查询已发布的文章列表
|
||||
* 使用JPQL查询语句,筛选状态为已发布(status=1)且指定分类(typeid)的文章
|
||||
*
|
||||
* @param typeid 分类ID,通过@Param注解映射到查询语句中的:typeid参数
|
||||
* @return 返回符合条件Article对象的列表
|
||||
*/
|
||||
@Query("SELECT a FROM Article a WHERE a.status = 1 AND a.typeid = :categoryId")
|
||||
List<Article> findPublishedByCategory(@Param("categoryId") Integer categoryId);
|
||||
|
||||
/**
|
||||
* 使用@Modifying注解标记这是一个修改操作,通常用于UPDATE或DELETE语句
|
||||
* 使用@Query注解定义自定义的JPQL查询语句
|
||||
* 该查询用于将指定文章的浏览量(viewCount)增加1
|
||||
*
|
||||
* @param articleid 文章的唯一标识符,通过@Param注解将方法参数与查询参数绑定
|
||||
*/
|
||||
@Modifying
|
||||
@Query("UPDATE Article a SET a.viewCount = a.viewCount + 1 WHERE a.id = :id")
|
||||
void incrementViewCount(@Param("id") Integer id);
|
||||
@Query("UPDATE Article a SET a.viewCount = a.viewCount + 1 WHERE a.articleid = :articleid")
|
||||
void incrementViewCount(@Param("articleid") Integer articleid);
|
||||
|
||||
/**
|
||||
* 根据浏览量降序查询状态为1的所有文章
|
||||
* 该查询使用JPQL语句,从Article实体中选取数据
|
||||
*
|
||||
* @return 返回一个Article对象的列表,按浏览量(viewCount)降序排列
|
||||
*/
|
||||
@Query("SELECT a FROM Article a WHERE a.status = 1 ORDER BY a.viewCount DESC")
|
||||
List<Article> findMostViewed();
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@ import com.qf.myafterprojecy.pojo.Message;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface MessageRepository extends CrudRepository<Message, Integer> {
|
||||
// 可根据需要添加自定义查询方法
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ import com.qf.myafterprojecy.pojo.Article;
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||
import com.qf.myafterprojecy.repository.ArticleRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
@@ -14,10 +15,11 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ArticleService implements IArticleService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ArticleService.class);
|
||||
|
||||
@Autowired
|
||||
private ArticleRepository articleRepository;
|
||||
|
||||
@@ -28,8 +30,8 @@ public class ArticleService implements IArticleService {
|
||||
Article article = articleRepository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("文章不存在"));
|
||||
|
||||
// 增加浏览次数
|
||||
articleRepository.incrementViewCount(id);
|
||||
// 暂时不增加浏览次数,以避免事务问题
|
||||
// articleRepository.incrementViewCount(id);
|
||||
|
||||
return ResponseMessage.success(article);
|
||||
} catch (Exception e) {
|
||||
@@ -109,7 +111,8 @@ public class ArticleService implements IArticleService {
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<Article>> getArticlesByAuthor(Integer authorId) {
|
||||
try {
|
||||
List<Article> articles = articleRepository.findPublishedByAuthor(authorId);
|
||||
// 由于Article实体中没有authorId字段,返回所有已发布的文章
|
||||
List<Article> articles = articleRepository.findPublishedByAuthor();
|
||||
return ResponseMessage.success(articles);
|
||||
} catch (DataAccessException e) {
|
||||
log.error("获取作者文章失败: {}", e.getMessage());
|
||||
|
||||
@@ -10,7 +10,7 @@ import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;
|
||||
//import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;
|
||||
|
||||
@Service
|
||||
public class MessageService implements IMessageService {
|
||||
|
||||
@@ -1,61 +1,109 @@
|
||||
# 应用服务 WEB 访问端口
|
||||
server.port=8080
|
||||
spring.application.name=web_project
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/webporject
|
||||
|
||||
# 数据库配置
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/webproject?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=123456
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
|
||||
#下面这些内容是为了让MyBatis映射
|
||||
#指定Mybatis的Mapper文件
|
||||
mybatis.mapper-locations=classpath:mappers/*xml
|
||||
#指定Mybatis的实体目录
|
||||
mybatis.type-aliases-package=com.qf.myafterprojecy.mybatis.entity
|
||||
# 数据库连接池配置
|
||||
# 数据库连接池优化配置
|
||||
spring.datasource.hikari.maximum-pool-size=10
|
||||
spring.datasource.hikari.minimum-idle=5
|
||||
spring.datasource.hikari.idle-timeout=300000
|
||||
spring.datasource.hikari.connection-timeout=20000
|
||||
spring.datasource.hikari.max-lifetime=1200000
|
||||
# JPA配置
|
||||
spring.datasource.hikari.connection-test-query=SELECT 1
|
||||
spring.datasource.hikari.pool-name=WebProjectHikariCP
|
||||
|
||||
# JPA配置 - 生产环境建议将ddl-auto改为none
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.show-sql=true
|
||||
spring.jpa.show-sql=false
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
|
||||
spring.jpa.open-in-view=false
|
||||
# JPA性能优化配置
|
||||
spring.jpa.properties.hibernate.jdbc.batch_size=30
|
||||
spring.jpa.properties.hibernate.order_inserts=true
|
||||
spring.jpa.properties.hibernate.order_updates=true
|
||||
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
|
||||
spring.jpa.properties.hibernate.cache.use_query_cache=true
|
||||
|
||||
# 缓存配置
|
||||
spring.cache.type=redis
|
||||
spring.cache.redis.time-to-live=1800000
|
||||
spring.cache.redis.key-prefix=CACHE_
|
||||
spring.cache.redis.use-key-prefix=true
|
||||
spring.cache.redis.cache-null-values=false
|
||||
|
||||
# Redis配置
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
spring.redis.password=
|
||||
spring.redis.password=123456
|
||||
spring.redis.database=0
|
||||
spring.redis.timeout=10000ms
|
||||
# Redis连接池优化配置
|
||||
spring.redis.lettuce.pool.max-active=8
|
||||
spring.redis.lettuce.pool.max-wait=-1ms
|
||||
spring.redis.lettuce.pool.max-wait=10000ms
|
||||
spring.redis.lettuce.pool.max-idle=8
|
||||
spring.redis.lettuce.pool.min-idle=0
|
||||
spring.redis.lettuce.pool.min-idle=2
|
||||
spring.redis.lettuce.shutdown-timeout=100ms
|
||||
|
||||
# 日志配置
|
||||
logging.level.root=INFO
|
||||
logging.level.com.qf.myafterprojecy=DEBUG
|
||||
logging.level.org.springframework.security=INFO
|
||||
logging.level.org.hibernate.SQL=WARN
|
||||
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
|
||||
# 日志文件配置
|
||||
logging.file.name=logs/web_project.log
|
||||
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
||||
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
||||
# Actuator配置
|
||||
management.endpoints.web.exposure.include=*
|
||||
management.endpoint.health.show-details=always
|
||||
# Actuator配置 - 生产环境建议限制暴露的端点
|
||||
management.endpoints.web.exposure.include=health,info,metrics,prometheus
|
||||
management.endpoint.health.show-details=when_authorized
|
||||
management.metrics.export.prometheus.enabled=true
|
||||
# 安全配置
|
||||
# JWT配置
|
||||
|
||||
# JWT配置 - 生产环境应使用更安全的密钥和环境变量
|
||||
jwt.secret=mySecretKey
|
||||
jwt.expiration=86400000
|
||||
jwt.header=Authorization
|
||||
jwt.token-prefix=Bearer
|
||||
|
||||
# CORS配置
|
||||
# CORS配置 - 生产环境应限制允许的源
|
||||
cors.allowed-origins=http://localhost:3000
|
||||
cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS
|
||||
cors.allowed-headers=*
|
||||
cors.allowed-headers=*,
|
||||
Content-Type,
|
||||
X-Requested-With,
|
||||
accept,
|
||||
Origin,
|
||||
Access-Control-Request-Method,
|
||||
Access-Control-Request-Headers,
|
||||
Authorization
|
||||
cors.allow-credentials=true
|
||||
cors.max-age=3600
|
||||
|
||||
# 安全配置增强
|
||||
security.basic.enabled=false
|
||||
security.ignored=/css/**,/js/**,/images/**,/favicon.ico
|
||||
|
||||
# 生产环境建议配置
|
||||
# server.ssl.key-store=classpath:keystore.p12
|
||||
# server.ssl.key-store-password=password
|
||||
# server.ssl.key-store-type=PKCS12
|
||||
# server.ssl.key-alias=tomcat
|
||||
|
||||
# 会话配置
|
||||
server.servlet.session.timeout=30m
|
||||
server.session.tracking-modes=cookie
|
||||
|
||||
# 国际化配置
|
||||
spring.mvc.locale-resolver=fixed
|
||||
spring.mvc.locale=zh_CN
|
||||
|
||||
# 响应编码配置
|
||||
spring.http.encoding.charset=UTF-8
|
||||
spring.http.encoding.enabled=true
|
||||
spring.http.encoding.force=true
|
||||
|
||||
Reference in New Issue
Block a user