xyz327

hakuna matata

zuul是spring cloud的网关组件,用户在微服务中提供一个统一的对外接口,官方对zuul的说明是

Zuul is an edge service that provides dynamic routing, monitoring, resiliency, security, and more.

阅读全文 »

第三条:用私有构造器或者枚举类型强化Singleton

从1.5开始使用单元素的枚举类是实现单例的的最佳方法

第四条:通过私有构造器强化不可实例化的能力

主要对于工具类

第五条: 避免创建不必要的对象

要优先使用基本类型而不是装箱类型,要当心无意识的自动装箱

阅读全文 »

使用maven管理项目时,完成开发后需要把项目发布到maven私服上去。

手动SNAPSHOT版本开发时执行mvn clean deploy就可以部署到私服上。

在开发是还会需要SNAPSHOT版本和RELEASE版本可以用mvn versions:set -DnewVersion=0.1.1-SNAPSHOT进行更改版本号

当然maven还有更好的管理插件进行RELEASE管理maven-release-plugin

阅读全文 »

公司服务器ip网段与电脑网段不同。于是要通过配置路由去访问。

每次开机都要重新执行一遍添加路由的脚本,

1
sudo route add -net 192.168.103.0/24 gw 192.168.8.118

于是就把脚本放入开机启动自动执行

只需要在 /etc/init.d/文件夹下新建一个文件

*** 添加执行权限 ***
*** 在文件开头添加 ***

阅读全文 »

在spring容器初始化后执行操作

1
2
3
4
5
6
7
8
9
10
11
@Component
public class AfterContextStarted implements ApplicationListener<ContextRefreshedEvent> {

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
//存在springMVC时 可能会被调用两次(一次spring容器,一次springMVC容器)
if(applicationContext.getParent() == null){//root application context 没有parent,他就是老大.
//TODO something
}
}
}

spring动态注册Bean

1
2
3
4
5
6
 //通过ConfigurableListableBeanFactory可以注册一个bean
ConfigurableApplicationContext configurableApplicationContext =
(ConfigurableApplicationContext) applicationContext;
ConfigurableListableBeanFactory beanFactory =
configurableApplicationContext.getBeanFactory();
beanFactory.registerSingleton(beanName, bean);

在Bean初始化时对Bean做一些操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//实现BeanPostProcessor接口
@Component
public class BeanProcessor implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
}
阅读全文 »

在自定义Appender时,设置属性可以直接通过logback.xml进行设置,但是枚举对象,默认的处理方法不能处理,
这事可以自己定义一个新的解析规则

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
public class DIYAppender extends OutputStreamAppender {
/**
* 使用 {@link ch.qos.logback.core.joran.action.NestedBasicPropertyIA} 解析
*/
private String attr;
/**
* 使用 {@link ch.qos.logback.core.joran.action.NestedComplexPropertyIA} 解析
*/
private User objAttr;
/**
* 使用 {@link enumObjAction} 解析
*/
private enumObj enumAttr;
//省略 getter/setter方法
}
public class User {

}
public enum enumObj {
Instance;
private String name;
//省略 getter/setter
}
public class enumObjAction extends ch.qos.logback.core.joran.action.Action {
@Override
public void begin(InterpretationContext ic, String name, Attributes attributes) throws ActionException {
ic.pushObject(enumObj.Instance);
}

@Override
public void end(InterpretationContext ic, String name) throws ActionException {

}
}

可以在logback.xml的appender节点中直接进行设置,如果属性是对象可以提供class属性进行设置

1
2
3
4
5
6
7
8
9
10
<newRule pattern="configuration/appender/enumAttr" class="enumObjAction"/>
<appender class="DIYAppender">
<attr>value</attr><!--设置attr的值为value -->
<objAttr class="package.User">
<!--还可以给User进行设置属性值-->
</objAttr>
<enumAttr>
<name>nameValue</name>
</enumAttr>
</appender>

有时候想要扫描某一个包下的类,spring提供一个一扫描的类,
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider

这个类的findCandidateComponents就是扫描的方法。通过自己继承这个类,再提供类的过滤条件。就可以了

还可以继承它的子类org.springframework.context.annotation.ClassPathBeanDefinitionScanner

需要两个过滤设置。因为扫描的时候会过滤两次
第一次是addIncludeFilter 添加的条件
第二次是调用isCandidateComponent(AnnotatedBeanDefinition)方法

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
/**
* Entity的扫描类,提供entity的包
* 扫描包下 {@link Entity}或{@link Table} 标注的类
* Created by xyz327 on 17-5-15.
*/
public class ClassPathCacheEntityScanner extends ClassPathScanningCandidateComponentProvider {
private Logger logger = LoggerFactory.getLogger(getClass());

ClassPathCacheEntityScanner(BeanDefinitionRegistry registry) {
super(false);//不使用默认的过滤器
//添加自己的过滤器
addIncludeFilter(new AnnotationTypeFilter(Entity.class));
addIncludeFilter(new AnnotationTypeFilter(Table.class));
}

public Set<Class> doScan(String... basePackages) throws ClassNotFoundException {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<Class> entitySet = new HashSet<>();

for (String basePackage : basePackages) {
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

for (BeanDefinition candidate : candidates) {
Class entityClass = ClassUtils.forName(candidate.getBeanClassName(), null);
entitySet.add(entityClass);
}
}
return entitySet;
}

/**
* {@inheritDoc}
*/
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isConcrete() //是否为具体的类 (非抽象和接口)
&& (beanDefinition.getMetadata().hasAnnotation(Entity.class.getName()) //需要标记 @Entity
|| beanDefinition.getMetadata().hasAnnotation(Table.class.getName())); // 或者标记 @Table
}

}

开发有时候需要使用terminal,无奈家里电脑还是只能用Windows,但是感觉CMD真的很难用,就是是powershell也不太习惯

公司电脑用deepin oh-my-zsh不能更舒服,就想到能不能在windows上也能装上oh-my-zsh

于是开始一番baidu+google

安装cywin

先装上cywin 网络太慢的话可以从迅雷下 32位 64位

开始安装,选择从网络安装,太慢的话可以使用国内的源 http://mirrors.ustc.edu.cn/cygwin/

阅读全文 »

项目需要实现类似nginx反向代理的功能,于是就采用Filter+HttpClient去实现请求转发。

为了开发方便就采用的springboot做测试项目。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@SpringBootApplication
//@ServletComponentScan
@Controller
public class AppTestApplication {

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

@Bean
public FilterRegistrationBean indexFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean(new TestFilter());
registration.addUrlPatterns("/*");
return registration;
}
}

Filter里面做匹配Uri后获取request.getInputStream()用httpClient转发请求

但是在转发Content-Type=multipart/form-data文件上传时,转发后目标服务器总是获取不到正常的payload的请求体

在Filter里面debug发现压根就获取不到文件…

阅读全文 »

使用karma+jasmine 构建前端自动化测试环境

在项目下先安装karma 和 jasmine

1
npm install karma karma-jasmine karma-chrome-launcher --save-dev

安装karma的命令行

1
npm install karma-cli -g

在项目跟路径下初始化karma

1
karma init

需要选择初始化的选项,根据自己的需要设置初始化的设置(会生成一个karma.conf.js)

安装karma-coverage 生成代码覆盖率报告

1
npm install karma-coverage --save-dev

安装karma-coverage后需要在karma.conf.js 添加相应的配置信息

安装完成后,编写源文件以及相对应的测试文件

开始执行测试(会打开chrome 修改了源文件或测试文件后会自动重新执行测试)

1
karma start karma.conf.js

karma.conf.js 具体内容

阅读全文 »