派大星的博客

很多事情不是会了才能做,而是做了才能学会


  • 首页

  • 标签

  • 分类

  • 关于

  • 搜索

基于Mysql实现锁机制

发表于 2019-07-16 | 分类于 Java,mysql

1 ReentrantLock

它是一个可重入锁,即一个线程可重复加锁,即当前线程获取该锁再次获取不会被阻塞。获得几次锁,解锁也要解几次。
它有两种实现,公平锁和非公平锁。

  • 公平锁:锁的获取顺序就应该符合请求上的绝对时间顺序
  • 非公平锁:不按请求的时间,谁抢到就是谁的

默认实现的为非公平锁,因为公平锁为了保证时间上的绝对顺序,需要频繁的上下文切换,而非公平锁会降低一定的上下文切换,降低性能开销。

1
2
//创建一个公平锁
Lock lock = new ReentrantLock(true);

2. 通过MySQL的GET_LOCK函数实现

获得锁

1
GET_LOCK(str,timeout)

根据字符串str 得到一个锁,超时为timeout 秒。若成功得到锁,则返回 1,若操作超时则返回0 ,当它获得锁之后,后面相同str的再获取这把锁就会一直等待,当超过timeout,就会返回0

释放锁

1
RELEASE_LOCK(str);

释放str这把锁,当连接中断后,这把锁也会释放的

使用

1
2
3
4
5
获取锁
SELECT GET_LOCK("pibigstar",10);

释放锁
SELECT RELEASE_LOCK(“pibigstar”);

3 通过MySQL行级锁进行实现

原理很简单,我们插入数据的时候都是只能插入一个唯一主键,如果有一个线程插入了,那么其他线程都不能插入了。

插入实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.pibigstar.domain;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Mysql {
@Id
private int id;
public Mysql(int id) {
this.id = id;
}
//setter、getter方法

}

dao层:使用jpa

1
2
3
4
5
6
7
8
9
package com.pibigstar.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import com.pibigstar.domain.Mysql;

public interface MysqlLockDao extends JpaRepository<Mysql, Integer>{

}

具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.pibigstar.utils;

import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import org.springframework.beans.factory.annotation.Autowired;
import com.pibigstar.dao.MysqlLockDao;
import com.pibigstar.domain.Mysql;

/**
* 基于mysql实现可重入锁
* @author pibigstar
*
*/
public class MysqlLock implements Lock{

@Autowired
private MysqlLockDao mysqlLockDao;

private static final Mysql my = new Mysql(1);

@Override
public void lock() {
//阻塞锁,不拿到资源不罢休
if (!tryLock()) {
try {
//如果没拿到,睡一下再拿
Thread.sleep(new Random().nextInt(10)+1);
} catch (InterruptedException e) {
}
lock();//继续调用自身拿锁
}
}

@Override
public boolean tryLock() {
//非阻塞锁,拿一次,拿到就拿到了,拿不到就撤
try {
mysqlLockDao.save(my);//插入成功即是拿到了
return true;
} catch (Exception e) {
//有异常说明已经被其他线程拿到了,
return false;
}
}

@Override
public void unlock() {
//解锁,将值删除即可
mysqlLockDao.delete(my);
}

@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return false;
}

@Override
public void lockInterruptibly() throws InterruptedException {

}

@Override
public Condition newCondition() {
return null;
}

}

自建gitlab仓库

发表于 2019-07-16 | 分类于 工具使用

1. 关闭防火墙

1
2
3
4
5
# 关闭防火墙
systemctl stop firewalld

# 阻止防火墙开机自启
systemctl disable firewalld

2. 安装sshd

1
2
3
sudo yum install -y curl policycoreutils-python openssh-server
sudo systemctl enable sshd
sudo systemctl start sshd

3. 安装邮件服务

主要是为了gitlab能通过邮件进行通知

1
2
3
sudo yum install postfix
sudo systemctl enable postfix
sudo systemctl start postfix

4. 安装gitlab

gitlab的安装地址为:https://docs.gitlab.com/omnibus/manual_install.html

有社区版(ce)和企业版(ee),这里建议你使用企业版

安装脚本地址:https://packages.gitlab.com/gitlab/gitlab-ee/install#bash-rpm

1
curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh | sudo bash

安装

1
yum install -y gitlab-ee

gitlab-ee会被安装/opt/gitlab目录下可通过下面命令查看

1
rpm -ql gitlab-ee | less

5. 配置gitlab

配置项非常多,这里我们就简单配置下gitlab的地址与端口
gitlab的配置文件在/etc/gitlab/目录下,主要配置文件为gitlab.rb

