前端Vue
前端使用vue3,vite构建,UI使用elementplus
后端SpringBoot
创建多模块的SpringBoot项目,下面是层级结构:
- cloud
- cloud-admin
- (cloud-admin)pom.xml (子)
- cloud-common
- (cloud-common)pom.xml (子)
- pom.xml (父)
(父)pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.juncloud</groupId> <artifactId>juncloud</artifactId> <version>1.0</version>
<name>juncloud</name> <description>智能云盘</description> <properties> <java.version>1.8</java.version> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.encoding>UTF-8</maven.compiler.encoding> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.7.14</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.7.13</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> <version>8.0.33</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <version>1.18.28</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.7.13</version> </dependency> <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> <version>2.7.13</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency> <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>2.0.35</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.13.0</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.11</version> </dependency> <dependency> <groupId>com.juncloud</groupId> <artifactId>juncloud-admin</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>com.juncloud</groupId> <artifactId>juncloud-common</artifactId> <version>1.0</version> </dependency> </dependencies> </dependencyManagement>
<modules> <module>juncloud-admin</module> <module>juncloud-common</module> </modules> <packaging>pom</packaging>
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.7.14</version> <configuration> <mainClass>com.juncloud.admin.JuncloudApplication</mainClass> </configuration> </plugin> </plugins> </build> </project>
|
(cloud-admin)pom.xml
(子)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>com.juncloud</groupId> <artifactId>juncloud</artifactId> <version>1.0</version> </parent>
<modelVersion>4.0.0</modelVersion> <packaging>jar</packaging> <artifactId>juncloud-admin</artifactId> <version>1.0</version> <name>juncloud-admin</name>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>com.juncloud</groupId> <artifactId>juncloud-common</artifactId> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.7.14</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
|
(cloud-common)pom.xml
(子)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.juncloud</groupId> <artifactId>juncloud</artifactId> <version>1.0</version> </parent> <groupId>com.juncloud</groupId> <artifactId>juncloud-common</artifactId> <version>1.0</version> <name>juncloud-common</name> <properties> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> </dependency> <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|
验证码
创建CreateImageCode.java
,进行绘制图片
public class CreateImageCode { private int width = 160; private int height = 40; private int codeCount = 5; private int lineCount = 150; private String code = null; private BufferedImage bufferImg = null; Random random = new Random(); public CreateImageCode() { creatImage(); } public CreateImageCode(int width, int height) { this.width = width; this.height = height; creatImage(); } public CreateImageCode(int width, int height, int codeCount) { this.width = width; this.height = height; this.codeCount = codeCount; creatImage(); } public CreateImageCode(int width, int height, int codeCount, int lineCount) { this.width = width; this.height = height; this.codeCount = codeCount; this.lineCount = lineCount; creatImage(); } private void creatImage() { int fontWidth = width / codeCount; int fontHeight = height - 5; int codeY = height - 8; bufferImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = bufferImg.getGraphics(); g.setColor(getRandColor(200, 250)); g.fillRect(0, 0, width, height);
Font font = new Font("Fixedsys", Font.BOLD, fontHeight); g.setFont(font); for (int i = 0; i < lineCount; i++) { int xs = random.nextInt(width); int ys = random.nextInt(height); int xe = xs + random.nextInt(width); int ye = ys + random.nextInt(height); g.setColor(getRandColor(1, 255)); g.drawLine(xs, ys, xe, ye); } float yawpRate = 0.10f; int area = (int) (yawpRate * width * height); for (int i = 0; i < area; i++) { int x = random.nextInt(width); int y = random.nextInt(height); bufferImg.setRGB(x, y, random.nextInt(255)); } String str1 = randomStr(codeCount); this.code = str1; for (int i = 0; i < codeCount; i++) { String strRand = str1.substring(i, i + 1); g.setColor(getRandColor(1, 255)); g.drawString(strRand, i * fontWidth + 3, codeY); } } private String randomStr(int n) { String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; String str2 = ""; int len = str1.length() - 1; double r; for (int i = 0; i < n; i++) { r = (Math.random()) * len; str2 = str2 + str1.charAt((int) r); } return str2; } private Color getRandColor(int fc, int bc) { if (fc > 255) fc = 255; if (bc > 255) bc = 255; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } private void shearY(Graphics g, int w1, int h1, Color color) { int period = random.nextInt(40) + 10; boolean borderGap = true; int frames = 20; int phase = 7; for (int i = 0; i < h1; i++) { double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); g.copyArea(i, 0, 1, h1, 0, (int) d); if (borderGap) { g.setColor(color); g.drawLine(i, (int) d, i, 0); g.drawLine(i, (int) d + h1, i, h1); } } } public void write(OutputStream sos) throws IOException { ImageIO.write(bufferImg, "png", sos); sos.close(); } public BufferedImage getBuffImg() { return bufferImg; } public String getCode() { return code.toLowerCase(); } }
|
使用时:
@GetMapping("/checkCode") public void checkCode(HttpServletResponse response, HttpSession session, Integer type) throws IOException { CreateImageCode createImageCode = new CreateImageCode(130, 38, 5, 20); response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); String code = createImageCode.getCode(); if (type == null || type == 0) { session.setAttribute(Constants.CHECK_CODE_KEY, code); } else { session.setAttribute(Constants.CHECK_CODE_KEY_EMAIL, code); } createImageCode.write(response.getOutputStream()); }
|
当我们需要验证用户传回的验证码是否正确时:(下面是一个示例)
@PostMapping("/sendEmailCode") @GlobalInterceptor(checkParams = true) public AjaxResult sendEmailCode(HttpSession session, @VerifyParam(required = true, regex = VeriyfRegexEnum.EMAIL, max = 150) String email, @VerifyParam(required = true) String checkCode, @VerifyParam(required = true) Integer type) { try { if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY_EMAIL))) { return AjaxResult.error("图片验证码不正确"); } userInfoService.sendEmailCode(email, type); } finally { session.removeAttribute(Constants.CHECK_CODE_KEY_EMAIL); } return AjaxResult.success("发送成功"); }
|
aop实现参数校验
引入切片依赖
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency>
|
新建包annotation
,在annotation
包中,创建GlobalInterceptor.java
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface GlobalInterceptor {
boolean checkLogin() default false;
boolean checkParams() default false;
}
|
新建包aspect
,在aspect
包中,新建GlobalOperationAspect.java
使用只需要在需要校验的接口添加@GlobalInterceptor
即可,如下示例:
@PostMapping("/sendEmailCode") @GlobalInterceptor(checkParams = true) public AjaxResult sendEmailCode(HttpSession session, String email, String checkCode, Integer type) { try { if (!checkCode.equalsIgnoreCase((String) session.getAttribute(Constants.CHECK_CODE_KEY_EMAIL))) { return AjaxResult.error("图片验证码不正确"); } emailCodeService.sendEmailCode(email, type); } finally { session.removeAttribute(Constants.CHECK_CODE_KEY_EMAIL); } return AjaxResult.success("发送成功"); }
|
文件上传
@PostMapping("/uploadFile") @GlobalInterceptor(checkParams = true) public AjaxResult uploadFile(HttpSession session, Integer fileId, MultipartFile file, @VerifyParam(required = true) String fileName, @VerifyParam(required = true) String filePid, @VerifyParam(required = true) String fileMd5, @VerifyParam(required = true) Integer chunkIndex, @VerifyParam(required = true) Integer chunks){ SessionWebUserDto webUserDto = getUserInfoFromSession(session); UploadResultDto resultDto = fileInfoService.uploadFile(webUserDto, fileId, file, fileName, filePid, fileMd5, chunkIndex, chunks); return AjaxResult.success(resultDto); }
|
服务器部署
前端nginx
nginx配置
server { listen 80; server_name junyyds.top; index index.php index.html index.htm default.php default.htm default.html; root /workspace/JunCloud/juncloud-ui/dist;
#SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则 #error_page 404/404.html; #SSL-END
#ERROR-PAGE-START 错误页配置,可以注释、删除或修改 #error_page 404 /404.html; #error_page 502 /502.html; #ERROR-PAGE-END
#PHP-INFO-START PHP引用配置,可以注释或修改 include enable-php-00.conf; #PHP-INFO-END
#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效 include /www/server/panel/vhost/rewrite/junyyds.top.conf; #REWRITE-END
#禁止访问的文件或目录 location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md) { return 404; }
#一键申请SSL证书验证目录相关设置 location ~ \.well-known{ allow all; }
#禁止在证书验证目录放入敏感文件 if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) { return 403; } location / { index /data/dist/index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://localhost:9090/api; proxy_set_header x-forwarded-for $remote_addr; }
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; error_log /dev/null; access_log /dev/null; }
location ~ .*\.(js|css)?$ { expires 12h; error_log /dev/null; access_log /dev/null; } access_log /www/wwwlogs/junyyds.top.log; error_log /www/wwwlogs/junyyds.top.error.log; }
|