Java实现将文件(包括压缩包)、文件夹压缩成zip,并且压缩包里面保留文件夹结构
参考链接、参考链接 、参考链接
Java源码中有Files.copy(source, target, options)方法,options可以不传值。
例如:D:/a.txt文件要复制到E:/xx/b.txt中,先要得到得到两文件的path。
Ps:这里要求目标文件b.txt文件不存在(存在会报错),而且目标文件的路径必须要有,源代码方法中没有创建dir的方法。
参考代码如下:
//要确认拷贝的路径存在
File destDir = new File("E:/xx");
if(!(destDir.exists()&& destDir.isDirectory())) {
destDir.mkdirs();
}
File source = new File("D:/a.txt");
File dest = new File("E:/xx/b.txt");
try{
Files.copy(source.toPath(), dest.toPath());
} catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
方法一:
1、netstat -lntp
找到端口对应的应用的ID
2、ps -ef |grep 进程ID
方法二:
lsof -i:端口号
输出的列表的pid就是进程号
在Java的switch中使用枚举的code或者name会报错,必须使用枚举类。
需要在枚举类中加入一个根据编码获取枚举类的方法。
参考代码如下:
/**
* 审核状态枚举(预审页面)
*
* @author Chuenhung
* @date 2021/10/12
*/
public enum PreApprovalStatusEnum {
TO_APPROVAL("2", "待审核"),
REJECT("3", "已退回"),
AGREE("4", "审核通过");
private final String code;
private final String name;
PreApprovalStatusEnum(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
/**
* 根据编码获取枚举
*
* @param: code
* @return PreApprovalStatusEnum
* @author Chuenhung
* @date 2022/6/13
*/
public static PreApprovalStatusEnum getEnumByCode(String code) {
if (StringUtil.isNotEmpty(code)) {
for (PreApprovalStatusEnum enu : PreApprovalStatusEnum.values()) {
if (code.equals(enu.getCode())) {
return enu;
}
}
}
return null;
}
}
// switch case示例代码
switch (PreApprovalStatusEnum.getEnumByCode(status)){
case TO_APPROVAL:
break;
case REJECT:
break;
case AGREE:
break;
default:
}
Ps: case后面的枚举不能带类名,否则会报"An enum switch case label must be the unqualified name of an enumeration constant"错误。
参考链接
location /portal {
proxy_pass http://10.12.7.182:7001;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
client_max_body_size 1000m;
fastcgi_buffers 8 256k;
fastcgi_buffer_size 64k;
gzip on;
gzip_min_length 50k;
gzip_comp_level 5;
gzip_vary on;
}
该配置(portal、proxy_pass后面无/)举例:
原始请求链接:http://10.12.7.182:5001/portal/carousel/getList
实际请求链接:http://10.12.7.182:7001/portal/carousel/getList
location /portal/ {
proxy_pass http://10.12.7.182:7001/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
client_max_body_size 1000m;
fastcgi_buffers 8 256k;
fastcgi_buffer_size 64k;
gzip on;
gzip_min_length 50k;
gzip_comp_level 5;
gzip_vary on;
}
该配置(portal、proxy_pass后面有/)举例:
原始请求链接:http://10.12.7.182:5001/portal/carousel/getList
实际请求链接:http://10.12.7.182:7001/carousel/getList
参考代码如下:
location /proxy_reward/web/login/findemployeebyphone {
default_type application/json;
add_header Content-Type 'text/html; charset=utf-8';
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin *;
add_header Cache-Control public;
add_header Cache-Control max-age=300;
return 200 '{"status":"200","data":{"companyId":"1781","name":"张三","mobile":"12345678901","email":"123@163.com"}}';
}
参考代码如下:
upstream test{
server 192.168.0.1;
server 192.168.0.2;
}
server{
listen 80;
server_name test.com;
charset utf-8;
location /nacos {
proxy_pass http://test/;
}
}
刷新命令
git rm -r --cached .
git add .
提交代码命令
git commit -m "update .gitignore"
git push origin
要发布的事件:
@Getter
public class TransformDocEvent extends ApplicationEvent {
public TransformDocEvent(Object source) {
super(source);
}
}
发布事件:
applicationContext.publishEvent(new TransformDocEvent(doc));
处理事件:
@Component
@Slf4j
public class TransformDocListener {
@Async("MyThreadPool")
@EventListener
public void transform(TransformDocEvent event) {
}
}
1、按住CTRL键选取截取范围,再点击滚动条下面的向下箭头
2、点击鼠标左键即可自动捕捉窗口全部页面(适用于页面禁用滚动条的时候)
1、RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
2、调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。
3、ClientHttpRequestFactory接口主要提供了两种实现方式
RestTemplate的getForObject完成get请求、postForObject完成post请求、put对应的完成put请求、delete完成delete请求;还有execute可以执行任何请求的方法,需要你设置RequestMethod来指定当前请求类型。
示例代码:
// RestTemplate也可以通过@Autowired注入到Spring容器。
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
// 请求参数
Map<String, Object> map = new HashMap<>();
map.put("typeId",9);
map.put("dontQueryEmpty",true);
JSONObject jsonObj = new JSONObject(map);
HttpEntity<String> formEntity = new HttpEntity<String>(jsonObj.toString(), headers);
String url = "http://10.12.7.124:18081/manage/awards/querysecondclasslist";
String result = restTemplate.postForObject(url, formEntity, String.class);
如果直接使用在postForObject中把对象传入很容易出现no suitable HttpMessageConverter found for request type的错误,建议直接先转成字符串,见jsonObj.otString()。
使用RestTemplate调用接口确实非常优雅,几行代码就解决了。
建议合并前把本地分支的代码先提交到远程仓库,方便解决冲突
@Transactional与@Async同时使用事务会失效,在Transactional注解中的多线程也会导致事物失效
参考链接
事务失效问题解决:
方法一:@Async与@Transactional不使用在同一个方法上
方法二:手动提交事务及回滚事务
参考链接
方法三:将需要事务的方法放到另一个类中。
@Component
public class A {
@Resource
private B b;
@Async
public void test(){
b.dd();
}
}
@Component
public class B {
@Transactional
public void dd(){
}
}
经过测试,直接在service实现类的方法同时加两个注解,事务和多线程都不会失效。
achievementRepetitionService.checkAchievementRepetition();
@Override
@Transactional(rollbackFor = Exception.class)
@Async("RepetitionThreadPool")
public void checkAchievementRepetition() {
}
经过测试,service实现类的非异步方法调用异步方法,多线程失效,事务不会失效。
@Override
public void checkAchievementRepetition() {
insert();
}
@Async("RepetitionThreadPool")
public void insert(){
}
限流算法
总结
MediaType type = MediaType.parseMediaType(“application/json; charset=UTF-8”);
把charset=utf-8去掉就可以了,对方接口解析请求头有问题
思路:分批次查询(分页查询)+循环写入Excel,及时清理查询的list,防止OOM
1、查询出此次要导出的数据量count,根据count和自定义的每次查询数量size(我是10000)来计算出一共要查询n次。(防止一次查询数据量过大导致OOM)
2、循环n次,每次查询size大小的数据。然后导出到同一个sheet的excel中。注意,每次循环完clear掉list数据,防止占用内存
3、循环中会有一个问题,就是你在循环过程中别人新插入了数据怎么办,我的做法是最开始查询count的时候根据创建时间排序,获取最新的创建时间,然后后面的循环都使用这个创建时间作为搜索条件。这样就只会查询到和count相符合的数据了。
注意:导出数据超过6w条的时候excel格式要用xlsx。
参考链接、参考链接(含代码)、参考链接
思路:分批次写入数据库,及时清理读取的list,防止OOM
参考链接(含代码)
方法一:
第一步:开始菜单->运行->cmd->输入 wmic
第二步(方法一):
分别输入下面的命令:
wmic:root\cli>cpu get NumberOfCores
NumberOfCores
6
wmic:root\cli>cpu get NumberOfLogicalProcessors
NumberOfLogicalProcessors
12
第二步(方法二)
方法二:
在任务管理器中的性能页面中查看,如下图所示:

方法三:
运行dxdiag命令
1、物理CPU数
实际机器中插槽上的CPU个数,查询命令如下:
[award_dev@localhost ~]$ cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l
16
2、CPU核心数
一块物理CPU上能处理数据的芯片组数量。也就是说一个物理CPU上可能会有多个核心,日常中说的双核、四核就是指的CPU核心。查询命令如下:
[award_dev@localhost ~]$ cat /proc/cpuinfo |grep "cores"|uniq
cpu cores: 1
3、逻辑CPU的个数(线程数)
逻辑CPU数量=物理cpu数量 x CPU核心数 x 2(如果支持并开启ht)。
查询命令如下所示:
[award_dev@localhost ~]$ cat /proc/cpuinfo |grep "processor"|wc -l
16
从结果可以看出,我的机器不支持(或不开启)ht。
一般情况,我们认为一颗cpu可以有多核,加上intel的超线程技术(HT),可以在逻辑上再分一倍数量的cpu core出来;所以逻辑CPU的值理论上是可以超过100%的。
4、CPU数量及型号
[award_dev@localhost ~]$ cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
16 Intel(R) Xeon(R) Gold 5118 CPU @ 2.30GHz
5、查看当前操作系统内核信息
[award_dev@localhost ~]$ uname -a
Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
Ps:Linux下top查看的CPU也是逻辑CPU个数
一个CPU核可以执行一个线程,由英特尔开发超线程技术可以把一个线程模拟出两个线程来使用,使得单个核心用起来像两个核心一样,以充分发挥CPU的性能。
通常:逻辑CPU数量=物理cpu数量 x CPU核心数,若不相等则表示CPU支持超线程技术。