Skip to content

Commit 5f873c0

Browse files
committed
refactor: optimization code structure for java
1 parent b30d5d9 commit 5f873c0

262 files changed

Lines changed: 14119 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
.idea
3+
*.iml
4+
5+
apache-tomcat-9.0.31
6+
res.hackyle.com
7+
nginx-1.20.2
8+
9+
*application-prod.yml
10+
11+
temp
12+
logs
13+
14+
# 排除所有.idea目录
15+
*.idea
16+
#排除所有target目录
17+
*target
18+
19+
# 排除vue相关目录
20+
*dist
21+
*node_modules

blog-admin/pom.xml

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.hackyle.blog</groupId>
8+
<artifactId>Blog</artifactId>
9+
<version>1.0.0</version>
10+
</parent>
11+
12+
<artifactId>blog-admin</artifactId>
13+
<packaging>war</packaging>
14+
15+
<properties>
16+
<java.version>17</java.version>
17+
<maven.compiler.source>17</maven.compiler.source>
18+
<maven.compiler.target>17</maven.compiler.target>
19+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
20+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
21+
</properties>
22+
23+
<dependencies>
24+
<dependency>
25+
<groupId>com.hackyle.blog</groupId>
26+
<artifactId>blog-common</artifactId>
27+
</dependency>
28+
29+
<!-- 获取系统信息 -->
30+
<dependency>
31+
<groupId>com.github.oshi</groupId>
32+
<artifactId>oshi-core</artifactId>
33+
</dependency>
34+
35+
<!-- Token生成与解析-->
36+
<dependency>
37+
<groupId>io.jsonwebtoken</groupId>
38+
<artifactId>jjwt</artifactId>
39+
</dependency>
40+
<dependency>
41+
<groupId>com.github.penggle</groupId>
42+
<artifactId>kaptcha</artifactId>
43+
</dependency>
44+
45+
<dependency>
46+
<groupId>org.springframework.boot</groupId>
47+
<artifactId>spring-boot-starter</artifactId>
48+
</dependency>
49+
<dependency>
50+
<groupId>org.springframework.boot</groupId>
51+
<artifactId>spring-boot-starter-web</artifactId>
52+
<exclusions>
53+
<exclusion>
54+
<groupId>org.springframework.boot</groupId>
55+
<artifactId>spring-boot-starter-tomcat</artifactId>
56+
</exclusion>
57+
</exclusions>
58+
</dependency>
59+
<!-- 引入 Tomcat 作为 provided(由外部容器提供) -->
60+
<dependency>
61+
<groupId>org.springframework.boot</groupId>
62+
<artifactId>spring-boot-starter-tomcat</artifactId>
63+
<scope>provided</scope>
64+
</dependency>
65+
66+
<dependency>
67+
<groupId>org.springframework.boot</groupId>
68+
<artifactId>spring-boot-starter-validation</artifactId>
69+
</dependency>
70+
<!--用于解析HTML-->
71+
<dependency>
72+
<groupId>org.jsoup</groupId>
73+
<artifactId>jsoup</artifactId>
74+
</dependency>
75+
<dependency>
76+
<groupId>org.springframework.boot</groupId>
77+
<artifactId>spring-boot-starter-aop</artifactId>
78+
</dependency>
79+
80+
<dependency>
81+
<groupId>mysql</groupId>
82+
<artifactId>mysql-connector-java</artifactId>
83+
</dependency>
84+
<dependency>
85+
<groupId>com.baomidou</groupId>
86+
<artifactId>mybatis-plus-boot-starter</artifactId>
87+
</dependency>
88+
89+
<dependency>
90+
<groupId>org.springframework.boot</groupId>
91+
<artifactId>spring-boot-starter-data-redis</artifactId>
92+
</dependency>
93+
94+
<dependency>
95+
<groupId>org.springframework.boot</groupId>
96+
<artifactId>spring-boot-starter-test</artifactId>
97+
</dependency>
98+
</dependencies>
99+
100+
101+
<build>
102+
<plugins>
103+
<!-- Spring Boot Maven Plugin,负责生成可执行 WAR -->
104+
<plugin>
105+
<groupId>org.springframework.boot</groupId>
106+
<artifactId>spring-boot-maven-plugin</artifactId>
107+
<version>2.7.18</version> <!-- 或你的 Spring Boot 版本 -->
108+
<!--配置springboot入口类-->
109+
<configuration>
110+
<fork>true</fork>
111+
<jvmArguments>Dfile.encoding=UTF-8</jvmArguments>
112+
<!--配置入口类的标签名-->
113+
<mainClass>com.hackyle.blog.admin.BlogAdminApp</mainClass>
114+
</configuration>
115+
</plugin>
116+
117+
<!--关键:升级到兼容 JDK 17/21 的 maven-war-plugin -->
118+
<plugin>
119+
<groupId>org.apache.maven.plugins</groupId>
120+
<artifactId>maven-war-plugin</artifactId>
121+
<version>3.3.2</version> <!-- 兼容 JDK 17+ 的版本 -->
122+
<configuration>
123+
<!-- 不自动打包 Spring Boot loader 文件(war 不需要) -->
124+
<failOnMissingWebXml>false</failOnMissingWebXml>
125+
</configuration>
126+
</plugin>
127+
128+
<!-- Maven Compiler,强制使用指定 JDK 版本 -->
129+
<plugin>
130+
<groupId>org.apache.maven.plugins</groupId>
131+
<artifactId>maven-compiler-plugin</artifactId>
132+
<version>3.11.0</version>
133+
<configuration>
134+
<source>${java.version}</source>
135+
<target>${java.version}</target>
136+
</configuration>
137+
</plugin>
138+
139+
</plugins>
140+
</build>
141+
142+
</project>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.hackyle.blog.admin;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.boot.builder.SpringApplicationBuilder;
6+
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
7+
8+
@SpringBootApplication
9+
public class BlogAdminApp extends SpringBootServletInitializer {
10+
/**
11+
* main() 仍然可用,用于本地开发运行
12+
* 当放进外部 Tomcat 时,会调用 configure()
13+
*/
14+
@Override
15+
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
16+
return builder.sources(BlogAdminApp.class);
17+
}
18+
19+
public static void main(String[] args) {
20+
SpringApplication.run(BlogAdminApp.class, args);
21+
}
22+
}
23+
24+
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package com.hackyle.blog.admin.handler;
2+
3+
import com.hackyle.blog.common.domain.ApiResponse;
4+
import com.hackyle.blog.common.exception.AuthenticationException;
5+
import com.hackyle.blog.common.exception.BizException;
6+
import com.hackyle.blog.common.exception.NotFoundException;
7+
import com.hackyle.blog.common.exception.PermissionException;
8+
import lombok.extern.slf4j.Slf4j;
9+
import org.springframework.http.HttpStatus;
10+
import org.springframework.web.bind.MethodArgumentNotValidException;
11+
import org.springframework.web.bind.annotation.ExceptionHandler;
12+
import org.springframework.web.bind.annotation.ResponseBody;
13+
import org.springframework.web.bind.annotation.ResponseStatus;
14+
import org.springframework.web.bind.annotation.RestControllerAdvice;
15+
16+
import javax.servlet.http.HttpServletRequest;
17+
import javax.validation.ConstraintViolation;
18+
import javax.validation.ConstraintViolationException;
19+
import java.util.stream.Collectors;
20+
21+
/**
22+
* 全局异常处理器
23+
* ControllerAdvice表示这是一个控制器增强类,当控制器发生异常且符合类中定义的拦截异常类,将会被拦截。
24+
* 在捕获异常时是按照异常方法的顺序依次捕获(类似于catch关键字后的捕获顺序),所以需要将顶级的异常放在最后
25+
* 注意:各个异常处理方法要同名,采取重载的形式
26+
*
27+
* IllegalArgumentException:参数错误,400
28+
* AuthenticationException:认证错误,401
29+
* PermissionException:权限错误,403
30+
* NotFoundException:资源不存在,404
31+
* BizException:业务异常,422,例如:用户名密码错误、库存不足
32+
* Exception、Error:500
33+
*/
34+
@RestControllerAdvice
35+
@Slf4j
36+
public class GlobalExceptionHandler {
37+
/**
38+
* 捕获参数校验注解失败抛出的异常:MethodArgumentNotValidException-Spring封装的参数验证异常处理
39+
* <p>MethodArgumentNotValidException:作用于 @Validated @Valid 注解,接收参数加上@RequestBody注解(json格式)才会有这种异常。</p>
40+
*
41+
* @param e MethodArgumentNotValidException异常信息
42+
* @return 响应数据
43+
*/
44+
@ResponseBody
45+
@ResponseStatus(HttpStatus.BAD_REQUEST)
46+
@ExceptionHandler(value = MethodArgumentNotValidException.class)
47+
public ApiResponse<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
48+
String msg = e.getBindingResult().getFieldErrors()
49+
.stream()
50+
.map(n -> String.format("%s: %s", n.getField(), n.getDefaultMessage()))
51+
.reduce((x, y) -> String.format("%s; %s", x, y))
52+
.orElse("参数输入有误");
53+
log.error("MethodArgumentNotValidException异常,参数校验异常:{}", msg);
54+
return ApiResponse.fail(HttpStatus.BAD_REQUEST.value(), msg);
55+
}
56+
57+
/**
58+
* 捕获参数校验注解失败抛出的异常:ConstraintViolationException-jsr规范中的验证异常,嵌套检验问题
59+
* <p>ConstraintViolationException:作用于 @NotBlank @NotNull @NotEmpty 注解,校验单个String、Integer、Collection等参数异常处理。</p>
60+
* <p>注:Controller类上必须添加@Validated注解,否则接口单个参数校验无效</p>
61+
*
62+
* @param e ConstraintViolationException异常信息
63+
* @return 响应数据
64+
*/
65+
@ResponseBody
66+
@ResponseStatus(HttpStatus.BAD_REQUEST)
67+
@ExceptionHandler(value = ConstraintViolationException.class)
68+
public ApiResponse<?> constraintViolationExceptionHandler(ConstraintViolationException e) {
69+
String msg = e.getConstraintViolations()
70+
.stream()
71+
.map(ConstraintViolation::getMessage)
72+
.collect(Collectors.joining("; "));
73+
74+
log.error("ConstraintViolationException,参数校验异常:{}", msg);
75+
return ApiResponse.fail(HttpStatus.BAD_REQUEST.value(), msg);
76+
}
77+
78+
@ResponseStatus(HttpStatus.BAD_REQUEST)
79+
@ResponseBody
80+
@ExceptionHandler(IllegalArgumentException.class)
81+
public ApiResponse<Exception> badRequestExceptionHandler(HttpServletRequest request, IllegalArgumentException exception) {
82+
log.error("出现IllegalArgumentException异常:", exception);
83+
return ApiResponse.fail(HttpStatus.BAD_REQUEST.value(), "参数错误");
84+
}
85+
86+
@ResponseStatus(HttpStatus.UNAUTHORIZED)
87+
@ResponseBody
88+
@ExceptionHandler(AuthenticationException.class)
89+
public ApiResponse<Exception> unauthorizedExceptionHandler(HttpServletRequest request, AuthenticationException exception) {
90+
log.error("出现AuthenticationException异常:", exception);
91+
return ApiResponse.fail(HttpStatus.UNAUTHORIZED.value(), "认证失败");
92+
}
93+
94+
@ResponseStatus(HttpStatus.FORBIDDEN)
95+
@ResponseBody
96+
@ExceptionHandler(PermissionException.class)
97+
public ApiResponse<Exception> permissionExceptionHandler(HttpServletRequest request, PermissionException exception) {
98+
log.error("出现PermissionException异常:", exception);
99+
return ApiResponse.fail(HttpStatus.FORBIDDEN.value(), "权限不足");
100+
}
101+
102+
@ResponseStatus(HttpStatus.NOT_FOUND)
103+
@ResponseBody
104+
@ExceptionHandler(NotFoundException.class)
105+
public ApiResponse<Exception> notFoundExceptionHandler(HttpServletRequest request, NotFoundException exception) {
106+
log.error("出现NotFoundException异常:", exception);
107+
return ApiResponse.fail(HttpStatus.NOT_FOUND.value(), "资源不存在");
108+
}
109+
110+
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
111+
@ResponseBody
112+
@ExceptionHandler(BizException.class)
113+
public ApiResponse<Exception> bizExceptionHandler(HttpServletRequest request, BizException exception) {
114+
log.error("出现BizException异常:", exception);
115+
return ApiResponse.fail(HttpStatus.UNPROCESSABLE_ENTITY.value(), exception.getMessage());
116+
}
117+
118+
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
119+
@ResponseBody
120+
@ExceptionHandler(Exception.class)
121+
public ApiResponse<Exception> exceptionHandler(HttpServletRequest request, Exception exception) {
122+
log.error("出现Exception异常:", exception);
123+
//不要直接把exception.getMessage()抛给前端,可能包含整个异常栈信息,造成信息泄露
124+
return ApiResponse.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "服务器内部错误");
125+
}
126+
127+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.hackyle.blog.admin.infrastructure.aop;
2+
3+
import org.springframework.context.annotation.Configuration;
4+
import org.springframework.context.annotation.EnableAspectJAutoProxy;
5+
6+
// 表示通过aop框架暴露该代理对象,AopContext能够访问
7+
@EnableAspectJAutoProxy(exposeProxy = true)
8+
@Configuration
9+
public class AopConfig {
10+
}

0 commit comments

Comments
 (0)