filter和拦截器的执行顺序
request –> filter1 –> filter2 –> interceptor1 –> interceptor2 –> dispatcherServlet
–> controller – modelAndView –> dispatcherServlet –> 视图渲染 –> interceptor2(afterCompletion)
–> interceptor1(afterCompletion) –> filter2 –> filter1
spring boot打包成war,切切换profile
spring boot: 1.5.6
spring cloud: Dalston.SR2
基于spring cloud的开发,默认是打包成jar的,有些情况我们需要打成war然后部署到tomcat下,下面的方式可以打成war并且使用maven切换profile
<packaging>war</packaging>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>${tomcat.scope}</scope>
</dependency>
<profiles>
<profile>
<id>dev</id>
<properties>
<tomcat.scope>compile</tomcat.scope>
<project.profile.active>dev</project.profile.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>mock</id>
<properties>
<tomcat.scope>compile</tomcat.scope>
<project.profile.active>mock</project.profile.active>
</properties>
</profile>
<profile>
<id>uat</id>
<properties>
<tomcat.scope>provided</tomcat.scope>
<project.profile.active>uat</project.profile.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<tomcat.scope>provided</tomcat.scope>
<project.profile.active>prod</project.profile.active>
</properties>
</profile>
</profiles>
<build>
<finalName>ur-name</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
如果不添加第二个插件,项目会因为没有web.xml为打包报错
@EnableDiscoveryClient
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
spring:
application:
name: gateway-app
cloud:
config:
discovery:
enabled: true
service-id: payment-config-server
label: master
profile: @project.profile.active@
profile变量名需要使用2个@引起来,service-id是config server的名字
mysql一致性读笔记
mysql 5.6
读的是数据行的快照, 既历史版本的记录, 通过读undo实现, 默认读取方式
总是读取被锁定行的最新的一份快照数据
总是读取事务开始时的行数据版本
val的初始值是1
t2时刻, session A 查询返回1
t4时刻, session B 修改该记录
t5时刻, session A 重复查询, 返回1, 由于t4时刻的修改未提交
t7时刻, session A 重复查询, 返回2, 是最新的数据
t2时刻, session A 查询返回1
t4时刻, session B 修改该记录
t5时刻, session A 重复查询, 返回1, 由于t4时刻的修改未提交
t7时刻, session A 重复查询, 依然返回1, 快照读返回的是事务开始时的行数据
不同隔离级别下, 一致性读的行为不一致, 如果需要保证数据的逻辑一致, 可以使用加锁
select … for update, 加一个排它锁(X锁)
select … lock in share mode, 加一个共享读锁(S锁)
java关于interrupt笔记
jdk version: 1.8
t.isInterrupted(),用来判断线程的中断状态
t.interrupt(),用来中断该线程
Thread.interrupted(),用来恢复线程的中断状态
调用t.interrupt()可以中断线程t
此时t.isInterrupted()为true
调用Thread.interrupted(),操作返回true
调用t.isInterrupted()检查中断状态,为false
若再次调用Thread.interrupted(),此时返回false,即已经重置过了
jmh的简单使用说明
jmh version:1.18
jdk version: 1.8
使用maven添加jmh-core和jmh-generator-annprocess
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@Threads(2)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@BenchmarkMode(Mode.Throughput)
@State(Scope.Benchmark)
public class JMHCase1 {
ObjectMapper om = new ObjectMapper();
@State(Scope.Benchmark)
public static class UserInfo {
int age;
String name;
int sex;
double salary;
String location;
int isMarried;
Date birthday;
String mobile;
String idCardNo;
String job;
@Setup(Level.Trial)
public void init() {
age = 18;
name = "Roronoa-Zoro";
sex = 1;
salary = 20000.1;
location = "One Piece";
isMarried = 0;
birthday = new Date();
mobile = "1380000000";
idCardNo = "11012011912345";
job = "fighter";
}
}
@Benchmark
public String fastjsonTest(UserInfo userInfo) {
String result = JSON.toJSONString(userInfo);
// JSON.parseObject(result, UserInfo.class);
return result;
}
@Benchmark
public String jacksonTest(UserInfo userInfo) throws IOException {
String result = om.writeValueAsString(userInfo);
// om.readValue(result, UserInfo.class);
return result;
}
@Test
public void starter() throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHCase1.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
@Warmup, 进行预热,正式基准测试前进行
@Measurement, 正式基准测试,包括执行几次,每次执行的时间
@Fork, 表示每个基准测试执行几轮
@Threads, 表示启用几个线程
@OutputTimeUnit, 表示输出结果时的时间单位
@BenchmarkMode, 表示基准测试采集的数据,有吞吐量,平均执行时间,抽样统计方法的执行时间,其他见源码参数注释
@State, 表示是每个线程独有还是在这一次基准测试过程中共享
Benchmark Mode Cnt Score Error Units
JMHCase1.fastjsonTest thrpt 5 5396.680 ± 646.910 ops/ms
JMHCase1.jacksonTest thrpt 5 4641.159 ± 755.968 ops/ms
上面的error的±表示误差幅度, score和units则表示每毫秒有多少操作数
@Warmup(iterations = 2, time = 50, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 2, time = 50, timeUnit = TimeUnit.MILLISECONDS)
@Fork(1)
@Threads(1)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@BenchmarkMode(Mode.Throughput)
@State(Scope.Benchmark)
public class JMHCase2 {
@Param({"hello", "world", "jmh"})
String argument;
@Benchmark
public void showParamUsage() {
System.out.println("argument value=" + argument);
}
@Test
public void starter() throws RunnerException {
Options opt = new OptionsBuilder()
.include(JMHCase2.class.getSimpleName())
.build();
new Runner(opt).run();
}
}
主要添加了@param, 就是可以给参数赋值,而且上例中有3个值,则基准测试会针对每个参数值执行一次