feat: 添加UTF-8编码支持并优化DTO验证

refactor: 重构用户服务密码更新逻辑
fix: 删除不再使用的MarkdownDto类
style: 清理日志文件并优化日志配置
build: 更新pom.xml配置以支持UTF-8编码
docs: 更新application.properties配置文档
This commit is contained in:
qingfeng1121
2025-10-30 19:00:47 +08:00
parent 5803080352
commit f6d1d719a9
18 changed files with 2778 additions and 729 deletions

View File

@@ -3,11 +3,40 @@ package com.qf.myafterprojecy;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.nio.charset.StandardCharsets;
/**
* 应用主类
* 设置系统编码并启动Spring Boot应用
*/
@SpringBootApplication
public class MyAfterProjecyApplication {
public static void main(String[] args) {
// 在应用启动前设置系统编码确保所有输出都使用UTF-8
setSystemEncoding();
// 启动Spring Boot应用
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());
}
}
}

View File

@@ -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;
}
}

View File

@@ -14,6 +14,7 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* Spring Security配置类
@@ -61,8 +62,10 @@ public class SecurityConfig {
.antMatchers(HttpMethod.GET,"/api/markdowns/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/articles/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/messages/**").permitAll()
.antMatchers(HttpMethod.GET,"/api/categories/**").permitAll()
// 公开post请求
.antMatchers(HttpMethod.POST,"/api/messages/**").permitAll()
.antMatchers(HttpMethod.POST,"/api/users/**").permitAll()
// 管理员才能访问的路径
.antMatchers("/api/admin/**").hasRole("ADMIN")
// 其他所有请求都需要认证
@@ -72,6 +75,15 @@ public class SecurityConfig {
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 确保Spring Security不会添加额外的CharacterEncodingFilter
// 因为我们在CharacterEncodingConfig中已经配置了自定义的过滤器
http.addFilterBefore((request, response, chain) -> {
// 确保响应使用UTF-8编码
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
chain.doFilter(request, response);
}, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}

View File

@@ -67,8 +67,7 @@ public class AuthController {
try {
// 创建认证令牌
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
// 执行认证
Authentication authentication = authenticationManager.authenticate(authenticationToken);
@@ -78,12 +77,11 @@ public class AuthController {
// 获取认证后的用户信息
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// 构建返回数据
Map<String, Object> data = new HashMap<>();
data.put("username", userDetails.getUsername());
data.put("authorities", userDetails.getAuthorities());
data.put("message", "登录成功");
// data.put("message", "登录成功");
return ResponseMessage.success(data, "登录成功");

View File

@@ -1,13 +1,10 @@
package com.qf.myafterprojecy.pojo.dto;
import lombok.Getter;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Getter
public class ArticleDto {
private Integer id;
private Integer articleid;
@NotBlank(message = "标题不能为空")
private String title;
@@ -19,17 +16,23 @@ public class ArticleDto {
private Integer attributeid;
private String img;
private Integer viewCount;
private Integer likes;
private Integer status;
// Getters and Setters
@NotBlank(message = "Markdown内容不能为空")
private String markdownscontent;
public Integer getId() {
return id;
// Getters and Setters
public Integer getArticleid() {
return articleid;
}
public void setId(Integer id) {
this.id = id;
public void setArticleid(Integer articleid) {
this.articleid = articleid;
}
public String getTitle() {
@@ -48,12 +51,12 @@ public class ArticleDto {
this.content = content;
}
public Integer getStatus() {
return status;
public Integer getAttributeid() {
return attributeid;
}
public void setStatus(Integer status) {
this.status = status;
public void setAttributeid(Integer attributeid) {
this.attributeid = attributeid;
}
public String getImg() {
@@ -63,4 +66,36 @@ public class ArticleDto {
public void setImg(String 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;
}
}

View File

@@ -4,6 +4,7 @@ import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
public class CategoryAttributeDto {
private Integer attributeid;
@NotNull(message = "分类ID不能为空")
private Integer categoryid;
@@ -12,6 +13,14 @@ public class CategoryAttributeDto {
private String attributename;
// Getters and Setters
public Integer getAttributeid() {
return attributeid;
}
public void setAttributeid(Integer attributeid) {
this.attributeid = attributeid;
}
public Integer getCategoryid() {
return categoryid;
}

View File

@@ -1,12 +1,18 @@
package com.qf.myafterprojecy.pojo.dto;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime;
public class CategoryDto {
private Integer typeid;
@NotBlank(message = "分类名称不能为空")
private String typename;
private String description;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
// Getters and Setters

View File

@@ -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;
}
}

View File

@@ -18,6 +18,8 @@ public class MessageDto {
private Integer replyid;
private Integer articleid;
private Integer likes;
public Integer getReplyid() {
return replyid;
@@ -26,6 +28,7 @@ public class MessageDto {
public void setReplyid(Integer replyid) {
this.replyid = replyid;
}
public Integer getMessageid() {
return messageid;
}
@@ -81,4 +84,12 @@ public class MessageDto {
public void setArticleid(Integer articleid) {
this.articleid = articleid;
}
public Integer getLikes() {
return likes;
}
public void setLikes(Integer likes) {
this.likes = likes;
}
}

View File

@@ -3,6 +3,8 @@ package com.qf.myafterprojecy.pojo.dto;
import javax.validation.constraints.NotBlank;
public class UserDto {
private Long id;
@NotBlank(message = "用户名不能为空")
private String username;
@@ -15,9 +17,16 @@ public class UserDto {
@NotBlank(message = "手机号不能为空")
private String phone;
@NotBlank(message = "角色不能为空")
private int role;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
@@ -57,5 +66,4 @@ public class UserDto {
public void setRole(int role) {
this.role = role;
}
}

View File

@@ -147,7 +147,10 @@ public class UserService implements IUserService {
// 更新用户信息
BeanUtils.copyProperties(userDto, user);
// 保存更新后的用户
// 如果提供了新密码,则进行加密
if (userDto.getPassword() != null && !userDto.getPassword().isEmpty()) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
}
Users updatedUser = usersRepository.save(user);
return ResponseMessage.update(true, updatedUser);
} catch (DataAccessException e) {

View File

@@ -0,0 +1,38 @@
// package com.qf.myafterprojecy.util;
// import org.slf4j.Logger;
// import org.slf4j.LoggerFactory;
// import org.springframework.stereotype.Component;
// import javax.annotation.PostConstruct;
// /**
// * 编码测试工具类
// * 用于验证系统编码配置是否正确,解决中文乱码问题
// */
// @Component
// public class EncodingTestUtil {
// private static final Logger logger = LoggerFactory.getLogger(EncodingTestUtil.class);
// /**
// * 在Bean初始化时执行编码测试
// * 验证日志系统是否能正确输出中文
// */
// @PostConstruct
// public void testEncoding() {
// // 输出系统编码信息
// logger.info("===== 系统编码测试开始 =====");
// logger.info("默认字符编码: {}", java.nio.charset.Charset.defaultCharset());
// logger.info("file.encoding: {}", System.getProperty("file.encoding"));
// logger.info("sun.stdout.encoding: {}", System.getProperty("sun.stdout.encoding"));
// logger.info("sun.stderr.encoding: {}", System.getProperty("sun.stderr.encoding"));
// // 测试中文字符输出
// logger.info("中文测试 - 这是一条测试日志,用于验证中文是否正常显示");
// logger.warn("中文警告测试 - 这是一条警告日志,用于验证中文是否正常显示");
// logger.error("中文错误测试 - 这是一条错误日志,用于验证中文是否正常显示");
// logger.info("===== 系统编码测试结束 =====");
// }
// }