Compare commits
11 Commits
5803080352
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15eca0d0b5 | ||
|
|
f27be2130c | ||
|
|
9b01ee8889 | ||
|
|
505a7a0944 | ||
|
|
51392bf807 | ||
|
|
eb1f70d431 | ||
|
|
47c357695b | ||
|
|
d8c6c74de4 | ||
|
|
5136a3a78b | ||
|
|
25eeab4940 | ||
|
|
f6d1d719a9 |
4183
logs/web_project.log
4183
logs/web_project.log
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
53
pom.xml
53
pom.xml
@@ -18,11 +18,7 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.mybatis.spring.boot</groupId>
|
|
||||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
|
||||||
<version>2.2.2</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- Spring Security 核心依赖 -->
|
<!-- Spring Security 核心依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@@ -81,29 +77,13 @@
|
|||||||
<version>0.18.2</version>
|
<version>0.18.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- JCache API -->
|
<!-- JWT依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.cache</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>cache-api</artifactId>
|
<artifactId>jjwt</artifactId>
|
||||||
|
<version>0.9.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- EHCache 3作为JCache实现 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.ehcache</groupId>
|
|
||||||
<artifactId>ehcache</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax</groupId>
|
|
||||||
<artifactId>javaee-api</artifactId>
|
|
||||||
<version>8.0.1</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>log4j</groupId>
|
|
||||||
<artifactId>log4j</artifactId>
|
|
||||||
<version>1.2.17</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
@@ -138,6 +118,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>com.qf.myafterprojecy.MyAfterProjecyApplication</mainClass>
|
<mainClass>com.qf.myafterprojecy.MyAfterProjecyApplication</mainClass>
|
||||||
<skip>false</skip>
|
<skip>false</skip>
|
||||||
|
<jvmArguments>-Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8</jvmArguments>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
@@ -148,7 +129,27 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<!-- 添加资源编码配置 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>3.3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
<!-- 确保项目编译和资源处理使用UTF-8编码 -->
|
||||||
|
<sourceDirectory>src/main/java</sourceDirectory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -3,11 +3,40 @@ package com.qf.myafterprojecy;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用主类
|
||||||
|
* 设置系统编码并启动Spring Boot应用
|
||||||
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class MyAfterProjecyApplication {
|
public class MyAfterProjecyApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
// 在应用启动前设置系统编码,确保所有输出都使用UTF-8
|
||||||
|
setSystemEncoding();
|
||||||
|
|
||||||
|
// 启动Spring Boot应用
|
||||||
SpringApplication.run(MyAfterProjecyApplication.class, args);
|
SpringApplication.run(MyAfterProjecyApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置系统编码为UTF-8
|
||||||
|
* 解决控制台输出和日志中的中文乱码问题
|
||||||
|
*/
|
||||||
|
private static void setSystemEncoding() {
|
||||||
|
// 设置系统属性,确保所有输出流都使用UTF-8编码
|
||||||
|
System.setProperty("file.encoding", StandardCharsets.UTF_8.name());
|
||||||
|
System.setProperty("sun.stdout.encoding", StandardCharsets.UTF_8.name());
|
||||||
|
System.setProperty("sun.stderr.encoding", StandardCharsets.UTF_8.name());
|
||||||
|
|
||||||
|
// 设置默认字符编码
|
||||||
|
try {
|
||||||
|
java.nio.charset.Charset.defaultCharset();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 记录编码设置异常
|
||||||
|
System.err.println("设置默认字符编码时发生异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.qf.myafterprojecy.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.web.filter.CharacterEncodingFilter;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符编码配置类
|
||||||
|
* 确保所有HTTP请求和响应都使用UTF-8编码,解决中文乱码问题
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class CharacterEncodingConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建字符编码过滤器
|
||||||
|
* 优先级设置为最高,确保在所有其他过滤器之前执行
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public FilterRegistrationBean<Filter> characterEncodingFilter() {
|
||||||
|
// 创建字符编码过滤器
|
||||||
|
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
|
||||||
|
|
||||||
|
// 设置请求编码为UTF-8
|
||||||
|
encodingFilter.setEncoding(StandardCharsets.UTF_8.name());
|
||||||
|
|
||||||
|
// 强制请求使用UTF-8编码
|
||||||
|
encodingFilter.setForceRequestEncoding(true);
|
||||||
|
|
||||||
|
// 强制响应使用UTF-8编码
|
||||||
|
encodingFilter.setForceResponseEncoding(true);
|
||||||
|
|
||||||
|
// 创建过滤器注册Bean
|
||||||
|
FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>(encodingFilter);
|
||||||
|
|
||||||
|
// 设置过滤器顺序为最高优先级
|
||||||
|
registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||||
|
|
||||||
|
// 为所有请求路径注册过滤器
|
||||||
|
registrationBean.addUrlPatterns("/*");
|
||||||
|
|
||||||
|
return registrationBean;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.qf.myafterprojecy.config;
|
package com.qf.myafterprojecy.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
@@ -12,38 +13,67 @@ import org.springframework.web.filter.CorsFilter;
|
|||||||
@Configuration
|
@Configuration
|
||||||
public class CorsConfig {
|
public class CorsConfig {
|
||||||
|
|
||||||
|
// 从配置文件中读取CORS配置
|
||||||
|
@Value("${cors.allowed-origins}")
|
||||||
|
private String allowedOrigins;
|
||||||
|
|
||||||
|
@Value("${cors.allowed-methods}")
|
||||||
|
private String allowedMethods;
|
||||||
|
|
||||||
|
@Value("${cors.allowed-headers}")
|
||||||
|
private String allowedHeaders;
|
||||||
|
|
||||||
|
@Value("${cors.allow-credentials}")
|
||||||
|
private Boolean allowCredentials;
|
||||||
|
|
||||||
|
@Value("${cors.max-age:3600}")
|
||||||
|
private Long maxAge;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建CORS过滤器,配置跨域请求的规则
|
* 创建CORS过滤器,配置跨域请求的规则
|
||||||
|
* 从配置文件中读取CORS配置,实现配置的统一管理
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public CorsFilter corsFilter() {
|
public CorsFilter corsFilter() {
|
||||||
// 创建CORS配置对象
|
// 创建CORS配置对象
|
||||||
CorsConfiguration config = new CorsConfiguration();
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
|
|
||||||
// 允许的来源,这里允许所有来源,实际生产环境应该限制特定域名
|
// 允许的来源,从配置文件读取并分割
|
||||||
config.addAllowedOriginPattern("*");
|
String[] originsArray = allowedOrigins.split(",");
|
||||||
|
for (String origin : originsArray) {
|
||||||
|
config.addAllowedOrigin(origin.trim());
|
||||||
|
}
|
||||||
|
|
||||||
// 允许携带凭证(如Cookie)
|
// 允许携带凭证(如Cookie)
|
||||||
config.setAllowCredentials(true);
|
config.setAllowCredentials(allowCredentials);
|
||||||
|
|
||||||
// 允许的请求方法
|
// 允许的HTTP方法,从配置文件读取并分割
|
||||||
config.addAllowedMethod("*");
|
String[] methodsArray = allowedMethods.split(",");
|
||||||
|
for (String method : methodsArray) {
|
||||||
// 允许的请求头
|
config.addAllowedMethod(method.trim());
|
||||||
config.addAllowedHeader("*");
|
}
|
||||||
|
|
||||||
// 暴露的响应头,这些头信息可以被前端JavaScript访问
|
// 允许的请求头,从配置文件读取
|
||||||
config.addExposedHeader("*");
|
config.addAllowedHeader(allowedHeaders);
|
||||||
|
|
||||||
// 设置预检请求的有效期(秒)
|
// 明确暴露的响应头,对于JWT认证很重要
|
||||||
config.setMaxAge(3600L);
|
config.addExposedHeader("Authorization");
|
||||||
|
config.addExposedHeader("Content-Type");
|
||||||
|
config.addExposedHeader("X-Requested-With");
|
||||||
|
config.addExposedHeader("Accept");
|
||||||
|
config.addExposedHeader("Access-Control-Allow-Origin");
|
||||||
|
config.addExposedHeader("Access-Control-Allow-Credentials");
|
||||||
|
|
||||||
|
// 设置预检请求的有效期(秒),从配置文件读取
|
||||||
|
config.setMaxAge(maxAge);
|
||||||
|
|
||||||
// 创建基于URL的CORS配置源
|
// 创建基于URL的CORS配置源
|
||||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||||
|
|
||||||
// 为所有路径应用CORS配置
|
// 为所有路径应用CORS配置
|
||||||
source.registerCorsConfiguration("/**", config);
|
source.registerCorsConfiguration("/**", config);
|
||||||
|
|
||||||
// 返回配置好的CORS过滤器
|
// 返回配置好的CORS过滤器
|
||||||
return new CorsFilter(source);
|
return new CorsFilter(source);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.qf.myafterprojecy.config;
|
||||||
|
|
||||||
|
import com.qf.myafterprojecy.utils.JwtUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT认证过滤器,用于验证token并授权用户
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtUtils jwtUtils;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserDetailsService userDetailsService;
|
||||||
|
|
||||||
|
@Value("${jwt.header:Authorization}")
|
||||||
|
private String tokenHeader;
|
||||||
|
|
||||||
|
@Value("${jwt.token-prefix:Bearer}")
|
||||||
|
private String tokenPrefix;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
try {
|
||||||
|
// 获取token
|
||||||
|
String token = getTokenFromRequest(request);
|
||||||
|
System.out.println(token);
|
||||||
|
if (token != null && validateToken(token)) {
|
||||||
|
// 从token中获取用户名
|
||||||
|
String username = jwtUtils.getUsernameFromToken(token);
|
||||||
|
System.out.println("username: " + username);
|
||||||
|
// 加载用户信息
|
||||||
|
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||||
|
|
||||||
|
// 创建认证对象
|
||||||
|
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||||
|
userDetails, null, userDetails.getAuthorities());
|
||||||
|
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
|
|
||||||
|
// 设置认证信息到上下文
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("无法设置用户认证: {}", e);
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从请求头中获取token
|
||||||
|
*/
|
||||||
|
private String getTokenFromRequest(HttpServletRequest request) {
|
||||||
|
String bearerToken = request.getHeader(tokenHeader);
|
||||||
|
if (bearerToken != null && bearerToken.startsWith(tokenPrefix + " ")) {
|
||||||
|
return bearerToken.substring(tokenPrefix.length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证token
|
||||||
|
*/
|
||||||
|
private boolean validateToken(String token) {
|
||||||
|
try {
|
||||||
|
String username = jwtUtils.getUsernameFromToken(token);
|
||||||
|
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||||
|
return jwtUtils.validateToken(token, userDetails);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("无效的token: {}", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ public class PasswordEncoderConfig {
|
|||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
// 强度设置为10,这是一个平衡安全性和性能的值
|
// 强度设置为10,这是一个平衡安全性和性能的值
|
||||||
|
// 数值越高,计算成本越大,安全性越好
|
||||||
return new BCryptPasswordEncoder(10);
|
return new BCryptPasswordEncoder(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.qf.myafterprojecy.config;
|
package com.qf.myafterprojecy.config;
|
||||||
|
|
||||||
import javax.ws.rs.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@@ -14,6 +14,8 @@ import org.springframework.security.config.http.SessionCreationPolicy;
|
|||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spring Security配置类
|
* Spring Security配置类
|
||||||
@@ -31,6 +33,9 @@ public class SecurityConfig {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PasswordEncoder passwordEncoder;
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置AuthenticationManager Bean
|
* 配置AuthenticationManager Bean
|
||||||
* 使用AuthenticationConfiguration来获取认证管理器,这是更现代的方式
|
* 使用AuthenticationConfiguration来获取认证管理器,这是更现代的方式
|
||||||
@@ -49,28 +54,81 @@ public class SecurityConfig {
|
|||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
|
// 启用CORS支持,确保与CorsConfig中配置的过滤器配合工作
|
||||||
|
.cors().and()
|
||||||
// 禁用CSRF保护(对于API服务通常不需要)
|
// 禁用CSRF保护(对于API服务通常不需要)
|
||||||
.csrf().disable()
|
.csrf().disable()
|
||||||
// 配置URL访问权限
|
// 配置URL访问权限
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
// 允许公开访问的路径
|
// 允许公开访问的路径
|
||||||
// 公开get请求
|
// 登录和认证相关端点应该全部公开
|
||||||
.antMatchers(HttpMethod.GET,"/api/auth/**").permitAll()
|
.antMatchers(HttpMethod.POST,"/api/auth/**").permitAll()
|
||||||
.antMatchers(HttpMethod.GET,"/api/help/**").permitAll()
|
// 文章浏览量增加接口公开
|
||||||
.antMatchers(HttpMethod.GET,"/api/category-attributes/**").permitAll()
|
.antMatchers(HttpMethod.POST,"/api/articles/view/**").permitAll()
|
||||||
.antMatchers(HttpMethod.GET,"/api/markdowns/**").permitAll()
|
// 所有GET请求公开
|
||||||
.antMatchers(HttpMethod.GET,"/api/articles/**").permitAll()
|
.antMatchers(HttpMethod.GET,"/api/**").permitAll()
|
||||||
.antMatchers(HttpMethod.GET,"/api/messages/**").permitAll()
|
// 公开评论新增接口
|
||||||
// 公开post请求
|
.antMatchers(HttpMethod.POST,"/api/messages").permitAll()
|
||||||
.antMatchers(HttpMethod.POST,"/api/messages/**").permitAll()
|
// 新增、删除、修改操作需要管理员权限
|
||||||
|
.antMatchers(HttpMethod.POST,"/api/**").hasRole("ADMIN")
|
||||||
|
.antMatchers(HttpMethod.PUT,"/api/**").hasRole("ADMIN")
|
||||||
|
.antMatchers(HttpMethod.DELETE,"/api/**").hasRole("ADMIN")
|
||||||
// 管理员才能访问的路径
|
// 管理员才能访问的路径
|
||||||
.antMatchers("/api/admin/**").hasRole("ADMIN")
|
.antMatchers("/api/admin/**").hasRole("ADMIN")
|
||||||
// 其他所有请求都需要认证
|
// 其他所有请求都需要认证
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.and()
|
.and()
|
||||||
// 配置会话管理,使用无状态会话
|
// 配置会话管理,使用无状态会话策略
|
||||||
|
// 这意味着每个请求都需要包含认证信息(如JWT)
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
|
.and()
|
||||||
|
// 确保OPTIONS请求能够通过,处理预检请求
|
||||||
|
.exceptionHandling()
|
||||||
|
.authenticationEntryPoint((request, response, authException) -> {
|
||||||
|
// 设置CORS头信息
|
||||||
|
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
response.setHeader("Access-Control-Allow-Credentials", "true");
|
||||||
|
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH");
|
||||||
|
response.setHeader("Access-Control-Allow-Headers", "*");
|
||||||
|
response.setHeader("Access-Control-Max-Age", "3600");
|
||||||
|
|
||||||
|
// 如果是预检请求,直接返回200
|
||||||
|
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_OK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 未认证处理
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
response.setContentType("application/json;charset=UTF-8");
|
||||||
|
response.getWriter().write("{\"message\": \"未授权访问,请先登录\"}");
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加JWT认证过滤器
|
||||||
|
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
|
||||||
|
// 确保Spring Security不会添加额外的CharacterEncodingFilter
|
||||||
|
// 因为我们在CharacterEncodingConfig中已经配置了自定义的过滤器
|
||||||
|
http.addFilterBefore((request, response, chain) -> {
|
||||||
|
// 确保响应使用UTF-8编码
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
response.setContentType("application/json;charset=UTF-8");
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}, JwtAuthenticationFilter.class);
|
||||||
|
|
||||||
|
// 配置访问拒绝处理器
|
||||||
|
http.exceptionHandling()
|
||||||
|
.accessDeniedHandler((request, response, accessDeniedException) -> {
|
||||||
|
// 设置CORS头信息
|
||||||
|
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
response.setHeader("Access-Control-Allow-Credentials", "true");
|
||||||
|
|
||||||
|
// 无权限处理
|
||||||
|
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||||
|
response.setContentType("application/json;charset=UTF-8");
|
||||||
|
response.getWriter().write("{\"message\": \"权限不足,无法访问\"}");
|
||||||
|
});
|
||||||
|
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package com.qf.myafterprojecy.controller;
|
package com.qf.myafterprojecy.controller;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Article;
|
import com.qf.myafterprojecy.pojo.Article;
|
||||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||||
import com.qf.myafterprojecy.service.imp.IArticleService;
|
import com.qf.myafterprojecy.pojo.dto.ArriclePageDto;
|
||||||
|
import com.qf.myafterprojecy.service.IArticleService;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
@@ -19,6 +22,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/articles")
|
@RequestMapping("/api/articles")
|
||||||
|
|
||||||
@Validated
|
@Validated
|
||||||
public class ArticleController {
|
public class ArticleController {
|
||||||
|
|
||||||
@@ -35,13 +39,37 @@ public class ArticleController {
|
|||||||
return articleService.getArticleById(id);
|
return articleService.getArticleById(id);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 获取已发布的文章列表
|
* 获取已发布或未发布的文章列表
|
||||||
* @return 返回包含已发布文章列表的ResponseMessage对象
|
* @return 返回包含已发布文章列表的ResponseMessage对象
|
||||||
*/
|
*/
|
||||||
@GetMapping("/published")
|
@GetMapping("/published")
|
||||||
public ResponseMessage<List<Article>> getPublishedArticles() {
|
public ResponseMessage<List<Article>> getPublishedArticles() {
|
||||||
return articleService.getPublishedArticles();
|
return articleService.getPublishedArticles();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 根据状态获取文章列表
|
||||||
|
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||||
|
* @return 返回包含文章列表的ResponseMessage对象
|
||||||
|
*/
|
||||||
|
@GetMapping("/status/{status}")
|
||||||
|
public ResponseMessage<List<Article>> getArticlesByStatus(@PathVariable Integer status) {
|
||||||
|
return articleService.getArticlesByStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据状态分页获取文章列表
|
||||||
|
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||||
|
* @param page 页码,从0开始(可选,默认为0)
|
||||||
|
* @param size 每页大小(可选,默认为10,最大为100)
|
||||||
|
* @return 返回包含分页文章列表的ResponseMessage对象
|
||||||
|
*/
|
||||||
|
// api/articles/status/page?status=1&page=1&size=2
|
||||||
|
// get 只能这样不能传递json
|
||||||
|
@GetMapping("/status/page")
|
||||||
|
public ResponseMessage<Page<Article>> getArticlesByStatusWithPagination(ArriclePageDto pageDto) {
|
||||||
|
return articleService.getArticlesByStatusWithPagination(pageDto);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有文章列表
|
* 获取所有文章列表
|
||||||
* @return 返回包含文章列表的ResponseMessage对象
|
* @return 返回包含文章列表的ResponseMessage对象
|
||||||
@@ -50,6 +78,15 @@ public class ArticleController {
|
|||||||
public ResponseMessage<List<Article>> getAllArticles() {
|
public ResponseMessage<List<Article>> getAllArticles() {
|
||||||
return articleService.getAllArticles();
|
return articleService.getAllArticles();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 获取文章数量
|
||||||
|
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||||
|
* @return 返回文章数量
|
||||||
|
*/
|
||||||
|
@GetMapping("/count/{status}")
|
||||||
|
public ResponseMessage<Integer> getArticleCount(@PathVariable Integer status) {
|
||||||
|
return articleService.getArticleCount(status);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 根据标题查询文章列表
|
* 根据标题查询文章列表
|
||||||
* @param title 文章标题
|
* @param title 文章标题
|
||||||
@@ -70,7 +107,6 @@ public class ArticleController {
|
|||||||
return articleService.getArticlesByAttribute(attributeId);
|
return articleService.getArticlesByAttribute(attributeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
/**
|
/**
|
||||||
* 根据属性ID获取最新文章(按创建时间降序)
|
* 根据属性ID获取最新文章(按创建时间降序)
|
||||||
* @param attributeId 属性ID
|
* @param attributeId 属性ID
|
||||||
@@ -88,7 +124,7 @@ public class ArticleController {
|
|||||||
* @return 返回包含新创建文章信息的ResponseMessage对象
|
* @return 返回包含新创建文章信息的ResponseMessage对象
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
@PreAuthorize("hasRole('AUTHOR')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Article> createArticle(@Valid @RequestBody ArticleDto articleDto) {
|
public ResponseMessage<Article> createArticle(@Valid @RequestBody ArticleDto articleDto) {
|
||||||
return articleService.saveArticle(articleDto);
|
return articleService.saveArticle(articleDto);
|
||||||
}
|
}
|
||||||
@@ -109,7 +145,7 @@ public class ArticleController {
|
|||||||
* @return 返回包含更新后文章信息的ResponseMessage对象
|
* @return 返回包含更新后文章信息的ResponseMessage对象
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
@PreAuthorize("hasRole('AUTHOR')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Article> updateArticle(
|
public ResponseMessage<Article> updateArticle(
|
||||||
@PathVariable Integer id,
|
@PathVariable Integer id,
|
||||||
@Valid @RequestBody ArticleDto articleDto) {
|
@Valid @RequestBody ArticleDto articleDto) {
|
||||||
@@ -123,7 +159,7 @@ public class ArticleController {
|
|||||||
* @return 返回包含被删除文章信息的ResponseMessage对象
|
* @return 返回包含被删除文章信息的ResponseMessage对象
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
@PreAuthorize("hasRole('AUTHOR') or hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Article> deleteArticle(@PathVariable Integer id) {
|
public ResponseMessage<Article> deleteArticle(@PathVariable Integer id) {
|
||||||
return articleService.deleteArticle(id);
|
return articleService.deleteArticle(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.qf.myafterprojecy.controller;
|
package com.qf.myafterprojecy.controller;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
|
import com.qf.myafterprojecy.utils.JwtUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -31,6 +32,9 @@ public class AuthController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private AuthenticationManager authenticationManager;
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtUtils jwtUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户登录请求体
|
* 用户登录请求体
|
||||||
*/
|
*/
|
||||||
@@ -67,8 +71,7 @@ public class AuthController {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 创建认证令牌
|
// 创建认证令牌
|
||||||
UsernamePasswordAuthenticationToken authenticationToken =
|
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
|
||||||
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
|
|
||||||
|
|
||||||
// 执行认证
|
// 执行认证
|
||||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||||
@@ -78,12 +81,14 @@ public class AuthController {
|
|||||||
|
|
||||||
// 获取认证后的用户信息
|
// 获取认证后的用户信息
|
||||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||||
|
// 生成JWT token
|
||||||
|
String token = jwtUtils.generateToken(userDetails);
|
||||||
// 构建返回数据
|
// 构建返回数据
|
||||||
Map<String, Object> data = new HashMap<>();
|
Map<String, Object> data = new HashMap<>();
|
||||||
data.put("username", userDetails.getUsername());
|
data.put("username", userDetails.getUsername());
|
||||||
data.put("authorities", userDetails.getAuthorities());
|
data.put("authorities", userDetails.getAuthorities());
|
||||||
data.put("message", "登录成功");
|
data.put("token", token);
|
||||||
|
data.put("tokenPrefix", jwtUtils.getTokenPrefix());
|
||||||
|
|
||||||
return ResponseMessage.success(data, "登录成功");
|
return ResponseMessage.success(data, "登录成功");
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package com.qf.myafterprojecy.controller;
|
package com.qf.myafterprojecy.controller;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Category_attribute;
|
import com.qf.myafterprojecy.pojo.Categoryattribute;
|
||||||
import com.qf.myafterprojecy.pojo.dto.CategoryAttributeDto;
|
import com.qf.myafterprojecy.pojo.dto.CategoryAttributeDto;
|
||||||
import com.qf.myafterprojecy.service.imp.ICategoryAttributeService;
|
import com.qf.myafterprojecy.service.ICategoryAttributeService;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -30,11 +31,15 @@ public class CategoryAttributeController {
|
|||||||
* @return 属性信息
|
* @return 属性信息
|
||||||
*/
|
*/
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public ResponseMessage<Category_attribute> getAttributeById(@PathVariable Integer id) {
|
public ResponseMessage<Categoryattribute> getAttributeById(@PathVariable Integer id) {
|
||||||
log.info("接收根据ID获取分类属性的请求: ID={}", id);
|
log.info("接收根据ID获取分类属性的请求: ID={}", id);
|
||||||
return categoryAttributeService.getCategoryAttributeById(id);
|
return categoryAttributeService.getCategoryAttributeById(id);
|
||||||
}
|
}
|
||||||
|
@GetMapping
|
||||||
|
public ResponseMessage<List<Categoryattribute>> getAttributeCount() {
|
||||||
|
log.info("接收获取分类属性数量的请求");
|
||||||
|
return categoryAttributeService.getAllCategoryAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据分类ID获取属性列表
|
* 根据分类ID获取属性列表
|
||||||
@@ -42,7 +47,7 @@ public class CategoryAttributeController {
|
|||||||
* @return 属性列表
|
* @return 属性列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/category/{categoryId}")
|
@GetMapping("/category/{categoryId}")
|
||||||
public ResponseMessage<List<Category_attribute>> getAttributesByCategory(@PathVariable Integer categoryId) {
|
public ResponseMessage<List<Categoryattribute>> getAttributesByCategory(@PathVariable Integer categoryId) {
|
||||||
log.info("接收根据分类ID获取属性列表的请求: 分类ID={}", categoryId);
|
log.info("接收根据分类ID获取属性列表的请求: 分类ID={}", categoryId);
|
||||||
return categoryAttributeService.getAttributesByCategoryId(categoryId);
|
return categoryAttributeService.getAttributesByCategoryId(categoryId);
|
||||||
}
|
}
|
||||||
@@ -53,7 +58,8 @@ public class CategoryAttributeController {
|
|||||||
* @return 创建结果
|
* @return 创建结果
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseMessage<Category_attribute> createAttribute(@Valid @RequestBody CategoryAttributeDto dto) {
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseMessage<Categoryattribute> createAttribute(@Valid @RequestBody CategoryAttributeDto dto) {
|
||||||
log.info("接收创建分类属性的请求: 分类ID={}, 属性名称={}",
|
log.info("接收创建分类属性的请求: 分类ID={}, 属性名称={}",
|
||||||
dto.getCategoryid(), dto.getAttributename());
|
dto.getCategoryid(), dto.getAttributename());
|
||||||
return categoryAttributeService.saveCategoryAttribute(dto);
|
return categoryAttributeService.saveCategoryAttribute(dto);
|
||||||
@@ -66,7 +72,8 @@ public class CategoryAttributeController {
|
|||||||
* @return 更新结果
|
* @return 更新结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
public ResponseMessage<Category_attribute> updateAttribute(
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseMessage<Categoryattribute> updateAttribute(
|
||||||
@PathVariable Integer id,
|
@PathVariable Integer id,
|
||||||
@Valid @RequestBody CategoryAttributeDto dto) {
|
@Valid @RequestBody CategoryAttributeDto dto) {
|
||||||
log.info("接收更新分类属性的请求: ID={}, 分类ID={}, 属性名称={}",
|
log.info("接收更新分类属性的请求: ID={}, 分类ID={}, 属性名称={}",
|
||||||
@@ -80,6 +87,7 @@ public class CategoryAttributeController {
|
|||||||
* @return 删除结果
|
* @return 删除结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Boolean> deleteAttribute(@PathVariable Integer id) {
|
public ResponseMessage<Boolean> deleteAttribute(@PathVariable Integer id) {
|
||||||
log.info("接收删除分类属性的请求: ID={}", id);
|
log.info("接收删除分类属性的请求: ID={}", id);
|
||||||
return categoryAttributeService.deleteCategoryAttribute(id);
|
return categoryAttributeService.deleteCategoryAttribute(id);
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package com.qf.myafterprojecy.controller;
|
package com.qf.myafterprojecy.controller;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Category;
|
import com.qf.myafterprojecy.pojo.Category;
|
||||||
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
||||||
import com.qf.myafterprojecy.service.imp.ICategoryService;
|
import com.qf.myafterprojecy.service.ICategoryService;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -55,6 +56,7 @@ public class CategoryController {
|
|||||||
* @return 返回创建结果
|
* @return 返回创建结果
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Category> createCategory(@Valid @RequestBody CategoryDto categoryDto) {
|
public ResponseMessage<Category> createCategory(@Valid @RequestBody CategoryDto categoryDto) {
|
||||||
log.info("接收创建分类的请求: {}", categoryDto.getTypename());
|
log.info("接收创建分类的请求: {}", categoryDto.getTypename());
|
||||||
return categoryService.saveCategory(categoryDto);
|
return categoryService.saveCategory(categoryDto);
|
||||||
@@ -67,6 +69,7 @@ public class CategoryController {
|
|||||||
* @return 返回更新结果
|
* @return 返回更新结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Category> updateCategory(
|
public ResponseMessage<Category> updateCategory(
|
||||||
@PathVariable Integer id,
|
@PathVariable Integer id,
|
||||||
@Valid @RequestBody CategoryDto categoryDto) {
|
@Valid @RequestBody CategoryDto categoryDto) {
|
||||||
@@ -80,6 +83,7 @@ public class CategoryController {
|
|||||||
* @return 返回删除结果
|
* @return 返回删除结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Boolean> deleteCategory(@PathVariable Integer id) {
|
public ResponseMessage<Boolean> deleteCategory(@PathVariable Integer id) {
|
||||||
log.info("接收删除分类的请求: {}", id);
|
log.info("接收删除分类的请求: {}", id);
|
||||||
return categoryService.deleteCategory(id);
|
return categoryService.deleteCategory(id);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.GetMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@@ -53,8 +53,8 @@ public class HelpController {
|
|||||||
// 读取文件内容
|
// 读取文件内容
|
||||||
String markdownContent = new String(FileCopyUtils.copyToByteArray(new FileInputStream(readmeFile)), StandardCharsets.UTF_8);
|
String markdownContent = new String(FileCopyUtils.copyToByteArray(new FileInputStream(readmeFile)), StandardCharsets.UTF_8);
|
||||||
// 将Markdown转换为HTML
|
// 将Markdown转换为HTML
|
||||||
// String htmlContent = convertMarkdownToHtml(markdownContent);
|
String htmlContent = convertMarkdownToHtml(markdownContent);
|
||||||
return ResponseMessage.success(markdownContent, "获取API文档成功");
|
return ResponseMessage.success(htmlContent, "获取API文档成功");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return ResponseMessage.error("读取README_API.md文件失败: " + e.getMessage());
|
return ResponseMessage.error("读取README_API.md文件失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
package com.qf.myafterprojecy.controller;
|
package com.qf.myafterprojecy.controller;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Message;
|
import com.qf.myafterprojecy.pojo.Message;
|
||||||
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
||||||
import com.qf.myafterprojecy.service.imp.IMessageService;
|
import com.qf.myafterprojecy.pojo.dto.MessagePageDto;
|
||||||
|
import com.qf.myafterprojecy.service.IMessageService;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -29,7 +31,25 @@ public class MessageController {
|
|||||||
logger.info("接收获取所有消息的请求");
|
logger.info("接收获取所有消息的请求");
|
||||||
return messageService.getAllMessages();
|
return messageService.getAllMessages();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 分页查询消息
|
||||||
|
*/
|
||||||
|
@GetMapping("/page")
|
||||||
|
public ResponseMessage<List<Message>> getMessagesByPage(MessagePageDto messagePageDto) {
|
||||||
|
logger.info("接收分页查询消息的请求: {}", messagePageDto);
|
||||||
|
return messageService.getMessagesByPage(messagePageDto);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取消息数量
|
||||||
|
* @param articleId 文章ID (可选)
|
||||||
|
* @return 消息数量
|
||||||
|
* 文章ID为null时返回所有消息数量
|
||||||
|
*/
|
||||||
|
@GetMapping("/count")
|
||||||
|
public ResponseMessage<Integer> getMessageCount( Integer articleId) {
|
||||||
|
logger.info("接收获取消息数量的请求: {}", articleId);
|
||||||
|
return messageService.getMessageCountByArticleId(articleId);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 根据ID获取消息
|
* 根据ID获取消息
|
||||||
*/
|
*/
|
||||||
@@ -75,18 +95,11 @@ public class MessageController {
|
|||||||
return messageService.searchMessagesByNickname(nickname);
|
return messageService.searchMessagesByNickname(nickname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取指定文章的评论数量
|
|
||||||
*/
|
|
||||||
@GetMapping("/count/article/{articleId}")
|
|
||||||
public ResponseMessage<Long> getMessageCountByArticleId(@PathVariable Integer articleId) {
|
|
||||||
logger.info("接收获取文章评论数量的请求: {}", articleId);
|
|
||||||
return messageService.getMessageCountByArticleId(articleId);
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 创建新消息
|
* 创建新消息
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@PostMapping
|
||||||
|
// 允许匿名用户发表评论
|
||||||
public ResponseMessage<Message> createMessage(@RequestBody MessageDto message) {
|
public ResponseMessage<Message> createMessage(@RequestBody MessageDto message) {
|
||||||
logger.info("接收创建消息的请求: {}", message != null ? message.getNickname() : "null");
|
logger.info("接收创建消息的请求: {}", message != null ? message.getNickname() : "null");
|
||||||
return messageService.saveMessage(message);
|
return messageService.saveMessage(message);
|
||||||
@@ -101,16 +114,16 @@ public class MessageController {
|
|||||||
* 根据ID删除消息
|
* 根据ID删除消息
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or #id == authentication.principal.id")
|
||||||
public ResponseMessage<Message> deleteMessage(@PathVariable Integer id) {
|
public ResponseMessage<Message> deleteMessage(@PathVariable Integer id) {
|
||||||
logger.info("接收删除消息的请求: {}", id);
|
logger.info("接收删除消息的请求: {}", id);
|
||||||
return messageService.deleteMessage(id);
|
return messageService.deleteMessage(id);
|
||||||
}
|
}
|
||||||
//删除所有评论
|
//删除所有评论 - 仅管理员可操作
|
||||||
@DeleteMapping("/all")
|
@DeleteMapping("/all")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Void> deleteAllMessages() {
|
public ResponseMessage<Void> deleteAllMessages() {
|
||||||
logger.info("接收删除所有消息的请求");
|
logger.info("接收删除所有消息的请求");
|
||||||
return messageService.deleteAllMessages();
|
return messageService.deleteAllMessages();
|
||||||
}
|
}
|
||||||
// 新增API端点
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package com.qf.myafterprojecy.controller;
|
||||||
|
|
||||||
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
|
import com.qf.myafterprojecy.pojo.Nonsense;
|
||||||
|
import com.qf.myafterprojecy.pojo.dto.NonsenseDto;
|
||||||
|
import com.qf.myafterprojecy.service.INonsenseService;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.Max;
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/nonsense")
|
||||||
|
@Validated
|
||||||
|
public class NonsenseController {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(NonsenseController.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private INonsenseService nonsenseService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有疯言疯语内容
|
||||||
|
* @return 疯言疯语内容列表
|
||||||
|
*/
|
||||||
|
@GetMapping
|
||||||
|
public ResponseMessage<List<Nonsense>> getAllNonsense() {
|
||||||
|
logger.info("请求获取所有疯言疯语内容");
|
||||||
|
return nonsenseService.getAllNonsense();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据状态获取疯言疯语内容
|
||||||
|
* @param status 状态:0未发表 1已发表 2已删除
|
||||||
|
* @return 疯言疯语内容列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/status/{status}")
|
||||||
|
public ResponseMessage<List<Nonsense>> getNonsenseByStatus(
|
||||||
|
@PathVariable("status") Integer status) {
|
||||||
|
logger.info("请求获取状态为{}的疯言疯语内容", status);
|
||||||
|
return nonsenseService.getNonsenseByStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID获取疯言疯语内容
|
||||||
|
* @param id 疯言疯语内容ID
|
||||||
|
* @return 疯言疯语内容
|
||||||
|
*/
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
public ResponseMessage<Nonsense> getNonsenseById(@PathVariable("id") Integer id) {
|
||||||
|
logger.info("请求获取ID为{}的疯言疯语内容", id);
|
||||||
|
return nonsenseService.getNonsenseById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建疯言疯语内容
|
||||||
|
* 需要管理员权限
|
||||||
|
* @param nonsenseDto 疯言疯语内容数据
|
||||||
|
* @return 创建结果
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
public ResponseMessage<Nonsense> saveNonsense(@Valid @RequestBody NonsenseDto nonsenseDto) {
|
||||||
|
logger.info("请求保存疯言疯语内容");
|
||||||
|
return nonsenseService.saveNonsense(nonsenseDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新疯言疯语内容
|
||||||
|
* 需要管理员权限
|
||||||
|
* @param id 疯言疯语内容ID
|
||||||
|
* @param nonsenseDto 疯言疯语内容数据
|
||||||
|
* @return 更新结果
|
||||||
|
*/
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseMessage<Nonsense> updateNonsense(@PathVariable("id") Integer id, @Valid @RequestBody NonsenseDto nonsenseDto) {
|
||||||
|
logger.info("请求更新ID为{}的疯言疯语内容", id);
|
||||||
|
return nonsenseService.updateNonsense(id, nonsenseDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除疯言疯语内容
|
||||||
|
* 需要管理员权限
|
||||||
|
* @param id 疯言疯语内容ID
|
||||||
|
* @return 删除结果
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseMessage<Boolean> deleteNonsense(@PathVariable("id") Integer id) {
|
||||||
|
logger.info("请求删除ID为{}的疯言疯语内容", id);
|
||||||
|
return nonsenseService.deleteNonsense(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新疯言疯语内容状态
|
||||||
|
* 需要管理员权限
|
||||||
|
* @param id 疯言疯语内容ID
|
||||||
|
* @param status 新状态:0未发表 1已发表 2已删除
|
||||||
|
* @return 更新结果
|
||||||
|
*/
|
||||||
|
@PutMapping("/{id}/status/{status}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
public ResponseMessage<Nonsense> updateNonsenseStatus(
|
||||||
|
@PathVariable("id") Integer id,
|
||||||
|
@PathVariable("status") @Min(0) @Max(2) Integer status) {
|
||||||
|
logger.info("请求更新ID为{}的疯言疯语内容状态为{}", id, status);
|
||||||
|
return nonsenseService.updateNonsenseStatus(id, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
package com.qf.myafterprojecy.controller;
|
package com.qf.myafterprojecy.controller;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Users;
|
import com.qf.myafterprojecy.pojo.Users;
|
||||||
import com.qf.myafterprojecy.pojo.dto.UserDto;
|
import com.qf.myafterprojecy.pojo.dto.UserDto;
|
||||||
import com.qf.myafterprojecy.service.imp.IUserService;
|
import com.qf.myafterprojecy.service.IUserService;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
@@ -15,6 +17,7 @@ import java.util.List;
|
|||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/users")
|
@RequestMapping("/api/users")
|
||||||
|
@Validated
|
||||||
public class UserController {
|
public class UserController {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
|
private static final Logger logger = LoggerFactory.getLogger(UserController.class);
|
||||||
@@ -38,6 +41,7 @@ public class UserController {
|
|||||||
* @return 用户列表
|
* @return 用户列表
|
||||||
*/
|
*/
|
||||||
@GetMapping
|
@GetMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<List<Users>> getAllUsers() {
|
public ResponseMessage<List<Users>> getAllUsers() {
|
||||||
logger.info("获取所有用户列表");
|
logger.info("获取所有用户列表");
|
||||||
return userService.getAllUsers();
|
return userService.getAllUsers();
|
||||||
@@ -45,10 +49,10 @@ public class UserController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户名获取用户信息
|
* 根据用户名获取用户信息
|
||||||
* @param username 用户名
|
|
||||||
* @return 用户信息
|
* @return 用户信息
|
||||||
*/
|
*/
|
||||||
@GetMapping("/username/{username}")
|
@GetMapping("/username/{username}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or #username == authentication.name")
|
||||||
public ResponseMessage<Users> getUserByUsername(@PathVariable String username) {
|
public ResponseMessage<Users> getUserByUsername(@PathVariable String username) {
|
||||||
logger.info("根据用户名获取用户信息,用户名: {}", username);
|
logger.info("根据用户名获取用户信息,用户名: {}", username);
|
||||||
return userService.getUserByUsername(username);
|
return userService.getUserByUsername(username);
|
||||||
@@ -72,6 +76,7 @@ public class UserController {
|
|||||||
* @return 更新结果
|
* @return 更新结果
|
||||||
*/
|
*/
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN') or #id == authentication.principal.id")
|
||||||
public ResponseMessage<Users> updateUser(@PathVariable Long id, @Valid @RequestBody UserDto userDto) {
|
public ResponseMessage<Users> updateUser(@PathVariable Long id, @Valid @RequestBody UserDto userDto) {
|
||||||
logger.info("更新用户信息,用户ID: {}", id);
|
logger.info("更新用户信息,用户ID: {}", id);
|
||||||
return userService.updateUser(id, userDto);
|
return userService.updateUser(id, userDto);
|
||||||
@@ -83,6 +88,7 @@ public class UserController {
|
|||||||
* @return 删除结果
|
* @return 删除结果
|
||||||
*/
|
*/
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<Boolean> deleteUser(@PathVariable Long id) {
|
public ResponseMessage<Boolean> deleteUser(@PathVariable Long id) {
|
||||||
logger.info("删除用户,用户ID: {}", id);
|
logger.info("删除用户,用户ID: {}", id);
|
||||||
return userService.deleteUser(id);
|
return userService.deleteUser(id);
|
||||||
@@ -94,6 +100,7 @@ public class UserController {
|
|||||||
* @return 用户列表
|
* @return 用户列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/role/{role}")
|
@GetMapping("/role/{role}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
public ResponseMessage<List<Users>> getUsersByRole(@PathVariable int role) {
|
public ResponseMessage<List<Users>> getUsersByRole(@PathVariable int role) {
|
||||||
logger.info("根据角色查询用户列表,角色: {}", role);
|
logger.info("根据角色查询用户列表,角色: {}", role);
|
||||||
return userService.getUsersByRole(role);
|
return userService.getUsersByRole(role);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.qf.myafterprojecy;
|
package com.qf.myafterprojecy.exceptopn;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
@@ -7,8 +7,6 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
|
||||||
|
|
||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
public class GlobalExceptionHandler {
|
public class GlobalExceptionHandler {
|
||||||
Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.qf.myafterprojecy.config;
|
package com.qf.myafterprojecy.exceptopn;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
// package com.qf.myafterprojecy.init;
|
|
||||||
|
|
||||||
// import com.qf.myafterprojecy.pojo.Category;
|
|
||||||
// import com.qf.myafterprojecy.repository.CategoryRepository;
|
|
||||||
// import org.slf4j.Logger;
|
|
||||||
// import org.slf4j.LoggerFactory;
|
|
||||||
// import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
// import org.springframework.boot.ApplicationArguments;
|
|
||||||
// import org.springframework.boot.ApplicationRunner;
|
|
||||||
// import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
// import java.time.LocalDateTime;
|
|
||||||
// import java.util.ArrayList;
|
|
||||||
// import java.util.List;
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 分类数据初始化类,用于在应用启动时初始化分类数据
|
|
||||||
// */
|
|
||||||
// @Component
|
|
||||||
// public class CategoryDataInit implements ApplicationRunner {
|
|
||||||
|
|
||||||
// private static final Logger logger = LoggerFactory.getLogger(CategoryDataInit.class);
|
|
||||||
|
|
||||||
// @Autowired
|
|
||||||
// private CategoryRepository categoryRepository;
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void run(ApplicationArguments args) throws Exception {
|
|
||||||
// logger.info("===== 分类数据初始化开始 =====");
|
|
||||||
|
|
||||||
// // 检查数据库中是否已有分类数据
|
|
||||||
// long count = categoryRepository.count();
|
|
||||||
// logger.info("当前数据库中分类数量: {}", count);
|
|
||||||
|
|
||||||
// // 如果没有分类数据,添加一些测试数据
|
|
||||||
// if (count == 0) {
|
|
||||||
// logger.info("数据库中没有分类数据,开始添加初始化数据...");
|
|
||||||
// addInitialCategories();
|
|
||||||
// } else {
|
|
||||||
// logger.info("数据库中已存在分类数据,无需初始化");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// logger.info("===== 分类数据初始化结束 =====");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 添加初始分类数据
|
|
||||||
// */
|
|
||||||
// private void addInitialCategories() {
|
|
||||||
// List<Category> categories = new ArrayList<>();
|
|
||||||
|
|
||||||
// // 创建几个常见的文章分类
|
|
||||||
// Category category1 = new Category();
|
|
||||||
// category1.setTypename("技术分享");
|
|
||||||
// category1.setDescription("技术文章、教程、经验分享等");
|
|
||||||
// category1.setCreatedAt(LocalDateTime.now());
|
|
||||||
// category1.setUpdatedAt(LocalDateTime.now());
|
|
||||||
// categories.add(category1);
|
|
||||||
|
|
||||||
// Category category2 = new Category();
|
|
||||||
// category2.setTypename("生活随笔");
|
|
||||||
// category2.setDescription("日常生活、心情记录、随笔等");
|
|
||||||
// category2.setCreatedAt(LocalDateTime.now());
|
|
||||||
// category2.setUpdatedAt(LocalDateTime.now());
|
|
||||||
// categories.add(category2);
|
|
||||||
|
|
||||||
// Category category3 = new Category();
|
|
||||||
// category3.setTypename("学习笔记");
|
|
||||||
// category3.setDescription("学习过程中的笔记、总结等");
|
|
||||||
// category3.setCreatedAt(LocalDateTime.now());
|
|
||||||
// category3.setUpdatedAt(LocalDateTime.now());
|
|
||||||
// categories.add(category3);
|
|
||||||
|
|
||||||
// Category category4 = new Category();
|
|
||||||
// category4.setTypename("行业动态");
|
|
||||||
// category4.setDescription("行业新闻、趋势分析等");
|
|
||||||
// category4.setCreatedAt(LocalDateTime.now());
|
|
||||||
// category4.setUpdatedAt(LocalDateTime.now());
|
|
||||||
// categories.add(category4);
|
|
||||||
|
|
||||||
// // 保存分类数据到数据库
|
|
||||||
// categoryRepository.saveAll(categories);
|
|
||||||
// logger.info("成功添加 {} 条分类数据", categories.size());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
// package com.qf.myafterprojecy.init;
|
|
||||||
|
|
||||||
// import com.qf.myafterprojecy.pojo.Message;
|
|
||||||
// import com.qf.myafterprojecy.repository.MessageRepository;
|
|
||||||
// import org.slf4j.Logger;
|
|
||||||
// import org.slf4j.LoggerFactory;
|
|
||||||
// import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
// import org.springframework.boot.ApplicationArguments;
|
|
||||||
// import org.springframework.boot.ApplicationRunner;
|
|
||||||
// import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
// import java.util.Date;
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 消息数据初始化类,用于在应用启动时为Message表添加默认的测试数据
|
|
||||||
// */
|
|
||||||
// @Component
|
|
||||||
// public class MessageDataInit implements ApplicationRunner {
|
|
||||||
|
|
||||||
// private static final Logger logger = LoggerFactory.getLogger(MessageDataInit.class);
|
|
||||||
|
|
||||||
// @Autowired
|
|
||||||
// private MessageRepository messageRepository;
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void run(ApplicationArguments args) throws Exception {
|
|
||||||
// logger.info("===== 消息数据初始化开始 =====");
|
|
||||||
|
|
||||||
// // 检查数据库中是否已有消息数据
|
|
||||||
// long count = messageRepository.count();
|
|
||||||
// logger.info("当前数据库中消息数量: {}", count);
|
|
||||||
|
|
||||||
// // 如果没有消息数据,添加一些测试数据
|
|
||||||
// if (count == 0) {
|
|
||||||
// logger.info("数据库中没有消息数据,开始添加初始化数据...");
|
|
||||||
// addInitialMessages();
|
|
||||||
// } else {
|
|
||||||
// logger.info("数据库中已存在消息数据,无需初始化");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// logger.info("===== 消息数据初始化结束 =====");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private void addInitialMessages() {
|
|
||||||
// // 添加第一篇文章的评论
|
|
||||||
// Message message1 = new Message();
|
|
||||||
// message1.setNickname("系统用户");
|
|
||||||
// message1.setEmail("system@example.com");
|
|
||||||
// message1.setContent("这是系统自动添加的第一条评论,欢迎使用本系统!");
|
|
||||||
// message1.setCreatedAt(new Date());
|
|
||||||
// message1.setArticleid(1);
|
|
||||||
// message1.setParentid(null); // 根评论
|
|
||||||
// messageRepository.save(message1);
|
|
||||||
|
|
||||||
// // 添加回复
|
|
||||||
// Message reply1 = new Message();
|
|
||||||
// reply1.setNickname("管理员");
|
|
||||||
// reply1.setEmail("admin@example.com");
|
|
||||||
// reply1.setContent("感谢您的支持,如有任何问题请随时联系我们!");
|
|
||||||
// reply1.setCreatedAt(new Date());
|
|
||||||
// reply1.setArticleid(1);
|
|
||||||
// reply1.setParentid(message1.getMessageid()); // 回复第一条评论
|
|
||||||
// messageRepository.save(reply1);
|
|
||||||
|
|
||||||
// // 添加第二篇文章的评论
|
|
||||||
// Message message2 = new Message();
|
|
||||||
// message2.setNickname("访客");
|
|
||||||
// message2.setEmail("visitor@example.com");
|
|
||||||
// message2.setContent("这篇文章写得非常好,学到了很多知识。");
|
|
||||||
// message2.setCreatedAt(new Date());
|
|
||||||
// message2.setArticleid(2);
|
|
||||||
// message2.setParentid(null);
|
|
||||||
// messageRepository.save(message2);
|
|
||||||
|
|
||||||
// // 再添加一些测试数据
|
|
||||||
// Message message3 = new Message();
|
|
||||||
// message3.setNickname("测试用户1");
|
|
||||||
// message3.setEmail("test1@example.com");
|
|
||||||
// message3.setContent("这是测试内容1");
|
|
||||||
// message3.setCreatedAt(new Date());
|
|
||||||
// message3.setArticleid(1);
|
|
||||||
// message3.setParentid(null);
|
|
||||||
// messageRepository.save(message3);
|
|
||||||
|
|
||||||
// Message reply2 = new Message();
|
|
||||||
// reply2.setNickname("测试用户2");
|
|
||||||
// reply2.setEmail("test2@example.com");
|
|
||||||
// reply2.setContent("回复测试内容1");
|
|
||||||
// reply2.setCreatedAt(new Date());
|
|
||||||
// reply2.setArticleid(1);
|
|
||||||
// reply2.setParentid(message3.getMessageid());
|
|
||||||
// messageRepository.save(reply2);
|
|
||||||
|
|
||||||
// logger.info("成功添加了{}条初始化消息数据", messageRepository.count());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
65
src/main/java/com/qf/myafterprojecy/init/UserDataInit.java
Normal file
65
src/main/java/com/qf/myafterprojecy/init/UserDataInit.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package com.qf.myafterprojecy.init;
|
||||||
|
|
||||||
|
import com.qf.myafterprojecy.pojo.Users;
|
||||||
|
import com.qf.myafterprojecy.repository.UsersRepository;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户数据初始化类
|
||||||
|
* 在应用启动时检查并创建管理员账号
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class UserDataInit implements ApplicationRunner {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(UserDataInit.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UsersRepository usersRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
// 管理员账号信息
|
||||||
|
private static final String ADMIN_USERNAME = "qf1121";
|
||||||
|
private static final String ADMIN_PASSWORD = "qf1121";
|
||||||
|
private static final String ADMIN_EMAIL = "admin@qf1121.com";
|
||||||
|
private static final String ADMIN_PHONE = "13800138000";
|
||||||
|
private static final Integer ADMIN_ROLE = 1; // 1表示管理员角色
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) {
|
||||||
|
logger.info("开始检查管理员账号...");
|
||||||
|
|
||||||
|
// 检查管理员账号是否已存在
|
||||||
|
Optional<Users> adminUser = usersRepository.findByUsername(ADMIN_USERNAME);
|
||||||
|
|
||||||
|
if (adminUser.isPresent()) {
|
||||||
|
logger.info("管理员账号 {} 已存在,无需创建", ADMIN_USERNAME);
|
||||||
|
} else {
|
||||||
|
// 创建管理员账号
|
||||||
|
Users newAdmin = new Users();
|
||||||
|
newAdmin.setUsername(ADMIN_USERNAME);
|
||||||
|
// 加密密码
|
||||||
|
newAdmin.setPassword(passwordEncoder.encode(ADMIN_PASSWORD));
|
||||||
|
newAdmin.setEmail(ADMIN_EMAIL);
|
||||||
|
newAdmin.setPhone(ADMIN_PHONE);
|
||||||
|
newAdmin.setRole(ADMIN_ROLE);
|
||||||
|
newAdmin.setCreateTime(LocalDateTime.now());
|
||||||
|
try {
|
||||||
|
usersRepository.save(newAdmin);
|
||||||
|
logger.info("管理员账号 {} 创建成功", ADMIN_USERNAME);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("创建管理员账号失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,6 @@ public class Article {
|
|||||||
@Column(name = "title")
|
@Column(name = "title")
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
@NotBlank(message = "内容不能为空")
|
|
||||||
@Column(name = "content", columnDefinition = "TEXT")
|
@Column(name = "content", columnDefinition = "TEXT")
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
@@ -44,7 +43,6 @@ public class Article {
|
|||||||
private Integer status; // 0-草稿,1-已发布,2-已删除
|
private Integer status; // 0-草稿,1-已发布,2-已删除
|
||||||
|
|
||||||
@Column(name = "markdownscontent")
|
@Column(name = "markdownscontent")
|
||||||
@NotBlank(message = "Markdown内容不能为空")
|
|
||||||
private String markdownscontent;
|
private String markdownscontent;
|
||||||
|
|
||||||
// Getters and Setters
|
// Getters and Setters
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import java.time.LocalDateTime;
|
|||||||
public class Category {
|
public class Category {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
@Column(name = "typeid")
|
@Column(name = "categoryid")
|
||||||
private Integer typeid;
|
private Integer categoryid;
|
||||||
|
|
||||||
@NotBlank(message = "分类名称不能为空")
|
@NotBlank(message = "分类名称不能为空")
|
||||||
@Column(name = "typename")
|
@Column(name = "typename")
|
||||||
@@ -26,12 +26,12 @@ public class Category {
|
|||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
// Getters and Setters
|
// Getters and Setters
|
||||||
public Integer getTypeid() {
|
public Integer getCategoryid() {
|
||||||
return typeid;
|
return categoryid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTypeid(Integer typeid) {
|
public void setCategoryid(Integer categoryid) {
|
||||||
this.typeid = typeid;
|
this.categoryid = categoryid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTypename() {
|
public String getTypename() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import javax.persistence.*;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "category_attribute")
|
@Table(name = "category_attribute")
|
||||||
public class Category_attribute {
|
public class Categoryattribute {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
@Column(name = "attributeid")
|
@Column(name = "attributeid")
|
||||||
@@ -8,7 +8,6 @@ import java.util.Date;
|
|||||||
public class Message {
|
public class Message {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|
||||||
@Column(name = "messageid")
|
@Column(name = "messageid")
|
||||||
private Integer messageid;
|
private Integer messageid;
|
||||||
|
|
||||||
@@ -21,6 +20,9 @@ public class Message {
|
|||||||
@Column(name = "content", columnDefinition = "text")
|
@Column(name = "content", columnDefinition = "text")
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
|
@Column(name = "messageimg")
|
||||||
|
private String messageimg;
|
||||||
|
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
@Column(name = "created_at")
|
@Column(name = "created_at")
|
||||||
private Date createdAt;
|
private Date createdAt;
|
||||||
@@ -37,6 +39,7 @@ public class Message {
|
|||||||
@Column(name = "likes")
|
@Column(name = "likes")
|
||||||
private Integer likes; // 点赞数
|
private Integer likes; // 点赞数
|
||||||
|
|
||||||
|
|
||||||
public Integer getLikes() {
|
public Integer getLikes() {
|
||||||
return likes;
|
return likes;
|
||||||
}
|
}
|
||||||
@@ -108,4 +111,12 @@ public class Message {
|
|||||||
public void setArticleid(Integer articleid) {
|
public void setArticleid(Integer articleid) {
|
||||||
this.articleid = articleid;
|
this.articleid = articleid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMessageimg() {
|
||||||
|
return messageimg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessageimg(String messageimg) {
|
||||||
|
this.messageimg = messageimg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
46
src/main/java/com/qf/myafterprojecy/pojo/Nonsense.java
Normal file
46
src/main/java/com/qf/myafterprojecy/pojo/Nonsense.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package com.qf.myafterprojecy.pojo;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "nonsense")
|
||||||
|
public class Nonsense {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id", nullable = false, unique = true)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@Column(name = "content",nullable = false)
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
@Column(name = "status",nullable = false)
|
||||||
|
private Integer status;//状态 0:未发表 1:已发表 2:已删除
|
||||||
|
|
||||||
|
@Column(name = "time")
|
||||||
|
private Date time;
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
public Date getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
public void setTime(Date time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
public void setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.qf.myafterprojecy.pojo.dto;
|
||||||
|
public class ArriclePageDto {
|
||||||
|
|
||||||
|
private Integer status;
|
||||||
|
private String title;
|
||||||
|
private Integer attributeid;
|
||||||
|
private Integer categoryid;
|
||||||
|
private Integer pagenum;
|
||||||
|
private Integer pagesize;
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
public void setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
public Integer getPagenum() {
|
||||||
|
return pagenum;
|
||||||
|
}
|
||||||
|
public void setPagenum(Integer pagenum) {
|
||||||
|
this.pagenum = pagenum;
|
||||||
|
}
|
||||||
|
public Integer getPagesize() {
|
||||||
|
return pagesize;
|
||||||
|
}
|
||||||
|
public void setPagesize(Integer pagesize) {
|
||||||
|
this.pagesize = pagesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
public Integer getAttributeid() {
|
||||||
|
return attributeid;
|
||||||
|
}
|
||||||
|
public void setAttributeid(Integer attributeid) {
|
||||||
|
this.attributeid = attributeid;
|
||||||
|
}
|
||||||
|
public Integer getCategoryid() {
|
||||||
|
return categoryid;
|
||||||
|
}
|
||||||
|
public void setCategoryid(Integer categoryid) {
|
||||||
|
this.categoryid = categoryid;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ArPageDto{" +
|
||||||
|
"status=" + status +
|
||||||
|
", pagenum=" + pagenum +
|
||||||
|
", pagesize=" + pagesize +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +1,36 @@
|
|||||||
package com.qf.myafterprojecy.pojo.dto;
|
package com.qf.myafterprojecy.pojo.dto;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class ArticleDto {
|
public class ArticleDto {
|
||||||
private Integer id;
|
private Integer articleid;
|
||||||
|
|
||||||
@NotBlank(message = "标题不能为空")
|
@NotBlank(message = "标题不能为空")
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
@NotBlank(message = "内容不能为空")
|
private String content;// 如果为空说明是长篇文章 不为空则是短篇说说
|
||||||
private String content;
|
|
||||||
|
|
||||||
@NotNull(message = "属性ID不能为空")
|
@NotNull(message = "属性ID不能为空")
|
||||||
private Integer attributeid;
|
private Integer attributeid;
|
||||||
|
|
||||||
private String img;
|
private String img;
|
||||||
|
|
||||||
|
private Integer viewCount;
|
||||||
|
|
||||||
|
private Integer likes;
|
||||||
|
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
// Getters and Setters
|
private String markdownscontent; // 文章内容的Markdown格式
|
||||||
|
|
||||||
public Integer getId() {
|
// Getters and Setters
|
||||||
return id;
|
public Integer getArticleid() {
|
||||||
|
return articleid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(Integer id) {
|
public void setArticleid(Integer articleid) {
|
||||||
this.id = id;
|
this.articleid = articleid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
@@ -48,12 +49,12 @@ public class ArticleDto {
|
|||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getStatus() {
|
public Integer getAttributeid() {
|
||||||
return status;
|
return attributeid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(Integer status) {
|
public void setAttributeid(Integer attributeid) {
|
||||||
this.status = status;
|
this.attributeid = attributeid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getImg() {
|
public String getImg() {
|
||||||
@@ -63,4 +64,36 @@ public class ArticleDto {
|
|||||||
public void setImg(String img) {
|
public void setImg(String img) {
|
||||||
this.img = img;
|
this.img = img;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getViewCount() {
|
||||||
|
return viewCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setViewCount(Integer viewCount) {
|
||||||
|
this.viewCount = viewCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getLikes() {
|
||||||
|
return likes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLikes(Integer likes) {
|
||||||
|
this.likes = likes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMarkdownscontent() {
|
||||||
|
return markdownscontent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMarkdownscontent(String markdownscontent) {
|
||||||
|
this.markdownscontent = markdownscontent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import javax.validation.constraints.NotBlank;
|
|||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
public class CategoryAttributeDto {
|
public class CategoryAttributeDto {
|
||||||
|
private Integer attributeid;
|
||||||
|
|
||||||
@NotNull(message = "分类ID不能为空")
|
@NotNull(message = "分类ID不能为空")
|
||||||
private Integer categoryid;
|
private Integer categoryid;
|
||||||
@@ -12,6 +13,14 @@ public class CategoryAttributeDto {
|
|||||||
private String attributename;
|
private String attributename;
|
||||||
|
|
||||||
// Getters and Setters
|
// Getters and Setters
|
||||||
|
public Integer getAttributeid() {
|
||||||
|
return attributeid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttributeid(Integer attributeid) {
|
||||||
|
this.attributeid = attributeid;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getCategoryid() {
|
public Integer getCategoryid() {
|
||||||
return categoryid;
|
return categoryid;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,27 @@
|
|||||||
package com.qf.myafterprojecy.pojo.dto;
|
package com.qf.myafterprojecy.pojo.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
public class CategoryDto {
|
public class CategoryDto {
|
||||||
private Integer typeid;
|
private Integer Categoryid;
|
||||||
|
|
||||||
|
@NotBlank(message = "分类名称不能为空")
|
||||||
private String typename;
|
private String typename;
|
||||||
|
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
// Getters and Setters
|
// Getters and Setters
|
||||||
public Integer getTypeid() {
|
public Integer getCategoryid() {
|
||||||
return typeid;
|
return Categoryid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTypeid(Integer typeid) {
|
public void setCategoryid(Integer Categoryid) {
|
||||||
this.typeid = typeid;
|
this.Categoryid = Categoryid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTypename() {
|
public String getTypename() {
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.qf.myafterprojecy.pojo.dto;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class MarkdownDto {
|
|
||||||
@NotBlank(message = "Markdown内容不能为空")
|
|
||||||
private String markdownscontent;
|
|
||||||
|
|
||||||
public String getMarkdownscontent() {
|
|
||||||
return markdownscontent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMarkdownscontent(String markdownscontent) {
|
|
||||||
this.markdownscontent = markdownscontent;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -18,6 +18,10 @@ public class MessageDto {
|
|||||||
private Integer replyid;
|
private Integer replyid;
|
||||||
|
|
||||||
private Integer articleid;
|
private Integer articleid;
|
||||||
|
|
||||||
|
private Integer likes;
|
||||||
|
|
||||||
|
private String messageimg;
|
||||||
|
|
||||||
public Integer getReplyid() {
|
public Integer getReplyid() {
|
||||||
return replyid;
|
return replyid;
|
||||||
@@ -26,6 +30,7 @@ public class MessageDto {
|
|||||||
public void setReplyid(Integer replyid) {
|
public void setReplyid(Integer replyid) {
|
||||||
this.replyid = replyid;
|
this.replyid = replyid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getMessageid() {
|
public Integer getMessageid() {
|
||||||
return messageid;
|
return messageid;
|
||||||
}
|
}
|
||||||
@@ -81,4 +86,20 @@ public class MessageDto {
|
|||||||
public void setArticleid(Integer articleid) {
|
public void setArticleid(Integer articleid) {
|
||||||
this.articleid = articleid;
|
this.articleid = articleid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getLikes() {
|
||||||
|
return likes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLikes(Integer likes) {
|
||||||
|
this.likes = likes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessageimg() {
|
||||||
|
return messageimg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessageimg(String messageimg) {
|
||||||
|
this.messageimg = messageimg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.qf.myafterprojecy.pojo.dto;
|
||||||
|
|
||||||
|
public class MessagePageDto {
|
||||||
|
private Integer pageNum;
|
||||||
|
private Integer pageSize;
|
||||||
|
private Integer articleid;
|
||||||
|
|
||||||
|
public Integer getPageNum() {
|
||||||
|
return pageNum;
|
||||||
|
}
|
||||||
|
public void setPageNum(Integer pageNum) {
|
||||||
|
this.pageNum = pageNum;
|
||||||
|
}
|
||||||
|
public Integer getPageSize() {
|
||||||
|
return pageSize;
|
||||||
|
}
|
||||||
|
public void setPageSize(Integer pageSize) {
|
||||||
|
this.pageSize = pageSize;
|
||||||
|
}
|
||||||
|
public Integer getArticleid() {
|
||||||
|
return articleid;
|
||||||
|
}
|
||||||
|
public void setArticleid(Integer articleid) {
|
||||||
|
this.articleid = articleid;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "MessagePageDto{" +
|
||||||
|
"pageNum=" + pageNum +
|
||||||
|
", pageSize=" + pageSize +
|
||||||
|
", articleid=" + articleid +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.qf.myafterprojecy.pojo.dto;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class NonsenseDto {
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
private Integer status;//状态 0:未发表 1:已发表 2:已删除
|
||||||
|
|
||||||
|
private Date time;
|
||||||
|
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime(Date time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@ package com.qf.myafterprojecy.pojo.dto;
|
|||||||
import javax.validation.constraints.NotBlank;
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
public class UserDto {
|
public class UserDto {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
@NotBlank(message = "用户名不能为空")
|
@NotBlank(message = "用户名不能为空")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@@ -15,9 +17,16 @@ public class UserDto {
|
|||||||
@NotBlank(message = "手机号不能为空")
|
@NotBlank(message = "手机号不能为空")
|
||||||
private String phone;
|
private String phone;
|
||||||
|
|
||||||
@NotBlank(message = "角色不能为空")
|
|
||||||
private int role;
|
private int role;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
@@ -57,5 +66,4 @@ public class UserDto {
|
|||||||
public void setRole(int role) {
|
public void setRole(int role) {
|
||||||
this.role = role;
|
this.role = role;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.qf.myafterprojecy.repository;
|
package com.qf.myafterprojecy.repository;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.pojo.Article;
|
import com.qf.myafterprojecy.pojo.Article;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Modifying;
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
@@ -79,6 +81,7 @@ public interface ArticleRepository extends JpaRepository<Article, Integer> {
|
|||||||
*/
|
*/
|
||||||
@Query("SELECT a FROM Article a WHERE a.status = 1 ORDER BY a.viewCount DESC")
|
@Query("SELECT a FROM Article a WHERE a.status = 1 ORDER BY a.viewCount DESC")
|
||||||
List<Article> findMostViewed();
|
List<Article> findMostViewed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据状态查询文章列表
|
* 根据状态查询文章列表
|
||||||
* @param status 文章状态,0-草稿,1-已发布,2-已删除
|
* @param status 文章状态,0-草稿,1-已发布,2-已删除
|
||||||
@@ -86,4 +89,47 @@ public interface ArticleRepository extends JpaRepository<Article, Integer> {
|
|||||||
*/
|
*/
|
||||||
@Query("SELECT a FROM Article a WHERE a.status = :status")
|
@Query("SELECT a FROM Article a WHERE a.status = :status")
|
||||||
List<Article> findByStatus(@Param("status") Integer status);
|
List<Article> findByStatus(@Param("status") Integer status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据状态分页查询文章列表
|
||||||
|
* @param status 文章状态,0-草稿,1-已发布,2-已删除
|
||||||
|
* @param pageable 分页参数,包含页码、每页大小和排序信息
|
||||||
|
* @return 返回符合状态条件的文章分页结果
|
||||||
|
*/
|
||||||
|
@Query("SELECT a FROM Article a WHERE a.status = :status ORDER BY a.createdAt DESC")
|
||||||
|
Page<Article> findByStatusWithPagination(@Param("status") Integer status, Pageable pageable);
|
||||||
|
/**
|
||||||
|
* 根据属性ID数组分页查询文章列表
|
||||||
|
* @param attributeids 文章属性ID数组
|
||||||
|
* @param status 文章状态,0-草稿,1-已发布,2-已删除
|
||||||
|
* @param pageable 分页参数,包含页码、每页大小和排序信息
|
||||||
|
* @return 返回符合状态条件的文章分页结果
|
||||||
|
*/
|
||||||
|
@Query("SELECT a FROM Article a WHERE a.status = :status AND a.attributeid IN :attributeids ORDER BY a.createdAt DESC")
|
||||||
|
Page<Article> findByStatusWithPagination(@Param("status") Integer status, @Param("attributeids") List<Integer> attributeids, Pageable pageable);
|
||||||
|
/**
|
||||||
|
* 根据属性ID分页查询文章列表
|
||||||
|
* @param attributeid 文章属性ID
|
||||||
|
* @param status 文章状态,0-草稿,1-已发布,2-已删除
|
||||||
|
* @param pageable 分页参数,包含页码、每页大小和排序信息
|
||||||
|
* @return 返回符合状态条件的文章分页结果
|
||||||
|
*/
|
||||||
|
@Query("SELECT a FROM Article a WHERE a.status = :status AND a.attributeid = :attributeid ORDER BY a.createdAt DESC")
|
||||||
|
Page<Article> findByStatusWithPagination(@Param("status") Integer status, @Param("attributeid") Integer attributeid, Pageable pageable);
|
||||||
|
/**
|
||||||
|
* 根据文章标题分页模糊查询文章列表
|
||||||
|
* @param title 文章标题
|
||||||
|
* @param status 文章状态,0-草稿,1-已发布,2-已删除
|
||||||
|
* @param pageable 分页参数,包含页码、每页大小和排序信息
|
||||||
|
* @return 返回符合状态条件的文章分页结果
|
||||||
|
*/
|
||||||
|
@Query("SELECT a FROM Article a WHERE a.status = :status AND a.title LIKE %:title% ORDER BY a.createdAt DESC")
|
||||||
|
Page<Article> findByStatusWithPagination(@Param("status") Integer status, @Param("title") String title, Pageable pageable);
|
||||||
|
/**
|
||||||
|
* 统计指定状态的文章数量
|
||||||
|
* @param status 文章状态,0-草稿,1-已发布,2-已删除
|
||||||
|
* @return 返回符合状态条件的文章数量
|
||||||
|
*/
|
||||||
|
@Query("SELECT COUNT(a) FROM Article a WHERE a.status = :status")
|
||||||
|
Integer countByStatus(@Param("status") Integer status);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.qf.myafterprojecy.repository;
|
package com.qf.myafterprojecy.repository;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.pojo.Category_attribute;
|
import com.qf.myafterprojecy.pojo.Categoryattribute;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
@@ -10,23 +10,23 @@ import java.util.List;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface CategoryAttributeRepository extends JpaRepository<Category_attribute, Integer> {
|
public interface CategoryAttributeRepository extends JpaRepository<Categoryattribute, Integer> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据分类ID查询分类属性列表
|
* 根据分类ID查询分类属性列表
|
||||||
* @param categoryid 分类ID
|
* @param categoryid 分类ID
|
||||||
* @return 返回该分类下的所有属性列表
|
* @return 返回该分类下的所有属性列表
|
||||||
*/
|
*/
|
||||||
@Query("SELECT ca FROM Category_attribute ca WHERE ca.categoryid = :categoryid")
|
@Query("SELECT ca FROM Categoryattribute ca WHERE ca.categoryid = :categoryid")
|
||||||
List<Category_attribute> findByCategoryId(@Param("categoryid") Integer categoryid);
|
List<Categoryattribute> findByCategoryId(@Param("categoryid") Integer categoryid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据属性ID查询属性信息
|
* 根据属性ID查询属性信息
|
||||||
* @param attributeid 属性ID
|
* @param attributeid 属性ID
|
||||||
* @return 返回属性对象
|
* @return 返回属性对象
|
||||||
*/
|
*/
|
||||||
@Query("SELECT ca FROM Category_attribute ca WHERE ca.attributeid = :attributeid")
|
@Query("SELECT ca FROM Categoryattribute ca WHERE ca.attributeid = :attributeid")
|
||||||
Optional<Category_attribute> findByAttributeId(@Param("attributeid") Integer attributeid);
|
Optional<Categoryattribute> findByAttributeId(@Param("attributeid") Integer attributeid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查分类下是否存在指定名称的属性
|
* 检查分类下是否存在指定名称的属性
|
||||||
@@ -42,5 +42,5 @@ public interface CategoryAttributeRepository extends JpaRepository<Category_attr
|
|||||||
* @param attributename 属性名称
|
* @param attributename 属性名称
|
||||||
* @return 属性对象
|
* @return 属性对象
|
||||||
*/
|
*/
|
||||||
Optional<Category_attribute> findByCategoryidAndAttributename(Integer categoryid, String attributename);
|
Optional<Categoryattribute> findByCategoryidAndAttributename(Integer categoryid, String attributename);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
package com.qf.myafterprojecy.repository;
|
package com.qf.myafterprojecy.repository;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.pojo.Message;
|
import com.qf.myafterprojecy.pojo.Message;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties.Pageable;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
@@ -60,10 +64,33 @@ public interface MessageRepository extends JpaRepository<Message, Integer> {
|
|||||||
void incrementLikes(@Param("messageId") Integer messageId);
|
void incrementLikes(@Param("messageId") Integer messageId);
|
||||||
// 统计指定文章的评论数量
|
// 统计指定文章的评论数量
|
||||||
/**
|
/**
|
||||||
* 统计指定文章的评论数量
|
* 根据文章ID分页查询消息
|
||||||
* @param articleId 文章ID
|
* @param articleid 文章ID
|
||||||
* @return 评论数量
|
* @param pageable 分页信息
|
||||||
|
* @return 分页消息列表
|
||||||
*/
|
*/
|
||||||
@Query("SELECT COUNT(m) FROM Message m WHERE m.articleid = :articleId")
|
@Query("SELECT m FROM Message m WHERE m.articleid = :articleId ORDER BY m.createdAt DESC")
|
||||||
Long countByArticleId(@Param("articleId") Integer articleId);
|
Page<Message> findByArticleId(@Param("articleId") Integer articleId, PageRequest pageable);
|
||||||
|
/**
|
||||||
|
* 根据页查询消息
|
||||||
|
* @param pageable 分页信息
|
||||||
|
* @return 分页消息列表
|
||||||
|
*/
|
||||||
|
@Query("SELECT m FROM Message m WHERE m.articleid IS NULL ORDER BY m.createdAt DESC")
|
||||||
|
Page<Message> findAllMessages(PageRequest pageable);
|
||||||
|
/**
|
||||||
|
* 统计指定文章下的回复消息数量
|
||||||
|
* @param articleId 文章ID
|
||||||
|
* @return 回复消息数量
|
||||||
|
*/
|
||||||
|
@Query("SELECT COUNT(m) FROM Message m WHERE m.articleid = :articleId AND m.parentid IS NULL")
|
||||||
|
Integer countReplyByArticleId(@Param("articleId") Integer articleId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统计指定文章id parentid为空的回复消息数量
|
||||||
|
* @param articleId 文章ID
|
||||||
|
* @return 回复消息数量
|
||||||
|
*/
|
||||||
|
@Query("SELECT COUNT(m) FROM Message m WHERE m.articleid IS NULL AND m.parentid IS NULL")
|
||||||
|
Integer countReplyByArticleIdIsNull();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.qf.myafterprojecy.repository;
|
||||||
|
|
||||||
|
import com.qf.myafterprojecy.pojo.Nonsense;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface NonsenseRepository extends JpaRepository<Nonsense, Integer> {
|
||||||
|
/**
|
||||||
|
* 根据状态获取文章列表
|
||||||
|
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||||
|
* @return 返回包含文章列表的ResponseMessage对象
|
||||||
|
*/
|
||||||
|
@Query("SELECT n FROM Nonsense n WHERE n.status = :status")
|
||||||
|
List<Nonsense> findByStatus(@Param("status") Integer status);
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.qf.myafterprojecy.service.imp;
|
package com.qf.myafterprojecy.service;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Article;
|
import com.qf.myafterprojecy.pojo.Article;
|
||||||
|
import com.qf.myafterprojecy.pojo.dto.ArriclePageDto;
|
||||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -18,7 +20,18 @@ public interface IArticleService {
|
|||||||
* @return 返回符合查询条件的文章列表
|
* @return 返回符合查询条件的文章列表
|
||||||
*/
|
*/
|
||||||
ResponseMessage<List<Article>> getArticlesByTitle(String title);
|
ResponseMessage<List<Article>> getArticlesByTitle(String title);
|
||||||
|
/**
|
||||||
|
* 根据状态获取文章列表
|
||||||
|
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||||
|
* @return 返回包含文章列表的ResponseMessage对象
|
||||||
|
*/
|
||||||
|
ResponseMessage<List<Article>> getArticlesByStatus(Integer status);
|
||||||
|
/**
|
||||||
|
* 获取文章数量
|
||||||
|
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||||
|
* @return 返回文章数量
|
||||||
|
*/
|
||||||
|
ResponseMessage<Integer> getArticleCount(Integer status);
|
||||||
/**
|
/**
|
||||||
* 创建新文章
|
* 创建新文章
|
||||||
* 仅限AUTHOR角色用户访问
|
* 仅限AUTHOR角色用户访问
|
||||||
@@ -83,4 +96,13 @@ public interface IArticleService {
|
|||||||
* @return 返回包含已发布文章列表的ResponseMessage对象
|
* @return 返回包含已发布文章列表的ResponseMessage对象
|
||||||
*/
|
*/
|
||||||
ResponseMessage<List<Article>> getPublishedArticles();
|
ResponseMessage<List<Article>> getPublishedArticles();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据状态分页查询文章列表
|
||||||
|
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||||
|
* @param page 页码,从0开始
|
||||||
|
* @param size 每页大小
|
||||||
|
* @return 返回包含分页文章列表的ResponseMessage对象
|
||||||
|
*/
|
||||||
|
ResponseMessage<Page<Article>> getArticlesByStatusWithPagination(ArriclePageDto arriclePageDto);
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,38 @@
|
|||||||
package com.qf.myafterprojecy.service.imp;
|
package com.qf.myafterprojecy.service;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Category_attribute;
|
import com.qf.myafterprojecy.pojo.Categoryattribute;
|
||||||
import com.qf.myafterprojecy.pojo.dto.CategoryAttributeDto;
|
import com.qf.myafterprojecy.pojo.dto.CategoryAttributeDto;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ICategoryAttributeService {
|
public interface ICategoryAttributeService {
|
||||||
|
/**
|
||||||
|
* 获取全部分类属性
|
||||||
|
* @return 所有分类属性列表
|
||||||
|
*/
|
||||||
|
ResponseMessage<List<Categoryattribute>> getAllCategoryAttributes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据ID获取分类属性
|
* 根据ID获取分类属性
|
||||||
* @param id 属性ID
|
* @param id 属性ID
|
||||||
* @return 分类属性信息
|
* @return 分类属性信息
|
||||||
*/
|
*/
|
||||||
ResponseMessage<Category_attribute> getCategoryAttributeById(Integer id);
|
ResponseMessage<Categoryattribute> getCategoryAttributeById(Integer id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据分类ID获取属性列表
|
* 根据分类ID获取属性列表
|
||||||
* @param categoryId 分类ID
|
* @param categoryId 分类ID
|
||||||
* @return 属性列表
|
* @return 属性列表
|
||||||
*/
|
*/
|
||||||
ResponseMessage<List<Category_attribute>> getAttributesByCategoryId(Integer categoryId);
|
ResponseMessage<List<Categoryattribute>> getAttributesByCategoryId(Integer categoryId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建新的分类属性
|
* 创建新的分类属性
|
||||||
* @param dto 分类属性数据
|
* @param dto 分类属性数据
|
||||||
* @return 创建结果
|
* @return 创建结果
|
||||||
*/
|
*/
|
||||||
ResponseMessage<Category_attribute> saveCategoryAttribute(CategoryAttributeDto dto);
|
ResponseMessage<Categoryattribute> saveCategoryAttribute(CategoryAttributeDto dto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新分类属性
|
* 更新分类属性
|
||||||
@@ -35,7 +40,7 @@ public interface ICategoryAttributeService {
|
|||||||
* @param dto 分类属性数据
|
* @param dto 分类属性数据
|
||||||
* @return 更新结果
|
* @return 更新结果
|
||||||
*/
|
*/
|
||||||
ResponseMessage<Category_attribute> updateCategoryAttribute(Integer id, CategoryAttributeDto dto);
|
ResponseMessage<Categoryattribute> updateCategoryAttribute(Integer id, CategoryAttributeDto dto);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除分类属性
|
* 删除分类属性
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.qf.myafterprojecy.service.imp;
|
package com.qf.myafterprojecy.service;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Category;
|
import com.qf.myafterprojecy.pojo.Category;
|
||||||
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
||||||
|
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
package com.qf.myafterprojecy.service.imp;
|
package com.qf.myafterprojecy.service;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Message;
|
import com.qf.myafterprojecy.pojo.Message;
|
||||||
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
||||||
|
import com.qf.myafterprojecy.pojo.dto.MessagePageDto;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -14,7 +17,18 @@ public interface IMessageService {
|
|||||||
* ResponseMessage是响应消息的包装类,Iterable<Message>表示可迭代的消息集合
|
* ResponseMessage是响应消息的包装类,Iterable<Message>表示可迭代的消息集合
|
||||||
*/
|
*/
|
||||||
ResponseMessage<Iterable<Message>> getAllMessages();
|
ResponseMessage<Iterable<Message>> getAllMessages();
|
||||||
|
/**
|
||||||
|
* 分页
|
||||||
|
* @param id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
ResponseMessage<List<Message>> getMessagesByPage(MessagePageDto messagePageDto);
|
||||||
|
/**
|
||||||
|
* 获取回复消息条数 如果id为空获取文章id为空的消息条数
|
||||||
|
* @param articleId 文章id
|
||||||
|
* @return 回复消息条数
|
||||||
|
*/
|
||||||
|
ResponseMessage<Integer> getMessageCountByArticleId(Integer articleId);
|
||||||
/**
|
/**
|
||||||
* 根据消息ID获取消息的方法
|
* 根据消息ID获取消息的方法
|
||||||
*
|
*
|
||||||
@@ -82,11 +96,4 @@ public interface IMessageService {
|
|||||||
// 删除所有评论
|
// 删除所有评论
|
||||||
ResponseMessage<Void> deleteAllMessages();
|
ResponseMessage<Void> deleteAllMessages();
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取指定文章的评论数量
|
|
||||||
*
|
|
||||||
* @param articleId 文章ID
|
|
||||||
* @return 评论数量
|
|
||||||
*/
|
|
||||||
ResponseMessage<Long> getMessageCountByArticleId(Integer articleId);
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.qf.myafterprojecy.service;
|
||||||
|
|
||||||
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
|
import com.qf.myafterprojecy.pojo.Nonsense;
|
||||||
|
import com.qf.myafterprojecy.pojo.dto.NonsenseDto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface INonsenseService {
|
||||||
|
/**
|
||||||
|
* 获取所有疯言疯语内容
|
||||||
|
* @return 疯言疯语内容列表
|
||||||
|
*/
|
||||||
|
ResponseMessage<List<Nonsense>> getAllNonsense();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID获取疯言疯语内容
|
||||||
|
* @param id 疯言疯语内容ID
|
||||||
|
* @return 疯言疯语内容
|
||||||
|
*/
|
||||||
|
ResponseMessage<Nonsense> getNonsenseById(Integer id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据状态获取疯言疯语内容
|
||||||
|
* @param status 状态:0未发表 1已发表 2已删除
|
||||||
|
* @return 疯言疯语内容列表
|
||||||
|
*/
|
||||||
|
ResponseMessage<List<Nonsense>> getNonsenseByStatus(Integer status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新疯言疯语内容状态
|
||||||
|
* @param id 疯言疯语内容ID
|
||||||
|
* @param status 新状态:0未发表 1已发表 2已删除
|
||||||
|
* @return 更新结果
|
||||||
|
*/
|
||||||
|
ResponseMessage<Nonsense> updateNonsenseStatus(Integer id, Integer status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存疯言疯语内容
|
||||||
|
* @param nonsenseDto 疯言疯语内容数据传输对象
|
||||||
|
* @return 保存结果
|
||||||
|
*/
|
||||||
|
ResponseMessage<Nonsense> saveNonsense(NonsenseDto nonsenseDto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新疯言疯语内容
|
||||||
|
* @param id 疯言疯语内容ID
|
||||||
|
* @param nonsenseDto 疯言疯语内容数据传输对象
|
||||||
|
* @return 更新结果
|
||||||
|
*/
|
||||||
|
ResponseMessage<Nonsense> updateNonsense(Integer id, NonsenseDto nonsenseDto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除疯言疯语内容
|
||||||
|
* @param id 疯言疯语内容ID
|
||||||
|
* @return 删除结果
|
||||||
|
*/
|
||||||
|
ResponseMessage<Boolean> deleteNonsense(Integer id);
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.qf.myafterprojecy.service.imp;
|
package com.qf.myafterprojecy.service;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Users;
|
import com.qf.myafterprojecy.pojo.Users;
|
||||||
import com.qf.myafterprojecy.pojo.dto.UserDto;
|
import com.qf.myafterprojecy.pojo.dto.UserDto;
|
||||||
|
|
||||||
@@ -1,22 +1,27 @@
|
|||||||
package com.qf.myafterprojecy.service;
|
package com.qf.myafterprojecy.service.impl;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Article;
|
import com.qf.myafterprojecy.pojo.Article;
|
||||||
|
import com.qf.myafterprojecy.pojo.Categoryattribute;
|
||||||
|
import com.qf.myafterprojecy.pojo.dto.ArriclePageDto;
|
||||||
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
import com.qf.myafterprojecy.pojo.dto.ArticleDto;
|
||||||
import com.qf.myafterprojecy.repository.ArticleRepository;
|
import com.qf.myafterprojecy.repository.ArticleRepository;
|
||||||
import com.qf.myafterprojecy.repository.CategoryAttributeRepository;
|
import com.qf.myafterprojecy.repository.CategoryAttributeRepository;
|
||||||
import com.qf.myafterprojecy.service.imp.IArticleService;
|
import com.qf.myafterprojecy.service.IArticleService;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ArticleService implements IArticleService {
|
public class ArticleService implements IArticleService {
|
||||||
@@ -29,6 +34,11 @@ public class ArticleService implements IArticleService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private CategoryAttributeRepository categoryAttributeRepository;
|
private CategoryAttributeRepository categoryAttributeRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文章ID获取文章详情
|
||||||
|
* @param id 文章ID
|
||||||
|
* @return 返回包含文章详情的ResponseMessage对象
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseMessage<Article> getArticleById(String id) {
|
public ResponseMessage<Article> getArticleById(String id) {
|
||||||
@@ -38,9 +48,10 @@ public class ArticleService implements IArticleService {
|
|||||||
}
|
}
|
||||||
Article article = articleRepository.findById(Integer.parseInt(id))
|
Article article = articleRepository.findById(Integer.parseInt(id))
|
||||||
.orElseThrow(() -> new RuntimeException("文章不存在"));
|
.orElseThrow(() -> new RuntimeException("文章不存在"));
|
||||||
|
// 文章浏览次数增加
|
||||||
|
articleRepository.incrementViewCount(Integer.parseInt(id));
|
||||||
|
|
||||||
|
|
||||||
// 暂时不增加浏览次数,以避免事务问题
|
|
||||||
// articleRepository.incrementViewCount(Integer.parseInt(id));
|
|
||||||
return ResponseMessage.success(article, "获取文章成功");
|
return ResponseMessage.success(article, "获取文章成功");
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
return ResponseMessage.badRequest("文章ID格式不正确");
|
return ResponseMessage.badRequest("文章ID格式不正确");
|
||||||
@@ -55,6 +66,50 @@ public class ArticleService implements IArticleService {
|
|||||||
return ResponseMessage.error("获取文章失败");
|
return ResponseMessage.error("获取文章失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 获取文章数量
|
||||||
|
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||||
|
* @return 返回文章数量
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public ResponseMessage<Integer> getArticleCount(Integer status) {
|
||||||
|
try {
|
||||||
|
if (status == null) {
|
||||||
|
return ResponseMessage.badRequest("文章状态不能为空");
|
||||||
|
}
|
||||||
|
if (status < 0 || status > 2) {
|
||||||
|
return ResponseMessage.badRequest("文章状态值必须在0到2之间");
|
||||||
|
}
|
||||||
|
Integer count = articleRepository.countByStatus(status);
|
||||||
|
return ResponseMessage.success(count, "获取文章数量成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取文章数量失败: {}", e.getMessage());
|
||||||
|
return ResponseMessage.error("获取文章数量失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 根据状态获取文章列表
|
||||||
|
* @param status 文章状态(0:未发表 1:已发表 2:已删除)
|
||||||
|
* @return 返回包含文章列表的ResponseMessage对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public ResponseMessage<List<Article>> getArticlesByStatus(Integer status) {
|
||||||
|
try {
|
||||||
|
if (status == null) {
|
||||||
|
return ResponseMessage.badRequest("文章状态不能为空");
|
||||||
|
}
|
||||||
|
if (status < 0 || status > 2) {
|
||||||
|
return ResponseMessage.badRequest("文章状态值必须在0到2之间");
|
||||||
|
}
|
||||||
|
List<Article> articles = articleRepository.findByStatus(status);
|
||||||
|
return ResponseMessage.success(articles, "根据状态查询文章成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("根据状态查询文章列表失败: {}", e.getMessage());
|
||||||
|
return ResponseMessage.error("根据状态查询文章列表失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 获取已发布的文章列表
|
* 获取已发布的文章列表
|
||||||
* @return 返回包含已发布文章列表的ResponseMessage对象
|
* @return 返回包含已发布文章列表的ResponseMessage对象
|
||||||
@@ -70,6 +125,52 @@ public class ArticleService implements IArticleService {
|
|||||||
return ResponseMessage.error("获取已发布文章列表失败");
|
return ResponseMessage.error("获取已发布文章列表失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public ResponseMessage<Page<Article>> getArticlesByStatusWithPagination(ArriclePageDto arriclePageDto) {
|
||||||
|
if (arriclePageDto.getPagenum() == null || arriclePageDto.getPagenum() < 0) {
|
||||||
|
arriclePageDto.setPagenum(0); // 默认第一页
|
||||||
|
}
|
||||||
|
if (arriclePageDto.getPagesize() == null || arriclePageDto.getPagesize() <= 0 || arriclePageDto.getPagesize() > 100) {
|
||||||
|
arriclePageDto.setPagesize(10); // 默认每页10条,最大100条
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 如果文章状态值是否在0到2之间则根据文章状态查询文章列表
|
||||||
|
if (arriclePageDto.getStatus() < 0 || arriclePageDto.getStatus() > 2) {
|
||||||
|
return ResponseMessage.badRequest("文章状态值必须在0到2之间");
|
||||||
|
}
|
||||||
|
PageRequest pageRequest = PageRequest.of(arriclePageDto.getPagenum(), arriclePageDto.getPagesize());
|
||||||
|
// 如果文章分类ID不为空则根据文章分类ID查询文章列表
|
||||||
|
if (arriclePageDto.getCategoryid() != null && arriclePageDto.getCategoryid() > 0) {
|
||||||
|
// 如果文章分类ID不为空则根据文章分类ID查询文章列表
|
||||||
|
List<Categoryattribute> categoryAttribute = categoryAttributeRepository.findByCategoryId(arriclePageDto.getCategoryid());
|
||||||
|
if (categoryAttribute.isEmpty()) {
|
||||||
|
return ResponseMessage.badRequest("分类下没有属性");
|
||||||
|
}
|
||||||
|
// 如果文章属性ID数组不为空则根据文章属性ID数组查询文章列表
|
||||||
|
List<Integer> attributeids = categoryAttribute.stream().map(Categoryattribute::getAttributeid).collect(Collectors.toList());
|
||||||
|
// 根据分类ID对应的属性ID数组分页查询文章列表
|
||||||
|
Page<Article> articlePage = articleRepository.findByStatusWithPagination(arriclePageDto.getStatus(), attributeids, pageRequest);
|
||||||
|
return ResponseMessage.success(articlePage, "根据分类ID分页查询文章成功");
|
||||||
|
}
|
||||||
|
// 如果文章属性ID不为空则根据文章属性ID查询文章列表
|
||||||
|
if (arriclePageDto.getAttributeid() != null && arriclePageDto.getAttributeid() > 0) {
|
||||||
|
Page<Article> articlePage = articleRepository.findByStatusWithPagination(arriclePageDto.getStatus(), arriclePageDto.getAttributeid(), pageRequest);
|
||||||
|
return ResponseMessage.success(articlePage, "根据属性ID分页查询文章成功");
|
||||||
|
}
|
||||||
|
// 如果文章标题不为空则根据文章标题查询文章列表
|
||||||
|
if (arriclePageDto.getTitle() != null && !arriclePageDto.getTitle().isEmpty()) {
|
||||||
|
Page<Article> articlePage = articleRepository.findByStatusWithPagination(arriclePageDto.getStatus(), arriclePageDto.getTitle(), pageRequest);
|
||||||
|
return ResponseMessage.success(articlePage, "根据标题分页查询文章成功");
|
||||||
|
}
|
||||||
|
Page<Article> articlePage = articleRepository.findByStatusWithPagination(arriclePageDto.getStatus(), pageRequest);
|
||||||
|
return ResponseMessage.success(articlePage, "根据状态分页查询文章成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("根据状态分页查询文章列表失败: {}", e.getMessage());
|
||||||
|
return ResponseMessage.error("根据状态分页查询文章列表失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseMessage<List<Article>> getArticlesByTitle(String title) {
|
public ResponseMessage<List<Article>> getArticlesByTitle(String title) {
|
||||||
@@ -168,8 +269,6 @@ public class ArticleService implements IArticleService {
|
|||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseMessage<List<Article>> getArticlesByCategory(Integer categoryId) {
|
public ResponseMessage<List<Article>> getArticlesByCategory(Integer categoryId) {
|
||||||
try {
|
try {
|
||||||
// 为了兼容旧接口,这里需要调整逻辑
|
|
||||||
// 旧接口使用typeid,但我们现在用attributeid
|
|
||||||
// 可以考虑查询该分类下的所有属性,然后获取相关文章
|
// 可以考虑查询该分类下的所有属性,然后获取相关文章
|
||||||
log.warn("使用了旧接口getArticlesByCategory,请考虑迁移到getArticlesByAttribute");
|
log.warn("使用了旧接口getArticlesByCategory,请考虑迁移到getArticlesByAttribute");
|
||||||
return ResponseMessage.success(articleRepository.findPublishedByAttribute(categoryId), "获取分类文章成功");
|
return ResponseMessage.success(articleRepository.findPublishedByAttribute(categoryId), "获取分类文章成功");
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.qf.myafterprojecy.service;
|
package com.qf.myafterprojecy.service.impl;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Category_attribute;
|
import com.qf.myafterprojecy.pojo.Categoryattribute;
|
||||||
import com.qf.myafterprojecy.pojo.dto.CategoryAttributeDto;
|
import com.qf.myafterprojecy.pojo.dto.CategoryAttributeDto;
|
||||||
import com.qf.myafterprojecy.repository.CategoryAttributeRepository;
|
import com.qf.myafterprojecy.repository.CategoryAttributeRepository;
|
||||||
import com.qf.myafterprojecy.service.imp.ICategoryAttributeService;
|
import com.qf.myafterprojecy.service.ICategoryAttributeService;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -24,15 +24,36 @@ public class CategoryAttributeService implements ICategoryAttributeService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private CategoryAttributeRepository categoryAttributeRepository;
|
private CategoryAttributeRepository categoryAttributeRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取全部分类属性
|
||||||
|
* @return 所有分类属性列表
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseMessage<Category_attribute> getCategoryAttributeById(Integer id) {
|
public ResponseMessage<List<Categoryattribute>> getAllCategoryAttributes() {
|
||||||
|
try {
|
||||||
|
List<Categoryattribute> attributes = categoryAttributeRepository.findAll();
|
||||||
|
return ResponseMessage.success(attributes, "获取所有分类属性成功");
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
log.error("获取所有分类属性失败: {}", e.getMessage());
|
||||||
|
return ResponseMessage.error("获取所有分类属性失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ID获取分类属性
|
||||||
|
* @param id 属性ID
|
||||||
|
* @return 分类属性信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public ResponseMessage<Categoryattribute> getCategoryAttributeById(Integer id) {
|
||||||
try {
|
try {
|
||||||
if (id == null || id <= 0) {
|
if (id == null || id <= 0) {
|
||||||
return ResponseMessage.badRequest("属性ID无效");
|
return ResponseMessage.badRequest("属性ID无效");
|
||||||
}
|
}
|
||||||
|
|
||||||
Category_attribute attribute = categoryAttributeRepository.findById(id)
|
Categoryattribute attribute = categoryAttributeRepository.findById(id)
|
||||||
.orElseThrow(() -> new RuntimeException("分类属性不存在"));
|
.orElseThrow(() -> new RuntimeException("分类属性不存在"));
|
||||||
|
|
||||||
return ResponseMessage.success(attribute, "获取分类属性成功");
|
return ResponseMessage.success(attribute, "获取分类属性成功");
|
||||||
@@ -48,15 +69,20 @@ public class CategoryAttributeService implements ICategoryAttributeService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据分类ID获取属性列表
|
||||||
|
* @param categoryId 分类ID
|
||||||
|
* @return 属性列表
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseMessage<List<Category_attribute>> getAttributesByCategoryId(Integer categoryId) {
|
public ResponseMessage<List<Categoryattribute>> getAttributesByCategoryId(Integer categoryId) {
|
||||||
try {
|
try {
|
||||||
if (categoryId == null || categoryId <= 0) {
|
if (categoryId == null || categoryId <= 0) {
|
||||||
return ResponseMessage.badRequest("分类ID无效");
|
return ResponseMessage.badRequest("分类ID无效");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Category_attribute> attributes = categoryAttributeRepository.findByCategoryId(categoryId);
|
List<Categoryattribute> attributes = categoryAttributeRepository.findByCategoryId(categoryId);
|
||||||
return ResponseMessage.success(attributes, "获取分类属性列表成功");
|
return ResponseMessage.success(attributes, "获取分类属性列表成功");
|
||||||
} catch (DataAccessException e) {
|
} catch (DataAccessException e) {
|
||||||
log.error("获取分类属性列表失败: {}", e.getMessage());
|
log.error("获取分类属性列表失败: {}", e.getMessage());
|
||||||
@@ -64,9 +90,14 @@ public class CategoryAttributeService implements ICategoryAttributeService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存分类属性
|
||||||
|
* @param dto 分类属性DTO
|
||||||
|
* @return 保存结果
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ResponseMessage<Category_attribute> saveCategoryAttribute(CategoryAttributeDto dto) {
|
public ResponseMessage<Categoryattribute> saveCategoryAttribute(CategoryAttributeDto dto) {
|
||||||
try {
|
try {
|
||||||
// 检查属性名称是否已存在于该分类下
|
// 检查属性名称是否已存在于该分类下
|
||||||
if (categoryAttributeRepository.existsByCategoryidAndAttributename(
|
if (categoryAttributeRepository.existsByCategoryidAndAttributename(
|
||||||
@@ -74,10 +105,10 @@ public class CategoryAttributeService implements ICategoryAttributeService {
|
|||||||
return ResponseMessage.badRequest("该分类下已存在同名属性");
|
return ResponseMessage.badRequest("该分类下已存在同名属性");
|
||||||
}
|
}
|
||||||
|
|
||||||
Category_attribute attribute = new Category_attribute();
|
Categoryattribute attribute = new Categoryattribute();
|
||||||
BeanUtils.copyProperties(dto, attribute);
|
BeanUtils.copyProperties(dto, attribute);
|
||||||
|
|
||||||
Category_attribute savedAttribute = categoryAttributeRepository.save(attribute);
|
Categoryattribute savedAttribute = categoryAttributeRepository.save(attribute);
|
||||||
log.info("成功创建分类属性: {}, 分类ID: {}",
|
log.info("成功创建分类属性: {}, 分类ID: {}",
|
||||||
savedAttribute.getAttributename(), savedAttribute.getCategoryid());
|
savedAttribute.getAttributename(), savedAttribute.getCategoryid());
|
||||||
|
|
||||||
@@ -88,15 +119,21 @@ public class CategoryAttributeService implements ICategoryAttributeService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新分类属性
|
||||||
|
* @param id 属性ID
|
||||||
|
* @param dto 分类属性DTO
|
||||||
|
* @return 更新结果
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ResponseMessage<Category_attribute> updateCategoryAttribute(Integer id, CategoryAttributeDto dto) {
|
public ResponseMessage<Categoryattribute> updateCategoryAttribute(Integer id, CategoryAttributeDto dto) {
|
||||||
try {
|
try {
|
||||||
if (id == null || id <= 0) {
|
if (id == null || id <= 0) {
|
||||||
return ResponseMessage.badRequest("属性ID无效");
|
return ResponseMessage.badRequest("属性ID无效");
|
||||||
}
|
}
|
||||||
|
|
||||||
Category_attribute attribute = categoryAttributeRepository.findById(id)
|
Categoryattribute attribute = categoryAttributeRepository.findById(id)
|
||||||
.orElseThrow(() -> new RuntimeException("分类属性不存在"));
|
.orElseThrow(() -> new RuntimeException("分类属性不存在"));
|
||||||
|
|
||||||
// 如果修改了属性名称,检查新名称是否已存在
|
// 如果修改了属性名称,检查新名称是否已存在
|
||||||
@@ -109,7 +146,7 @@ public class CategoryAttributeService implements ICategoryAttributeService {
|
|||||||
BeanUtils.copyProperties(dto, attribute);
|
BeanUtils.copyProperties(dto, attribute);
|
||||||
attribute.setAttributeid(id); // 确保ID不变
|
attribute.setAttributeid(id); // 确保ID不变
|
||||||
|
|
||||||
Category_attribute updatedAttribute = categoryAttributeRepository.save(attribute);
|
Categoryattribute updatedAttribute = categoryAttributeRepository.save(attribute);
|
||||||
log.info("成功更新分类属性: ID={}, 名称={}",
|
log.info("成功更新分类属性: ID={}, 名称={}",
|
||||||
updatedAttribute.getAttributeid(), updatedAttribute.getAttributename());
|
updatedAttribute.getAttributeid(), updatedAttribute.getAttributename());
|
||||||
|
|
||||||
@@ -126,6 +163,11 @@ public class CategoryAttributeService implements ICategoryAttributeService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除分类属性
|
||||||
|
* @param id 属性ID
|
||||||
|
* @return 删除结果
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ResponseMessage<Boolean> deleteCategoryAttribute(Integer id) {
|
public ResponseMessage<Boolean> deleteCategoryAttribute(Integer id) {
|
||||||
@@ -147,7 +189,12 @@ public class CategoryAttributeService implements ICategoryAttributeService {
|
|||||||
return ResponseMessage.error("删除分类属性失败");
|
return ResponseMessage.error("删除分类属性失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 检查分类属性是否存在
|
||||||
|
* @param categoryId 分类ID
|
||||||
|
* @param attributeName 属性名称
|
||||||
|
* @return 是否存在
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public ResponseMessage<Boolean> existsByCategoryAndName(Integer categoryId, String attributeName) {
|
public ResponseMessage<Boolean> existsByCategoryAndName(Integer categoryId, String attributeName) {
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.qf.myafterprojecy.service;
|
package com.qf.myafterprojecy.service.impl;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Category;
|
import com.qf.myafterprojecy.pojo.Category;
|
||||||
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
||||||
import com.qf.myafterprojecy.repository.CategoryRepository;
|
import com.qf.myafterprojecy.repository.CategoryRepository;
|
||||||
import com.qf.myafterprojecy.service.imp.ICategoryService;
|
import com.qf.myafterprojecy.service.ICategoryService;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -1,16 +1,20 @@
|
|||||||
package com.qf.myafterprojecy.service;
|
package com.qf.myafterprojecy.service.impl;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Message;
|
import com.qf.myafterprojecy.pojo.Message;
|
||||||
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
import com.qf.myafterprojecy.pojo.dto.MessageDto;
|
||||||
|
import com.qf.myafterprojecy.pojo.dto.MessagePageDto;
|
||||||
import com.qf.myafterprojecy.repository.MessageRepository;
|
import com.qf.myafterprojecy.repository.MessageRepository;
|
||||||
import com.qf.myafterprojecy.service.imp.IMessageService;
|
import com.qf.myafterprojecy.service.IMessageService;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties.Pageable;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@@ -231,20 +235,52 @@ public class MessageService implements IMessageService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseMessage<Long> getMessageCountByArticleId(Integer articleId) {
|
|
||||||
if (articleId == null || articleId <= 0) {
|
|
||||||
logger.warn("获取文章评论数量时ID无效: {}", articleId);
|
|
||||||
return ResponseMessage.badRequest("文章ID无效");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseMessage<List<Message>> getMessagesByPage(MessagePageDto messagePageDto) {
|
||||||
|
if (messagePageDto == null) {
|
||||||
|
logger.warn("分页查询消息时参数为空");
|
||||||
|
return ResponseMessage.badRequest("分页参数不能为空");
|
||||||
|
}
|
||||||
|
if (messagePageDto.getPageNum() == null) {
|
||||||
|
logger.warn("分页查询消息时页码无效: {}", messagePageDto.getPageNum());
|
||||||
|
return ResponseMessage.badRequest("页码无效");
|
||||||
|
}
|
||||||
|
if (messagePageDto.getPageSize() == null || messagePageDto.getPageSize() <= 0) {
|
||||||
|
logger.warn("分页查询消息时每页数量无效: {}", messagePageDto.getPageSize());
|
||||||
|
return ResponseMessage.badRequest("每页数量无效");
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
logger.info("获取文章评论数量: {}", articleId);
|
// 如何文章id为空,默认根据分页基础信息查询消息
|
||||||
Long count = messageRepository.countByArticleId(articleId);
|
PageRequest pageable = PageRequest.of(messagePageDto.getPageNum(), messagePageDto.getPageSize());
|
||||||
|
if (messagePageDto.getArticleid() != null && messagePageDto.getArticleid() > 0) {
|
||||||
|
// 如果文章ID存在,根据文章ID查询消息
|
||||||
|
Page<Message> messagePage = messageRepository.findByArticleId(messagePageDto.getArticleid(), pageable);
|
||||||
|
return ResponseMessage.success(messagePage.getContent(), "查询成功");
|
||||||
|
}
|
||||||
|
// 如果文章ID不存在,根据分页基础信息查询所有消息
|
||||||
|
Page<Message> messagePage = messageRepository.findAllMessages(pageable);
|
||||||
|
return ResponseMessage.success(messagePage.getContent(), "查询成功");
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
logger.error("分页查询消息失败: {}", messagePageDto, e);
|
||||||
|
return ResponseMessage.error("查询消息失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 获取回复消息条数 如果id为空获取文章id为空的消息条数
|
||||||
|
@Override
|
||||||
|
public ResponseMessage<Integer> getMessageCountByArticleId(Integer articleId) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
logger.info("获取文章回复数量: {}", articleId);
|
||||||
|
if (articleId == null || articleId <= 0) {
|
||||||
|
Integer count = messageRepository.countReplyByArticleIdIsNull();
|
||||||
|
return ResponseMessage.success(count, "查询成功");
|
||||||
|
}
|
||||||
|
Integer count = messageRepository.countReplyByArticleId(articleId);
|
||||||
return ResponseMessage.success(count, "查询成功");
|
return ResponseMessage.success(count, "查询成功");
|
||||||
} catch (DataAccessException e) {
|
} catch (DataAccessException e) {
|
||||||
logger.error("获取文章评论数量失败: {}", articleId, e);
|
logger.error("获取文章回复数量失败: {}", articleId, e);
|
||||||
return ResponseMessage.error("查询评论数量失败:" + e.getMessage());
|
return ResponseMessage.error("查询回复数量失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
package com.qf.myafterprojecy.service.impl;
|
||||||
|
|
||||||
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
|
import com.qf.myafterprojecy.pojo.Nonsense;
|
||||||
|
import com.qf.myafterprojecy.pojo.dto.NonsenseDto;
|
||||||
|
import com.qf.myafterprojecy.repository.NonsenseRepository;
|
||||||
|
import com.qf.myafterprojecy.service.INonsenseService;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class NonsenseService implements INonsenseService {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(NonsenseService.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NonsenseRepository nonsenseRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseMessage<List<Nonsense>> getAllNonsense() {
|
||||||
|
try {
|
||||||
|
// 获取所有疯言疯语内容,但在API层面只返回已发表(1)的内容
|
||||||
|
List<Nonsense> allNonsense = nonsenseRepository.findAll();
|
||||||
|
|
||||||
|
return new ResponseMessage<>(200, "获取成功", allNonsense, true);
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
logger.error("获取所有疯言疯语内容失败", e);
|
||||||
|
return new ResponseMessage<>(500, "数据库查询异常", null, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("获取所有疯言疯语内容失败", e);
|
||||||
|
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseMessage<Nonsense> getNonsenseById(Integer id) {
|
||||||
|
try {
|
||||||
|
Optional<Nonsense> nonsenseOptional = nonsenseRepository.findById(id);
|
||||||
|
if (nonsenseOptional.isPresent()) {
|
||||||
|
Nonsense nonsense = nonsenseOptional.get();
|
||||||
|
logger.info("获取ID为{}的疯言疯语内容成功,状态: {}", id, nonsense.getStatus());
|
||||||
|
return new ResponseMessage<>(200, "获取成功", nonsense, true);
|
||||||
|
} else {
|
||||||
|
logger.warn("未找到ID为{}的疯言疯语内容", id);
|
||||||
|
return new ResponseMessage<>(404, "未找到指定疯言疯语内容", null, false);
|
||||||
|
}
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
logger.error("根据ID查询疯言疯语内容失败,ID: {}", id, e);
|
||||||
|
return new ResponseMessage<>(500, "数据库查询异常", null, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("根据ID查询疯言疯语内容失败,ID: {}", id, e);
|
||||||
|
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseMessage<List<Nonsense>> getNonsenseByStatus(Integer status) {
|
||||||
|
try {
|
||||||
|
// 验证状态值是否有效
|
||||||
|
if (status < 0 || status > 2) {
|
||||||
|
logger.warn("无效的状态值: {}", status);
|
||||||
|
return new ResponseMessage<>(400, "无效的状态值,必须是0(未发表)、1(已发表)或2(已删除)", null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Nonsense> nonsenseList = nonsenseRepository.findByStatus(status);
|
||||||
|
// 根据状态过滤
|
||||||
|
return new ResponseMessage<>(200, "获取成功", nonsenseList, true);
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
logger.error("根据状态获取疯言疯语内容失败,状态: {}", status, e);
|
||||||
|
return new ResponseMessage<>(500, "数据库查询异常", null, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("根据状态获取疯言疯语内容失败,状态: {}", status, e);
|
||||||
|
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public ResponseMessage<Nonsense> updateNonsenseStatus(Integer id, Integer status) {
|
||||||
|
try {
|
||||||
|
// 验证状态值是否有效
|
||||||
|
if (status < 0 || status > 2) {
|
||||||
|
logger.warn("无效的状态值: {} 用于ID为{}的疯言疯语内容", status, id);
|
||||||
|
return new ResponseMessage<>(400, "无效的状态值,必须是0(未发表)、1(已发表)或2(已删除)", null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<Nonsense> nonsenseOptional = nonsenseRepository.findById(id);
|
||||||
|
if (nonsenseOptional.isPresent()) {
|
||||||
|
Nonsense nonsense = nonsenseOptional.get();
|
||||||
|
Integer oldStatus = nonsense.getStatus();
|
||||||
|
nonsense.setStatus(status);
|
||||||
|
|
||||||
|
Nonsense updatedNonsense = nonsenseRepository.save(nonsense);
|
||||||
|
logger.info("更新疯言疯语内容状态成功,ID: {}, 旧状态: {}, 新状态: {}", id, oldStatus, status);
|
||||||
|
return new ResponseMessage<>(200, "状态更新成功", updatedNonsense, true);
|
||||||
|
} else {
|
||||||
|
logger.warn("更新状态失败,未找到ID为{}的疯言疯语内容", id);
|
||||||
|
return new ResponseMessage<>(404, "未找到指定疯言疯语内容", null, false);
|
||||||
|
}
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
logger.error("更新疯言疯语内容状态失败,ID: {}, 状态: {}", id, status, e);
|
||||||
|
return new ResponseMessage<>(500, "数据库操作异常", null, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("更新疯言疯语内容状态失败,ID: {}, 状态: {}", id, status, e);
|
||||||
|
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public ResponseMessage<Nonsense> saveNonsense(NonsenseDto nonsenseDto) {
|
||||||
|
try {
|
||||||
|
Nonsense nonsense = new Nonsense();
|
||||||
|
BeanUtils.copyProperties(nonsenseDto, nonsense);
|
||||||
|
|
||||||
|
// 设置创建时间
|
||||||
|
if (nonsense.getTime() == null) {
|
||||||
|
nonsense.setTime(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置默认状态为未发表(0),如果DTO中未提供状态值
|
||||||
|
if (nonsense.getStatus() == null) {
|
||||||
|
nonsense.setStatus(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Nonsense savedNonsense = nonsenseRepository.save(nonsense);
|
||||||
|
logger.info("保存疯言疯语内容成功,ID: {}, 状态: {}", savedNonsense.getId(), savedNonsense.getStatus());
|
||||||
|
return new ResponseMessage<>(200, "保存成功", savedNonsense, true);
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
logger.error("保存疯言疯语内容失败", e);
|
||||||
|
return new ResponseMessage<>(500, "数据库操作异常", null, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("保存疯言疯语内容失败", e);
|
||||||
|
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public ResponseMessage<Nonsense> updateNonsense(Integer id, NonsenseDto nonsenseDto) {
|
||||||
|
try {
|
||||||
|
Optional<Nonsense> nonsenseOptional = nonsenseRepository.findById(id);
|
||||||
|
if (nonsenseOptional.isPresent()) {
|
||||||
|
Nonsense nonsense = nonsenseOptional.get();
|
||||||
|
// 只有当DTO中提供了status值时才更新
|
||||||
|
if (nonsenseDto.getStatus() != null) {
|
||||||
|
logger.info("更新疯言疯语内容状态,ID: {}, 新状态: {}", id, nonsenseDto.getStatus());
|
||||||
|
}
|
||||||
|
BeanUtils.copyProperties(nonsenseDto, nonsense, "id");
|
||||||
|
|
||||||
|
Nonsense updatedNonsense = nonsenseRepository.save(nonsense);
|
||||||
|
logger.info("更新疯言疯语内容成功,ID: {}, 当前状态: {}", id, updatedNonsense.getStatus());
|
||||||
|
return new ResponseMessage<>(200, "更新成功", updatedNonsense, true);
|
||||||
|
} else {
|
||||||
|
logger.warn("更新失败,未找到ID为{}的疯言疯语内容", id);
|
||||||
|
return new ResponseMessage<>(404, "未找到指定疯言疯语内容", null, false);
|
||||||
|
}
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
logger.error("更新疯言疯语内容失败,ID: {}", id, e);
|
||||||
|
return new ResponseMessage<>(500, "数据库操作异常", null, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("更新疯言疯语内容失败,ID: {}", id, e);
|
||||||
|
return new ResponseMessage<>(500, "服务器内部错误", null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public ResponseMessage<Boolean> deleteNonsense(Integer id) {
|
||||||
|
try {
|
||||||
|
if (nonsenseRepository.existsById(id)) {
|
||||||
|
// 先将状态设置为已删除(2)
|
||||||
|
Nonsense nonsense = nonsenseRepository.findById(id).get();
|
||||||
|
nonsense.setStatus(2);
|
||||||
|
nonsenseRepository.save(nonsense);
|
||||||
|
|
||||||
|
// 物理删除
|
||||||
|
// nonsenseRepository.deleteById(id);
|
||||||
|
logger.info("删除疯言疯语内容成功,ID: {}", id);
|
||||||
|
return new ResponseMessage<>(200, "删除成功", true, true);
|
||||||
|
} else {
|
||||||
|
logger.warn("删除失败,未找到ID为{}的疯言疯语内容", id);
|
||||||
|
return new ResponseMessage<>(404, "未找到指定疯言疯语内容", false, false);
|
||||||
|
}
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
logger.error("删除疯言疯语内容失败,ID: {}", id, e);
|
||||||
|
return new ResponseMessage<>(500, "数据库操作异常", false, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("删除疯言疯语内容失败,ID: {}", id, e);
|
||||||
|
return new ResponseMessage<>(500, "服务器内部错误", false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.qf.myafterprojecy.service;
|
package com.qf.myafterprojecy.service.impl;
|
||||||
|
|
||||||
import com.qf.myafterprojecy.config.ResponseMessage;
|
import com.qf.myafterprojecy.exceptopn.ResponseMessage;
|
||||||
import com.qf.myafterprojecy.pojo.Users;
|
import com.qf.myafterprojecy.pojo.Users;
|
||||||
import com.qf.myafterprojecy.pojo.dto.UserDto;
|
import com.qf.myafterprojecy.pojo.dto.UserDto;
|
||||||
import com.qf.myafterprojecy.repository.UsersRepository;
|
import com.qf.myafterprojecy.repository.UsersRepository;
|
||||||
import com.qf.myafterprojecy.service.imp.IUserService;
|
import com.qf.myafterprojecy.service.IUserService;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -147,7 +147,10 @@ public class UserService implements IUserService {
|
|||||||
// 更新用户信息
|
// 更新用户信息
|
||||||
BeanUtils.copyProperties(userDto, user);
|
BeanUtils.copyProperties(userDto, user);
|
||||||
|
|
||||||
// 保存更新后的用户
|
// 如果提供了新密码,则进行加密
|
||||||
|
if (userDto.getPassword() != null && !userDto.getPassword().isEmpty()) {
|
||||||
|
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||||
|
}
|
||||||
Users updatedUser = usersRepository.save(user);
|
Users updatedUser = usersRepository.save(user);
|
||||||
return ResponseMessage.update(true, updatedUser);
|
return ResponseMessage.update(true, updatedUser);
|
||||||
} catch (DataAccessException e) {
|
} catch (DataAccessException e) {
|
||||||
103
src/main/java/com/qf/myafterprojecy/utils/JwtUtils.java
Normal file
103
src/main/java/com/qf/myafterprojecy/utils/JwtUtils.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package com.qf.myafterprojecy.utils;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT工具类,用于生成和验证token
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JwtUtils {
|
||||||
|
|
||||||
|
@Value("${jwt.secret:default_secret_key_for_development}")
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
@Value("${jwt.expiration:86400000}")
|
||||||
|
private long expiration;
|
||||||
|
|
||||||
|
@Value("${jwt.token-prefix:Bearer}")
|
||||||
|
private String tokenPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从token中获取用户名
|
||||||
|
*/
|
||||||
|
public String getUsernameFromToken(String token) {
|
||||||
|
return getClaimFromToken(token, Claims::getSubject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从token中获取过期时间
|
||||||
|
*/
|
||||||
|
public Date getExpirationDateFromToken(String token) {
|
||||||
|
return getClaimFromToken(token, Claims::getExpiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从token中获取指定的claim
|
||||||
|
*/
|
||||||
|
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
|
||||||
|
final Claims claims = getAllClaimsFromToken(token);
|
||||||
|
return claimsResolver.apply(claims);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取token中的所有claims
|
||||||
|
*/
|
||||||
|
private Claims getAllClaimsFromToken(String token) {
|
||||||
|
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查token是否过期
|
||||||
|
*/
|
||||||
|
private Boolean isTokenExpired(String token) {
|
||||||
|
final Date expiration = getExpirationDateFromToken(token);
|
||||||
|
return expiration.before(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成token
|
||||||
|
*/
|
||||||
|
public String generateToken(UserDetails userDetails) {
|
||||||
|
Map<String, Object> claims = new HashMap<>();
|
||||||
|
claims.put("authorities", userDetails.getAuthorities());
|
||||||
|
return doGenerateToken(claims, userDetails.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成token的核心方法
|
||||||
|
*/
|
||||||
|
private String doGenerateToken(Map<String, Object> claims, String subject) {
|
||||||
|
return Jwts.builder()
|
||||||
|
.setClaims(claims)
|
||||||
|
.setSubject(subject)
|
||||||
|
.setIssuedAt(new Date(System.currentTimeMillis()))
|
||||||
|
.setExpiration(new Date(System.currentTimeMillis() + expiration))
|
||||||
|
.signWith(SignatureAlgorithm.HS512, secret)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证token
|
||||||
|
*/
|
||||||
|
public Boolean validateToken(String token, UserDetails userDetails) {
|
||||||
|
final String username = getUsernameFromToken(token);
|
||||||
|
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取token前缀
|
||||||
|
*/
|
||||||
|
public String getTokenPrefix() {
|
||||||
|
return tokenPrefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
68
src/main/resources/application-dev.properties
Normal file
68
src/main/resources/application-dev.properties
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# ====================================================================
|
||||||
|
# 开发环境配置文件
|
||||||
|
# 说明:此配置用于本地开发和调试,只包含开发环境特定配置
|
||||||
|
# 通用配置请参考主配置文件 application.properties
|
||||||
|
# ====================================================================
|
||||||
|
|
||||||
|
# 应用基本配置 - 开发特定
|
||||||
|
server.port=7071
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# 数据库与JPA配置 - 开发用
|
||||||
|
# ====================================================================
|
||||||
|
spring.datasource.url=jdbc:mysql://localhost:3306/webproject?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true
|
||||||
|
spring.datasource.username=root
|
||||||
|
spring.datasource.password=123456
|
||||||
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
|
||||||
|
# 数据库连接池配置(开发环境简化版)
|
||||||
|
spring.datasource.hikari.maximum-pool-size=5
|
||||||
|
spring.datasource.hikari.minimum-idle=2
|
||||||
|
|
||||||
|
# JPA配置(开发环境使用update以便自动创建/更新表结构)
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.jpa.show-sql=false
|
||||||
|
spring.jpa.properties.hibernate.format_sql=false
|
||||||
|
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# JWT 配置 - 开发用(方便调试,密钥较短,过期时间短)
|
||||||
|
# ====================================================================
|
||||||
|
jwt.secret=devSecretKey2024ForLocalDevelopment
|
||||||
|
jwt.expiration=3600000
|
||||||
|
# 1小时过期,方便调试
|
||||||
|
jwt.header=Authorization
|
||||||
|
jwt.token-prefix=Bearer
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# 安全与CORS配置 - 开发用
|
||||||
|
# ====================================================================
|
||||||
|
# CORS配置(开发环境允许所有本地前端访问)
|
||||||
|
cors.allowed-origins=http://localhost:3000,http://localhost:8080,http://localhost:5173
|
||||||
|
cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS
|
||||||
|
cors.allowed-headers=*
|
||||||
|
cors.allow-credentials=true
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# 日志配置 - 开发用(详细日志便于调试)
|
||||||
|
# ====================================================================
|
||||||
|
logging.level.root=INFO
|
||||||
|
logging.level.com.qf.myafterprojecy=DEBUG
|
||||||
|
logging.level.org.springframework=INFO
|
||||||
|
logging.level.org.hibernate.SQL=DEBUG
|
||||||
|
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# 开发环境特有配置
|
||||||
|
# ====================================================================
|
||||||
|
# 热部署配置
|
||||||
|
spring.devtools.restart.enabled=true
|
||||||
|
spring.devtools.restart.additional-paths=src/main/java
|
||||||
|
# 解决DevTools重启时丢失profile配置的问题
|
||||||
|
spring.devtools.restart.poll-interval=2s
|
||||||
|
spring.devtools.restart.quiet-period=1s
|
||||||
|
spring.devtools.restart.exclude=static/**,public/**
|
||||||
|
|
||||||
|
# Actuator配置(开发环境开放更多端点便于调试)
|
||||||
|
management.endpoints.web.exposure.include=*
|
||||||
|
management.endpoint.health.show-details=always
|
||||||
70
src/main/resources/application-prod.properties
Normal file
70
src/main/resources/application-prod.properties
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# ====================================================================
|
||||||
|
# 生产环境配置文件
|
||||||
|
# 说明:此配置用于生产环境部署,敏感信息从环境变量读取
|
||||||
|
# ====================================================================
|
||||||
|
|
||||||
|
# 应用基本配置 - 生产特定
|
||||||
|
server.port=7070
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# 数据库与JPA配置 - 生产用
|
||||||
|
# ====================================================================
|
||||||
|
spring.datasource.url=${DB_URL:jdbc:mysql://mysql:3306/webproject?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai}
|
||||||
|
spring.datasource.username=${DB_USERNAME:root}
|
||||||
|
spring.datasource.password=${DB_PASSWORD:root}
|
||||||
|
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||||
|
|
||||||
|
# 数据库连接池配置(生产环境优化版)
|
||||||
|
spring.datasource.hikari.maximum-pool-size=20
|
||||||
|
spring.datasource.hikari.minimum-idle=5
|
||||||
|
spring.datasource.hikari.idle-timeout=300000
|
||||||
|
spring.datasource.hikari.connection-timeout=20000
|
||||||
|
spring.datasource.hikari.max-lifetime=1200000
|
||||||
|
spring.datasource.hikari.connection-test-query=SELECT 1
|
||||||
|
spring.datasource.hikari.pool-name=WebProjectHikariCP
|
||||||
|
|
||||||
|
# JPA配置(生产环境禁用自动DDL,避免意外修改表结构)
|
||||||
|
spring.jpa.hibernate.ddl-auto=create
|
||||||
|
spring.jpa.show-sql=false
|
||||||
|
spring.jpa.properties.hibernate.format_sql=false
|
||||||
|
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
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# JWT 配置 - 生产用(敏感信息从环境变量读取)
|
||||||
|
# ====================================================================
|
||||||
|
jwt.secret=${JWT_SECRET:}
|
||||||
|
jwt.expiration=${JWT_EXPIRATION:86400000}
|
||||||
|
jwt.header=Authorization
|
||||||
|
jwt.token-prefix=Bearer
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# 安全与CORS配置 - 生产用
|
||||||
|
# ====================================================================
|
||||||
|
# CORS配置(生产环境限制为具体域名)
|
||||||
|
cors.allowed-origins=http://qf1121.top,https://qf1121.top,http://www.qf1121.top,https://www.qf1121.top
|
||||||
|
cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS
|
||||||
|
cors.allowed-headers=*
|
||||||
|
cors.allow-credentials=true
|
||||||
|
cors.max-age=3600
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# 日志配置 - 生产用(精简日志,提高性能)
|
||||||
|
# ====================================================================
|
||||||
|
logging.level.root=WARN
|
||||||
|
logging.level.com.qf.myafterprojecy=INFO
|
||||||
|
logging.level.org.springframework.security=WARN
|
||||||
|
logging.level.org.hibernate.SQL=ERROR
|
||||||
|
logging.file.name=logs/web_project.log
|
||||||
|
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
|
||||||
|
# ====================================================================
|
||||||
|
# API与应用配置 - 生产用
|
||||||
|
# ====================================================================
|
||||||
|
# Actuator配置(生产环境限制访问)
|
||||||
|
management.endpoints.web.exposure.include=health,info
|
||||||
|
management.endpoint.health.show-details=when_authorized
|
||||||
@@ -1,104 +1,43 @@
|
|||||||
# 应用服务 WEB 访问端口
|
# ====================================================================
|
||||||
server.port=8080
|
# 应用基本配置 - 通用配置
|
||||||
|
# ====================================================================
|
||||||
|
# 环境激活配置
|
||||||
|
# 说明:默认激活开发环境,生产环境部署时应通过命令行参数或环境变量覆盖
|
||||||
|
spring.profiles.active=dev
|
||||||
|
server.port=7070
|
||||||
|
# 应用名称(通用配置)
|
||||||
spring.application.name=web_project
|
spring.application.name=web_project
|
||||||
|
|
||||||
# 数据库配置
|
# ====================================================================
|
||||||
spring.datasource.url=jdbc:mysql://localhost:3306/webproject?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true
|
# 会话与编码配置 - 通用配置
|
||||||
spring.datasource.username=root
|
# ====================================================================
|
||||||
spring.datasource.password=123456
|
|
||||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
|
||||||
|
|
||||||
# 数据库连接池优化配置
|
|
||||||
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
|
|
||||||
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=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
|
|
||||||
# 暂时禁用Hibernate二级缓存和查询缓存
|
|
||||||
# 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=123456
|
|
||||||
spring.redis.database=0
|
|
||||||
spring.redis.timeout=10000ms
|
|
||||||
# Redis连接池优化配置
|
|
||||||
spring.redis.lettuce.pool.max-active=8
|
|
||||||
spring.redis.lettuce.pool.max-wait=10000ms
|
|
||||||
spring.redis.lettuce.pool.max-idle=8
|
|
||||||
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=health,info,metrics,prometheus
|
|
||||||
management.endpoint.health.show-details=when_authorized
|
|
||||||
management.metrics.export.prometheus.enabled=true
|
|
||||||
|
|
||||||
# JWT配置 - 生产环境应使用更安全的密钥和环境变量
|
|
||||||
jwt.secret=mySecretKey
|
|
||||||
jwt.expiration=86400000
|
|
||||||
jwt.header=Authorization
|
|
||||||
jwt.token-prefix=Bearer
|
|
||||||
|
|
||||||
# CORS配置 - 生产环境应限制允许的源
|
|
||||||
cors.allowed-origins=http://localhost:3000
|
|
||||||
cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS
|
|
||||||
cors.allowed-headers=*,
|
|
||||||
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.servlet.session.timeout=30m
|
||||||
server.session.tracking-modes=cookie
|
server.session.tracking-modes=cookie
|
||||||
|
|
||||||
# 国际化配置
|
# 国际化配置
|
||||||
spring.mvc.locale-resolver=fixed
|
|
||||||
spring.web.locale=zh_CN
|
spring.web.locale=zh_CN
|
||||||
#
|
spring.messages.encoding=UTF-8
|
||||||
## 响应编码配置
|
|
||||||
spring.http.encoding.charset=UTF-8
|
# 响应编码配置(通用,所有环境保持一致)
|
||||||
spring.http.encoding.enabled=true
|
server.servlet.encoding.charset=UTF-8
|
||||||
spring.http.encoding.force=true
|
server.servlet.encoding.force=true
|
||||||
|
server.servlet.encoding.force-request=true
|
||||||
|
server.servlet.encoding.force-response=true
|
||||||
|
server.servlet.encoding.enabled=true
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# API与应用配置 - 通用配置
|
||||||
|
# ====================================================================
|
||||||
|
# API 文档配置(通用)
|
||||||
|
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
|
||||||
|
|
||||||
|
# 应用性能优化配置(通用)
|
||||||
|
spring.main.allow-bean-definition-overriding=true
|
||||||
|
spring.main.lazy-initialization=false
|
||||||
|
|
||||||
|
# ====================================================================
|
||||||
|
# 说明:环境特定的配置(如数据库、JWT、CORS等)已移至对应的环境配置文件中
|
||||||
|
# - 开发环境:application-dev.properties
|
||||||
|
# - 生产环境:application-prod.properties
|
||||||
|
# ====================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user