详细配置可查看文档:https://docs.gitlab.com/omnibus/settings/configuration.html

更改gitlab地址

1
2
3
4
5
改: external_url 'http://gitlab.example.com'
为: external_url 'http://139.189.64.100:8500' #你的IP地址或域名

改: # unicorn['port'] = 8080
为: unicorn['port'] = 8500

设置邮箱
这里以163邮箱为例,QQ邮箱设置与其类似

1
2
3
4
5
6
7
8
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.163.com"
gitlab_rails['smtp_port'] = 25
gitlab_rails['smtp_user_name'] = "test@163.com"
gitlab_rails['smtp_password'] = "password"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['gitlab_email_from'] = "test@163.com"

重新加载配置文件

1
sudo gitlab-ctl reconfigure

这个过程有点慢,耐心等待…

重启gitlab

1
gitlab-ctl restart

浏览器打开该地址,第一次进入,会让你设置密码

6. gitlab基本操作

6.1 创建群组

企业内部使用,可以创建一个群组,方便我们后期管理我们的项目

6.2 创建项目

、

新创建的项目,要新增一个文件,不然master分支什么的都不会出来,有点坑

设置提交权限

6.3 创建其他用户



只需要填这三个

设置密码

6.4 将用户添加到项目中


这里就体现出了创建群组的好处,我们可以将用户添加到群组中,这样群组中的项目,该用户都有权限了

7. 注意

如果你是HTTP,clone 一定要采用 ssh方式,ssh秘钥生成方式

1
ssh-keygen -t rsa -C “username@*.com”

将 id_rsa.pub 里面的内容copy到gitlab的SSH配置里

SpringBoot使用异步任务

发表于 2019-07-16 | 分类于 Java,springboot,SpringBoot技能大全

1. 开启异步任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.pibigstar;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync //开启异步任务
public class SpringbootDemoApplication {

public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}

2. 编写异步任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

package com.pibigstar.task;

import java.util.concurrent.Future;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

@Component
public class AsyncTask {

@Async //异步方法注解
public Future<Boolean> task1() throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(1000);
long end = System.currentTimeMillis();
System.out.println("=====任务1 耗时:"+(end-start)+"======");
//返回true,告诉此任务已完成
return new AsyncResult<Boolean>(true);
}

@Async //异步方法注解
public Future<Boolean> task2() throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(800);
long end = System.currentTimeMillis();
System.out.println("=====任务2 耗时:"+(end-start)+"======");
//返回true,告诉此任务已完成
return new AsyncResult<Boolean>(true);
}

@Async //异步方法注解
public Future<Boolean> task3() throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(600);
long end = System.currentTimeMillis();
System.out.println("=====任务3 耗时:"+(end-start)+"======");
//返回true,告诉此任务已完成
return new AsyncResult<Boolean>(true);
}
}

3. 启动异步任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.pibigstar.web;

import java.util.concurrent.Future;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.pibigstar.task.AsyncTask;

@RestController
@RequestMapping("/task")
public class AsyncTaskController {

@Autowired
private AsyncTask asyncTask;

@GetMapping("test")
public String test() throws InterruptedException {
long start = System.currentTimeMillis();
Future<Boolean> a = asyncTask.task1();
Future<Boolean> b = asyncTask.task2();
Future<Boolean> c = asyncTask.task3();

//循环到三个任务全部完成
while (!a.isDone()||!b.isDone()||!c.isDone()) {
if (a.isDone()&&b.isDone()&&c.isDone()) {
break;
}
}
long end = System.currentTimeMillis();
String result = "任务完成,一共用时为:"+(end-start)+"毫秒";
System.out.println(result);
return result;
}
}

4. 运行结果

任务1 睡眠了 1000毫秒,任务2 睡眠了800毫秒,任务3 睡眠了600毫秒,如果是同步执行的话三个任务完成应该是2400毫秒,而这里只使用了1005毫秒,说明我们的任务执行确实是异步执行

5. 异步执行使用场景

SpringBoot使用JSR303做参数校验

发表于 2019-07-06 | 分类于 springboot

1. 实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class User {
@NotNull
private Integer id;

@NotNull
private String name;

@NotNull
@Length(min=6)
private String password;

@NotNull
@IsPhone //自定义的校验
private String phone;
}

#2. Controller中使用

1
2
3
4
@PostMapping(value="login")
public String login(@Valid User user) {

}

3. 自定义校验

