请注意,本文编写于 507 天前,最后修改于 440 天前,其中某些信息可能已经过时。
1、大文件上传到本地
1.1、前期准备
1.1.1、自定义starter
- 前往gitee仓库拉取项目,https://gitee.com/feege/spring-boot-starter-upload,用IDEA克隆这个项目并打开。
- 首先需要检查maven环境,其次找到
FileServiceAutoConfigurationProperties
这个类,修改如下:
- 紧接着在install安装到本地,复制当前项目的坐标去目标项目,导入依赖
1.1.2、配置文件
pom.xml依赖
<dependencies>
<!--使用本地仓库的upload-->
<dependency>
<groupId>com.llh</groupId>
<artifactId>JavaHighFive-file-upload</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
application.yml配置
server:
port: 9203
spring:
application:
name: llh-upload # 注册导eureka上面的应用名称
# 文件大小设置
servlet:
multipart:
enabled: true
max-file-size: 1024MB
max-request-size: 1024MB
# 大文件上传配置
llh:
file:
enable: true
path: D:\IJ_files\JavaHighFive\upload\
domain: http://localhost:${server.port}/
MyMvcConfig.java配置类
package com.llh.config;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* User: lilinhan
* DateTime: 2023/11/16 15:52
*/
@SpringBootConfiguration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/file/**")
.addResourceLocations("file:D:\\IJ_files\\JavaHighFive\\upload\\");
}
/**
* 跨域问题配置
*
* @return
*/
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").
allowedOrigins("*"). //允许跨域的域名,可以用*表示允许任何域名使用
allowedMethods("*"). //允许任何方法(post、get等)
allowedHeaders("*"). //允许任何请求头
allowCredentials(true). //带上cookie信息
exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
}
};
}
}
1.2、编写接口
UploadController.java控制层
package com.llh.controller;
import com.llh.upload.model.Chunk;
import com.llh.upload.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
/**
* User: lilinhan
* DateTime: 2023/11/16 14:56
*/
@CrossOrigin
@RestController
@RequestMapping("/file")
@Slf4j
public class UploadController {
@Autowired
FileService fileService;
@RequestMapping("/test")
public void test(@RequestBody Integer[] ids){
System.err.println(Arrays.toString(ids));
}
// 大文件上传
@RequestMapping("/upload")
public String bigFile(@ModelAttribute Chunk chunk) throws InterruptedException {
fileService.postFileUpload(chunk);
if (chunk.getTotalChunks().equals(chunk.getChunkNumber())) {
Thread.sleep(2000);
fileService.mergeFile(chunk);
return "文件合并";
}
log.info("文件上传成功");
return "success!!";
}
}
1.3、前端页面
- 打开vue-uploader的GitHub仓库:https://github.com/simple-uploader/vue-uploader/blob/HEAD/README_zh-CN.md,找到这个命令执行:
npm install vue-simple-uploader
,npm install spark-md5
UploadView.vue
<script>
export default {
data(){
return{
options: {
target: 'http://localhost:9203/file/upload', // 目标上传 URL
chunkSize: '2048000', //分块大小
fileParameterName: 'file', //上传文件时文件的参数名,默认file
maxChunkRetries: 3, //最大自动失败重试上传次数
testChunks: false, //是否开启服务器分片校验
},
attrs: {
accept: 'image/*'
}
}
},
methods:{
onFileAdded(file){
const fileReader = new FileReader()
fileReader.readAsBinaryString(file);
fileReader.onload = e => {
const md5 = SparkMD5.hashBinary(e.target.result);
console.log(md5);
file.uniqueIdentifier = md5;
}
}
}
}
</script>
<template>
<div>
<uploader :options="options" @file-added="onFileAdded" class="uploader-example">
<uploader-unsupport></uploader-unsupport>
<uploader-drop>
<p>Drop files here to upload or</p>
<uploader-btn id="global-uploader-btn">选择文件</uploader-btn>
</uploader-drop>
<uploader-list></uploader-list>
</uploader>
</div>
</template>
<style scoped>
.uploader-example {
width: 880px;
padding: 15px;
margin: 40px auto 0;
font-size: 12px;
box-shadow: 0 0 10px rgba(0, 0, 0, .4);
}
.uploader-example .uploader-btn {
margin-right: 4px;
}
.uploader-example .uploader-list {
max-height: 440px;
overflow: auto;
overflow-x: hidden;
overflow-y: auto;
}
</style>
1.4、部分效果
- 上传成功
2、PDF 相关操作
2.1、前期准备
2.1.1、自定义starter
- 前往gitee仓库拉取项目,https://gitee.com/feege/itext7-spring-boot-starter.git,用IDEA克隆这个项目并打开。
- 首先需要检查maven环境,其次找到
PdfAutoConfigurationProperties
这个类,修改如下:
- 紧接着在install安装到本地,复制当前项目的坐标去目标项目,导入依赖
2.1.2、生成签名文件
- 通过命令行cmd进入jdk的bin目录下,会发现有一个keytool.exe文件
- 执行命令:
keytool -genkey -alias house.keystore -keyalg RSA -validity 10000 -keystore D:\IJ_files\JavaHighFive\pdf\ks\house.keystore
解释如下:
-alias后面的参数test.keystore是要生成的文件名称
-validity后的参数10000是这个keystore的有效时间
-keystore后的参数D:\IJ_files\JavaHighFive\pdf\ks\house.keystore是文件路径,名称最好与前面-alias的参数保持一致
2.1.3、印章和字体
- 字体后续会放在服务器以附件形式下载。。。
- 印章:
2.1.4、配置文件
pom.xml依赖
<dependencies>
<!--spring web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--使用本地仓库的pdf-->
<dependency>
<groupId>com.llh</groupId>
<artifactId>JavaHighFive-pdf</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.yml配置
server:
port: 9201
spring:
application:
name: llh-pdf # 注册导eureka上面的应用名称
redis:
host: localhost
port: 6379
# pdf配置
llh:
pdf:
enable: true
domain: http://localhost:${server.port}/
pdf-ks: D:\IJ_files\JavaHighFive\pdf\ks\house.keystore
pdf-ks-pass: 123456
x: 400
y: 400
width: 100
height: 100
sign-pic-name: sign.png
path: D:\IJ_files\JavaHighFive\pdf\
font: D:\IJ_files\JavaHighFive\pdf\font\simsun.ttc
2.2、编写接口
PdfController.java控制层
package com.llh.controller;
import cn.hutool.bloomfilter.BitMapBloomFilter;
import com.llh.domain.House;
import com.llh.itext.pdf.service.PdfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* User: lilinhan
* DateTime: 2023/11/15 11:18
*/
@CrossOrigin
@RestController
@RequestMapping("/pdf")
public class PdfController {
@Autowired
private PdfService pdfService;
@Autowired
HttpServletResponse response;
@Autowired
RedisTemplate redisTemplate;
@RequestMapping("/house")
public List<House> house(String userKey){
House house = new House();
house.setId(1);
house.setAddress("北京市");
house.setCommunity("环境优美");
House house1 = new House();
house1.setId(2);
house1.setAddress("天津市");
house.setCommunity("环境优美");
// 使用布隆过滤器 过滤掉没用的请求(不包含redis的key)
// 初始化
int size = 100;
BitMapBloomFilter filter = new BitMapBloomFilter(size);
filter.add("house");
if(filter.contains(userKey)){
// 查询redis是否存在
List<House> houseList = redisTemplate.opsForList().range(userKey, 0, -1);
if(houseList!=null && houseList.size()>0){
System.err.println("查询的redis");
return houseList;
}
// 存入redis
List<House> listDB = Arrays.asList(house, house1);
redisTemplate.opsForList().leftPushAll(userKey, listDB);
System.err.println("查询的mysql");
return listDB;
}
return null;
}
// 生成pdf并且盖章
@RequestMapping("/test")
public void test() throws IOException {
List<House> list = new ArrayList<>();
House house = new House();
house.setId(1);
house.setAddress("北京市");
house.setCommunity("环境优美");
list.add(house);
House house1 = new House();
house1.setId(2);
house1.setAddress("天津市");
house.setCommunity("环境优美");
list.add(house);
// 生成pdf
pdfService.export(list,"house.pdf","导出demo",House.class);
// 电子签章
pdfService.sign("house.pdf","house.sign.pdf");
}
// 下载pdf
@RequestMapping("/down")
public void down() throws FileNotFoundException {
pdfService.download("house.sign.pdf",response);
}
// 预览pdf
@RequestMapping("/preview")
public void preview() throws IOException {
pdfService.preview("house.sign.pdf",response);
}
}
2.3、前端页面
PdfView.vue
<script>
export default {
data(){
return{
checkList:[],
}
},
methods:{
test(){
alert(this.checkList)
this.axios.post("http://localhost:9203/file/test",this.checkList).then(()=>{})
},
sheng(){
this.axios.get("http://localhost:9201/pdf/test").then(()=>{})
},
preview(){
window.location.href="http://localhost:9201/pdf/preview";
},
down(){
window.location.href="http://localhost:9201/pdf/down";
}
}
}
</script>
<template>
<div>
<el-button type="info" @click="sheng">生成pdf</el-button>
<el-button type="info" @click="preview">预览pdf</el-button>
<el-button type="info" @click="down">下载pdf</el-button>
<br>
<el-checkbox-group v-model="checkList">
<el-checkbox label="1">复选框 A</el-checkbox>
<el-checkbox label="2">复选框 B</el-checkbox>
<el-checkbox label="3">复选框 C</el-checkbox>
</el-checkbox-group>
<el-button type="warning" @click="test">测试数组</el-button>
</div>
</template>
<style scoped>
</style>
2.4、部分效果
- 生成PDF
- 预览PDF
- 下载PDF
3、xxl-job 定时任务
3.1、前期准备
3.1.1、自定义starter
- 前往gitee仓库拉取项目,https://gitee.com/xuxueli0323/xxl-job.git,先创建名为xxl-job的数据库,编码格式最好为utf8mb4,导入项目中doc>db>tables_xxl-job.mql文件
- 单独把xxl-job-admin这个模块分离出来,用IDEA打开
- 修改
application.properties
配置里的端口号、数据源、邮箱。需要主要的是,这里使用的是普通的mybatis,而不是加强版mybatis-plus - 修改logback.xml的存储位置
- 紧接着在install安装到本地,复制当前项目的坐标去目标项目,导入依赖
- 为了方便启动xxl-job服务,手写个bat文件快速启动
cd /d D:\Maven_Git\com\llh\xxl-job-admin\1.0-SNAPSHOT
cmd /k java -jar xxl-job-admin-1.0-SNAPSHOT.jar
3.1.2、配置文件
pom.xml依赖
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--spring web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.4.0</version>
</dependency>
</dependencies>
application.yml配置
server:
port: 9206
# xxl-job 配置
xxl:
job:
admin:
# 调度中心地址
addresses: http://127.0.0.1:8777/xxl-job-admin
accessToken: default_token
executor:
appname: testTask # 执行器AppName
port: 9000 # 执行器端口
ip:
address:
logpath: D:/logs
logretentiondays: 30
XxlJobConfig.java配置类
package com.llh.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* xxl-job config
*
* @author xuxueli 2017-04-28
*/
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.appname}")
private String appname;
@Value("${xxl.job.executor.address}")
private String address;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
/**
* 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;
*
* 1、引入依赖:
* <dependency>
* <groupId>org.springframework.cloud</groupId>
* <artifactId>spring-cloud-commons</artifactId>
* <version>${version}</version>
* </dependency>
*
* 2、配置文件,或者容器启动变量
* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
*
* 3、获取IP
* String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
*/
}
3.2、编写定时器
MyTask.java定时器
package com.llh.job;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.stereotype.Component;
/**
* User: lilinhan
* DateTime: 2023/11/27 13:41
*/
@Component
public class MyTask {
@XxlJob("test")
public void test(){
int num=1;
num++;
System.err.println("开始执行了---"+num);
}
}
- 双击刚刚创建的bat文件,在浏览器输入:
http://localhost:8777/xxl-job-admin
进入后台管理 - 先创建执行器,这里的AppName是yml文件设置的
testTask
,建议是手动录入,自动注册第一次执行需要带上执行器地址,端口号是yml文件设置的9000
- 创建执行器
- 接着新建个任务,选择刚刚创建的执行器,描述负责人随便填,Cron表达式选对就行,JobHandler必须和注解里值保持一致
- 创建新任务
3.3、部分效果
- 执行一次
- 启动任务
96 comments
不良千金
情感真挚自然,字里行间传递出强烈的感染力。
情感真挚自然,字里行间传递出强烈的感染力。
作者以简洁明了的语言,传达了深刻的思想和情感。
反驳对手观点时需更注重逻辑严密性。
段落衔接自然,过渡流畅,读来一气呵成。
反驳对手观点时需更注重逻辑严密性。
情感真挚自然,字里行间传递出强烈的感染力。
立意高远,以小见大,引发读者对社会/人性的深层共鸣。
这是一篇佳作,无论是从内容、语言还是结构上,都堪称完美。
技术伦理的探讨体现人文科技平衡意识。
作者的情感表达细腻入微,让人在阅读中找到了心灵的慰藉。
这篇文章如同一幅色彩斑斓的画卷,每一笔都充满了独特的创意。
情感真挚自然,字里行间传递出强烈的感染力。
文章深入浅出,既有深度思考,又不乏广度覆盖,令人叹为观止。
独特的构思和新颖的观点,让这篇文章在众多作品中脱颖而出。
隐喻层次丰富,留给读者想象空间。
场景转换稍显突兀,可增加过渡描写。
文章的叙述风格独特,用词精准,让人回味无穷。
哈哈哈,写的太好了https://www.lawjida.com/