智能云盘

本文最后更新于:2024年6月21日 凌晨

前端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>
            <!-- Spring Boot 依赖 -->
            <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>
            <!-- Redis -->
            <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>
            <!-- mybatis-plus -->
            <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>
            <!-- 阿里JSON解析器 -->
            <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>
            <!-- io常用工具类 -->
            <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>
		<!-- Redis -->
		<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>
		<!-- mybatis-plus -->
		<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>
		<!-- mybatis-plus -->
		<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>
		<!-- io常用工具类 -->
		<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;
	// 验证码图片Buffer
	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;
		
		// 图像buffer
		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 = getFont(fontHeight);
		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(a, x, y);
			// a为要画的字,x为字的左下角的x坐标,y为字的左下角的y坐标
			
			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; // 50;
		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 {
	/**
	 * 是否需要登录
	 * @return
	 */
	boolean checkLogin() default false;
	
	/**
	 * 校验参数
	 * @return
	 */
	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;
}

智能云盘
https://junyyds.top/2023/07/26/智能云盘/
作者
Phils
发布于
2023年7月26日
更新于
2024年6月21日
许可协议