注解IsPhone 判断是否为手机号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.pibigstar.springboot.validator;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {PhoneValidator.class})
public @interface IsPhone {

boolean required() default true;

String message() default "手机号不合法"; //错误默认提示信息

Class<?>[] groups() default { };

Class<? extends Payload>[] payload() default { };

}

4. 实现具体校验类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.pibigstar.springboot.validator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
* 手机号码验证者
* @author pibigstar
*
*/
public class PhoneValidator implements ConstraintValidator<IsPhone,String>{

private boolean requeired;
@Override
public void initialize(IsPhone constraintAnnotation) {
requeired = constraintAnnotation.required();
}


@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (requeired) {
return isPhone(value);
}else {
//phone 不是必须
if (value==null||value.length()==0) {
return true;
}else {
return isPhone(value);
}
}
}

private boolean isPhone(String phone) {
//以1开头,后面跟10个整数,一共11位
Pattern phonePattern = Pattern.compile("1\\d{10}");
if (phone==null||phone.length()<=0) {
return false;
}else {
Matcher matcher = phonePattern.matcher(phone);
return matcher.matches();
}
}
}

5. 对参数不通过进行统一捕获

参数验证不通过后统一格式返回给前端页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.pibigstar.springboot.exception;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import com.pibigstar.springboot.domain.result.MyResponse;

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

@ExceptionHandler(value=Exception.class)
public MyResponse exceptionHandler(HttpServletRequest request,Exception e) {
//参数校验异常
if (e instanceof BindException) {
BindException exception = (BindException) e;
List<ObjectError> allErrors = exception.getAllErrors();
ObjectError objectError = allErrors.get(0);
String defaultMessage = objectError.getDefaultMessage();
return MyResponse.error(defaultMessage);
}else {
//其他异常
return MyResponse.error(e);
}
}
}

SpringBoot使用RabbitMQ发送消息队列

发表于 2019-07-03 | 分类于 springboot,SpringBoot技能大全

准备

因为RabbitMQ使用erlang语言写的,所以要先安装erlang语言,貌似国内访问很慢,这里放一个下载好的,版本erlang:10.2,rabbitMq:3.7.9

下载:https://pan.baidu.com/s/1k0w23XJYTp_0gTaMb5bXRg
提取码:aeiz

启动(两种方式):

  1. 直接双击rabbitmq_server-3.7.9/sbin/rabbitmq-service.bat
  2. 在cmd中启动

建议在cmd中启动,直接双击的话关闭只能到任务管理器中关

1. 添加依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2. 添加配置

1
2
3
4
5
6
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest

3. direct模式

这种是点对点模式,一个发送一个接收

3.1 配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @author pibigstar
* @create 2018-12-17 10:57
* @desc direct模式,点对点,一个发送一个接收
**/
@Configuration
public class QueueRabbitConfig {
public static final String QUEUE_NAME = "pibigstar";
/**
* 定义一个名为:pibigstar 的队列
*/
@Bean
public Queue pibigstarQueue() {
return new Queue(QUEUE_NAME);
}
}

3.2 消费者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.pibgstar.demo.amqp.config.QueueRabbitConfig;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.logging.Logger;

/**
* @author pibigstar
* @create 2018-12-17 11:00
* @desc direct模式消费者
**/
@Component
// 监听pibigstar队列
@RabbitListener(queues = QueueRabbitConfig.QUEUE_NAME)
public class QueueConsumer {
private static Logger logger = Logger.getLogger("QueueConsumer");
@RabbitHandler
public void process(String message) {
logger.info("接受到的消息:"+message);
}
}

3.3 发送者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @author pibigstar
* @create 2018-12-17 11:04
* @desc 消息发送者
**/
@Component
public class Sender {
@Autowired
private AmqpTemplate rabbitTemplate;

/**
* 点对点发送
*/
public void sendMessage(String message) {
rabbitTemplate.convertAndSend(QueueRabbitConfig.QUEUE_NAME,message);
}
}

4. Topic模式

这种是订阅/发布模式,一个发送多个接收

4.1 配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @author pibigstar
* @create 2018-12-17 11:18
* @desc topic模式,订阅/发布模式,一个发送多个接收
**/
@Configuration
public class TopicRabbitConfig {
// 队列1
public final static String ONE = "topic.one";
// 队列2
public final static String TWO = "topic.two";
// 所有队列
public final static String ALL = "topic.#";
// 转发器
public final static String EXCHANGE = "topic.exchange";

@Bean
public Queue queueOne() {
return new Queue(TopicRabbitConfig.ONE);
}

@Bean
public Queue queueTwo() {
return new Queue(TopicRabbitConfig.TWO);
}

@Bean
TopicExchange exchange() {
return new TopicExchange(EXCHANGE);
}

/**
* 绑定队列one到转发器上
*/
@Bean
Binding bindingExchangeMessage(Queue queueOne, TopicExchange exchange) {
return BindingBuilder.bind(queueOne).to(exchange).with(ONE);
}
/**
* 绑定所有队列(one和two)到转发器上
*/
@Bean
Binding bindingExchangeMessages(Queue queueTwo, TopicExchange exchange) {
return BindingBuilder.bind(queueTwo).to(exchange).with(ALL);
}
}

4.2 消费者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import com.pibgstar.demo.amqp.config.TopicRabbitConfig;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.logging.Logger;

/**
* @author pibigstar
* @create 2018-12-17 11:29
* @desc topic模式消费者
**/
@Component
public class TopicConsumer {
private static Logger logger = Logger.getLogger("TopicConsumer");

@RabbitListener(queues = TopicRabbitConfig.ONE)
public void receiveOne(String message){
logger.info("one接受到的消息:"+message);
}

@RabbitListener(queues = TopicRabbitConfig.TWO)
public void receiveTwo(String message){
logger.info("two接受到的消息:"+message);
}
}

4.3 发送者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import com.pibgstar.demo.amqp.config.QueueRabbitConfig;
import com.pibgstar.demo.amqp.config.TopicRabbitConfig;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* @author pibigstar
* @create 2018-12-17 11:04
* @desc 消息发送者
**/
@Component
public class Sender {
@Autowired
private AmqpTemplate rabbitTemplate;
/**
* 一对多发送
*/
public void sendTopicMessage(String message) {
// 往队列one中发送信息, receiverOne和receiverTwo都可以收到
rabbitTemplate.convertAndSend(TopicRabbitConfig.EXCHANGE,TopicRabbitConfig.ONE,message);
// 往队列two中发送信息,只有receiverTwo收到
rabbitTemplate.convertAndSend(TopicRabbitConfig.EXCHANGE,TopicRabbitConfig.TWO,message);
}
}

微信小程序使用npm安装第三方库

发表于 2019-07-02 | 分类于 微信小程序

我们以安装有赞的 vant库做例子

1. 初始化

在小程序根目录中(miniprogram)执行

1
npm init

输入一些基本的信息,可以一直回车,按默认就可以,然后会生成一个package.json文件

2. 安装第三方库

有赞文档地址:https://youzan.github.io/vant-weapp/#/intro
执行

1
npm i vant-weapp -S --production

3.构建npm

回到微信开发者工具中,在工具中点击构建npm

4. 启用npm模块

在详情中,把 使用npm模块勾选上

5. 使用

  1. 在index.json中引入组件库

    1
    2
    3
    "usingComponents": {
    "van-button": "vant-weapp/button/index"
    }
  2. 在index.wxml使用按钮

    1
    <van-button type="danger">危险按钮</van-button>

注意:如果出现找不到路径,请再次点击 构建npm (步骤3)

10行代码搞定微信支付(Java版)

发表于 2019-07-02 | 分类于 工具使用,Java

微信支付痛点

对于大多数同学来说,要开发微信支付可不简单。
附上微信支付官方文档https://pay.weixin.qq.com/wiki/doc/api/index.html
从文档上可以看出,你需要解决很多问题,我就随便挑几个吧。

xml与对象的互转: 微信使用xml格式而不使用json通信, 也确实有点奇葩
签名:千万不要以为只是MD5一下,要是你自己开发,我敢说,你60%的时间都耗在签名调试这一块


以上是微信公众账号支付的时序图,简单概括为2个点。
下单,发起支付
接收异步通知,修改订单的支付状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//微信公众账号支付配置 
WxPayH5Config wxPayH5Config = new WxPayH5Config();
wxPayH5Config.setAppId("xxxxx");
wxPayH5Config.setAppSecret("xxxxxxxx");
wxPayH5Config.setMchId("xxxxxx");
wxPayH5Config.setMchKey("xxxxxxx");
wxPayH5Config.setNotifyUrl("http://xxxxx");

//支付类, 所有方法都在这个类里
BestPayServiceImpl bestPayService = new BestPayServiceImpl();
bestPayService.setWxPayH5Config(wxPayH5Config);

//发起支付
bestPayService.pay();

//异步回调
bestPayService.asyncNotify();
`

下单和修改支付状态是用户的业务系统干的事,我们来说说如何快速发起支付和接收异步通知
可能是目前最好的支付SDK
这是一款支付SDK,支付账号借用请往下看, best-pay-sdk
项目主页 https://github.com/Pay-Group/best-pay-sdk
有了它你接入支付的代码只需要像上面一样使用方法
去掉注释和空行,刚好10行!更多使用,请访问https://github.com/Pay-Group/best-pay-sdk

Java虚拟机常用命令参数

发表于 2019-07-02 | 分类于 JVM

1. 打印某个类的常量池

1
javap -v Test.class

2. 查看类的加载顺序

1
java -verbose:class Test

3. 反编译字节码

1
javap -v -c Test

批处理脚本启动多个应用

发表于 2019-06-26 | 分类于 工具使用

将其保存为 SSR.bat 即可

1
2
3
4
5
@echo off
start /d "D:\SSR\" SSR4.0.exe
start /d "D:\SSR\kcptun\" run.vbs
echo successfully open the SSR
exit

如果想让它开机自启,那么将这个脚本放到下面这个位置即可

1
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp

如果想在cmd中快速启动,那么将这个脚本放到下面这个位置即可:

1
C:\Windows

java随笔记

发表于 2019-06-26 | 分类于 Java

文件写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
String fileName = "/root/log/test.log";
Path file = Paths.get(fileName);
boolean exists = Files.exists(Paths.get(dir), LinkOption.NOFOLLOW_LINKS);
try {
if (!exists) {
Files.createDirectories(Paths.get(dir));
}
List<String> lines = Arrays.asList(msg);
// 写文件,CREATE,APPEND打开文件的标志位, 创建或追加
Files.write(file, lines, Charset.forName("UTF-8"),
StandardOpenOption.CREATE,
StandardOpenOption.APPEND);
} catch (IOException e) {
LOGGER.info("IOException", e);
}

NIO方式复制文件

1
2
3
4
5
6
7
8
9
10
public static void copyFileByChannel(File source, File dest) throws IOException {
try (FileChannel sourceChannel = new FileInputStream(source).getChannel();
FileChannel targetChannel = new FileOutputStream(dest).getChannel();){
for (long count = sourceChannel.size() ;count>0 ;) {
long transferred = sourceChannel.transferTo(sourceChannel.position(), count, targetChannel);
sourceChannel.position(sourceChannel.position() + transferred);
count -= transferred;
}
}
}

年月日获取

1
2
3
4
LocalDate today = LocalDate.now();
int year = today.getYear();
int month = today.getMonthValue();
int day = today.getDayOfMonth();

根据配置文件来决定是否显示Swagger

1
2
3
@ConditionalOnExpression("'${swagger.enable}' == 'true'")
public class SwaggerConfig {
}

并发集合不存在则加入

1
2
3
private ConcurrentMap<String, T> singletonInstances = new ConcurrentMap<>();
// 如果不存在此实例则将其放进去
singletonInstances.putIfAbsent(name, instance);

判断不为空

1
2
3
4
5
6
7
8
9
10
11
// 判断对象不为null,如果为null则抛出空指针异常,不为空返回此对象
obj = Objects.requireNonNull(obj);
// 这个是com.google.common.base包中的方法
Preconditions.checkNotNull(url);

// 检查集合不为null,为空抛出空指针
Collections.checkedList(lists)
// 检查map不为空,key或value为空则抛出空指针
Collections.checkedMap(map)
// 检查Set不为空
Collections.checkedSet(set)

检查某个Class对象是否被某注解注解

1
2
// 判断clazz对象是否有MyAnnotation注解
clazz.isAnnotationPresent(MyAnnotation.class);

读取配置文件

读取类似properties格式的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Enumeration<URL> urls = classLoader.getResources(“META-INF/extensions/test.info”);
if(urls!=null && urls.hasMoreElements()){
while(urls.hasMoreElements()){
URL url = urls.nextElement();
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
String line = null;
while ((line=br.readLine())!=null){
String config = line;
//跳过注释
if(config.startsWith("#")){
continue;
}
String key= null;
String value= null;
int i = config.indexOf('=');
if (i > 0) {
key= config.substring(0, i).trim();
value= config.substring(i + 1).trim();
}
System.out.Println("key:"+key+" value:"+value);
}
}
}

字符串格式化

1
String str = String.format("%s has already been exported", name)

Buffer流写操作

1
2
3
4
5
6
// 获取字符解码类
CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
// 将字符串转换为字节Buffer
ByteBuffer bytes = encoder.encode(CharBuffer.wrap("要写入的值"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("test.txt"));
bos.write(bytes.array(), 0, bytes.limit());
1…456…14
派大星

派大星

137 日志
64 分类
230 标签
GitHub CSDN
© 2019 派大星