posts - 19, comments - 32, trackbacks - 0, articles - 59
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2017年8月7日

1:pom.xml 找自己spring boot 对应的版本
  <!-- redis 配置-->
 <dependency>
 <groupId>redis.clients</groupId>
 <artifactId>jedis</artifactId>
 <version>2.8.1</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.data</groupId>
 <artifactId>spring-data-redis</artifactId>
 <version>1.7.2.RELEASE</version>
 </dependency>
<!-- end redis 配置-->

2: 在spring boot   *.properties 配置文件中增加连接配置:
     spring.redis.hostName=127.0.0.1
    spring.redis.port=6379
    spring.redis.password=
    spring.redis.pool.maxActive=8
    spring.redis.pool.maxWait=-1
    spring.redis.pool.maxIdle=8
    spring.redis.pool.minIdle=0
    spring.redis.timeout=0
3: spring boot 中增加redis 配置连接
      /**
 * Created by Administrator on 2017/2/27.
 
*/
@Configuration
@EnableAutoConfiguration
public class RedisConfig {

    private static Logger logger = LoggerFactory.getLogger(RedisConfig.class);

    @Bean
    @ConfigurationProperties(prefix="spring.redis")
    public JedisPoolConfig getRedisConfig(){
        JedisPoolConfig config = new JedisPoolConfig();
        return config;
    }
  @Bean
    @ConfigurationProperties(prefix="spring.redis")
    public RedisConnectionFactory jedisConnectionFactory(){
        return new JedisConnectionFactory(getRedisConfig());
    }
    @Bean
    public RedisTemplate<String, Object> redisTemplate(){
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        //这个缓存key的序列化方式
        template.setKeySerializer(new StringRedisSerializer());
        //设置redis 转换 value 通过jdk序列化方法,GenericJackson2JsonRedisSerializer 这个是json形式
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(jedisConnectionFactory());
        return template;
    }

    /**
     * 这个是redis 多值操作返回模版对象。比如:map,set ,list 等
     * 
@return
     
*/  @Bean
    public ValueOperations<String, Object> valueOperations(){
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        //这个缓存key的序列化方式
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //这个缓存value的序列化方式,通过有jdk序列化,这个是json 序列化
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setExposeConnection(true);
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        redisTemplate.afterPropertiesSet();
        return redisTemplate.opsForValue();
    }
}
4: RedisTemplate 使用
   @Service
public class RedisServiceImpl implements RedisService{
    @Autowired
    private RedisTemplate redisTemplate;
    public boolean expire(final String key, long expire,final TimeUnit unit) {
        return redisTemplate.expire(key, expire, unit);
    }
    @Override
    public void setList(String key, List<String> list, long expire, TimeUnit unit) throws Exception {
        redisTemplate.delete(key);
        redisTemplate.opsForValue().set(key,list,expire,unit);
    }
    public List<String> getList(String key) {
        return (List<String>)redisTemplate.opsForValue().get(key);
    }
    public void remove(String key){
        redisTemplate.delete(key);
    }
    @Override
    public void setKey(String key, String s, long expire, TimeUnit unit) {
        redisTemplate.opsForValue().set(key,s,expire,unit);
    }
    
    @Override
    public String getKey(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }
    @Override
    public Object getKeyForObject(String key) {
        return redisTemplate.opsForValue().get(key);
    }
    @Override
    public void setMap(String key, Map<String, Object> map, long expire, TimeUnit unit) throws Exception {
        this.expire(key,expire,unit);
        redisTemplate.opsForHash().putAll(key,map);
    }
      @Override
    public void removeKeyForMap(String key, String mapKey) {
        redisTemplate.opsForHash().delete(key,mapKey);
    }
    @Override
    public void putMapKey(String key, String mapKey, String mapValue) {
        redisTemplate.opsForHash().put(key,mapKey,mapValue);
    }
    public Set<String> keys(String o ){
        return redisTemplate.keys(o);
    }
}

5:单元测试类

RunWith(SpringRunner.class)
@SpringBootTest(classes = MyApplication.class)// 指定spring-boot的启动类
//相当于  --spring.profiles.active=dev
@ActiveProfiles(value = "dev")
public class RedisCacheTest {
    protected final Logger logger = Logger.getLogger(this.getClass());
    @Autowired
    private RedisService redisService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void CacheTest() throws Exception {
        redisService.setKey("111111","222222",100, TimeUnit.SECONDS);
        redisService.getKey("111111");
    }
    @Test
    public void SaveObjectForCacheTest()throws Exception{
        TargetDB targetDB=new TargetDB();
        targetDB.setDbType("111");
        targetDB.setPort("22");
        targetDB.setUserName("zzzlyr");
        redisTemplate.opsForValue().set("key111",targetDB);
        TargetDB targetDB12= (TargetDB) redisTemplate.opsForValue().get("key111");
        System.out.println(targetDB12.toString());
    }
      @Test
    public void SaveMapForCacheTest()throws Exception {
        TargetDB targetDB = new TargetDB();
        targetDB.setDbType("111");
        targetDB.setPort("22");
        targetDB.setUserName("zzzlyr");
        List<TargetDB> list = new LinkedList<TargetDB>();
        list.add(targetDB);
        Map<String, List<TargetDB>> map = new LinkedHashMap<String, List<TargetDB>>();
        map.put("111111111111", list);
        //向缓存中放入map
        redisTemplate.opsForHash().putAll("zzzzz", map);
        //从缓存中获取map
        Map<String, List<TargetDB>> cacheMap = redisTemplate.opsForHash().entries("zzzzz");
        //Map<String,List<String>> cacheMap= (Map<String, List<String>>) redisTemplate.opsForValue().get("platform-app_AppOperation");
        System.out.println(cacheMap.toString());
    }
}

posted @ 2017-08-07 17:38 张钊钊 阅读(19) | 评论 (0)编辑 收藏

2017年7月10日

前言:JUnit元数据

@Before: 
使用了该元数据的方法在每个测试方法执行之前都要执行一次。 
@After: 
使用了该元数据的方法在每个测试方法执行之后要执行一次。 
注意:@Before和@After标示的方法只能各有一个。这个相当于取代了JUnit以前版本中的setUp和tearDown方法,当然你还可以继续叫这个名字,不过JUnit不会霸道的要求你这么做了。
@Test(expected=*.class) 
在JUnit4.0之前,对错误的测试,我们只能通过fail来产生一个错误,并在try块里面assertTrue(true)来测试。现在,通过@Test元数据中的expected属性。expected属性的值是一个异常的类型
@Test(timeout=xxx): 
该元数据传入了一个时间(毫秒)给测试方法, 
如果测试方法在制定的时间之内没有运行完,则测试也失败。 
@ignore: 
该元数据标记的测试方法在测试中会被忽略。当测试的方法还没有实现,或者测试的方法已经过时,或者在某种条件下才能测试该方法(比如需要一个数据库联接,而在本地测试的时候,数据库并没有连接),那么使用该标签来标示这个方法。同时,你可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方 法。比如:@lgnore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。、

一、包含必要地Package

最主要地一个 Package就是org.junit.*,把它包含进来之后,绝大部分功能就有了。还有一句话也非常地重要“import static org.junit.Assert.*;”,我们在测试的时候使用的一系列assertEquals方法就来自这个包。大家注意一下,这是一个静态包含 (static),是JDK5中新增添的一个功能。也就是说,assertEquals是Assert类中的一系列的静态方法

二、测试类的声明

测试类是一个独立的类,没有任何父类。测试类的名字也可以任意命名,没有任何局限性。它与普通类的区别在于它内部的方法的声明

三、创建一个待测试的对象

你要测试哪个类,那么你首先就要创建一个该类的对象。

private staticCalculator calculator =newCalculator();

为了测试Calculator类,我们必须创建一个calculator对象。

四、测试方法的声明

在测试类中,并不是每一个方法都是用于测试的,你必须使用“标注”来明确表明哪些是测试方法。“标注”也是JDK5的一个新特性,用在此处非常恰当。我们可以看到,在某些方法的前有@Before、@Test、@Ignore等字样,这些就是标注,以一个“@”作为开头。这些标注都是JUnit4自定义 的,熟练掌握这些标注的含义非常重要。

六、 忽略测试某些尚未完成的方法

七、 Fixture(暂且翻译为“固定代码段”)

Fixture 的含义就是“在某些阶段必然被调用的代码”。“在任何一个测试执行之前必须执行的代码”就是一个Fixture,我们用@Before来标注它

一、 高级Fixture

两个Fixture标注,分别是@Before和@After,是否适合完成如下功能:有一个类是负责对大文件(超过 500兆)进行读写,他的每一个方法都是对文件进行操作。换句话说,在调用每一个方法之前,我们都要打开一个大文件并读入文件内容,这绝对是一个非常耗费时间的操作。如果我们使用@Before和@After,那么每次测试都要读取一次文件,效率及其低下。这里我们所希望的是在所有测试一开始读一次文件, 所有测试结束之后释放文件,而不是每次测试都读文件。JUnit的作者显然也考虑到了这个问题,它给出了@BeforeClass 和 @AfterClass两个Fixture来帮我们实现这个功能。从名字上就可以看出,用这两个Fixture标注的函数,只在测试用例初始化时执行@BeforeClass方法,当所有测试执行完毕之后,执行@AfterClass进行收尾工作。在这里要注意一下,每个测试类只能有一个方法被标注为 @BeforeClass或@AfterClass,并且该方法必须是Public和Static的。

二、 限时测试

那个求平方根的函数有Bug,是个死循环:

  public voidsquareRoot(intn) ...{

         for(; ;) ;//Bug : 死循环

  }

如果测试的时候遇到死循环,对于那些逻辑很复杂,循环嵌套比较深的程序,很有可能出现死循环,因此一定要采取一些预防措施。我们给这些测试函数设定一个执行时间,超过了这个时间,他们就会被系统强行终止,并且系统还会向你汇报该函数结束的原因是因为超时,这样你就可以发现这些Bug了。只需要给@Test标注加一个参数即可,代码如下:

  @Test(timeout = 1000)

  public voidsquareRoot() ...{

         calculator.squareRoot(4);

         assertEquals(2,calculator.getResult());

  }

  Timeout参数表明了你要设定的时间,单位为毫秒,因此1000就代表1秒。

三、 测试异常

经常会编写一些需要抛出异常的函数,如果一个函数应该抛出异常,但是它没抛出,当然是Bug。例如,我们写的计算器类有除法功能,如果除数是一个0,那么必然要抛出“除0异常”。因此,我们很有必要对这些进行测试。代码如下:

  @Test(expected = ArithmeticException.class)

  public void divideByZero() ...{

         calculator.divide(0);

  }

如上述代码所示,我们需要使用@Test标注的expected属性,将我们要检验的异常传递给他,这样JUnit框架就能自动帮我们检测是否抛出了我们指定的异常。

四、 Runner (运行器)

把测试代码提交给JUnit框架后,框架如何来运行代码呢?答案就是——Runner。在JUnit中有很多个 Runner,他们负责调用测试代码,每一个Runner都有各自的特殊功能,要根据需要选择不同的Runner来运行测试代码。JUnit中有一个默认Runner,如果没有指定,那么系统自动使用默认 Runner来运行你的代码。换句话说,下面两段代码含义是完全一样的:

import org.junit.runner.RunWith;

import org.junit.runners.Suite;

 

@RunWith(Suite.class)

@Suite.SuiteClasses({

MyTestCase.class, //测试类

PartSuite.class, //另一个测试套

})

public class AllTestCases {

}

  要想指定一个Runner,需要使用@RunWith标注,并且把你所指定的Runner作为参数传递给它。另外一个要注意的 是,@RunWith是用来修饰类的,而不是用来修饰函数的。只要对一个类指定了Runner,那么这个类中的所有函数都被这个Runner来调用。

五、 参数化测试

一个对考试分数进行评价的函数,返回值分别为“优秀,良好,一般,及格,不及格”,因此你在编写测试的时候,至少要写5个测试,把这5中情况都包含了,这 确实是一件很麻烦的事情。我们还使用我们先前的例子,测试一下“计算一个数的平方”这个函数,暂且分三类:正数、0、负数。测试代码如下:

importorg.junit.AfterClass;

  importorg.junit.Before;

  importorg.junit.BeforeClass;

  importorg.junit.Test;

  importstatic org.junit.Assert.*;

  public classAdvancedTest ...{

         private static Calculator calculator =new Calculator();

         @Before

         public void clearCalculator() ...{

                calculator.clear();

         }

         @Test

         public void square1() ...{

                calculator.square(2);

                assertEquals(4,calculator.getResult());

         }

         @Test

         public void square2() ...{

         calculator.square(0);

         assertEquals(0, calculator.getResult());

         }

         @Test

         public void square3() ...{

                calculator.square(-3);

                assertEquals(9,calculator.getResult());

         }

}

为了简化类似的测试,JUnit4提出了“参数化测试”的概念,只写一个测试函数,把这若干种情况作为参数传递进去,一次性的完成测试。代码如下:

  importstatic org.junit.Assert.assertEquals;

  importorg.junit.Test;

  importorg.junit.runner.RunWith;

  importorg.junit.runners.Parameterized;

  importorg.junit.runners.Parameterized.Parameters;

  importjava.util.Arrays;

  importjava.util.Collection;

  @RunWith(Parameterized.class)

  public classSquareTest{

  private static Calculator calculator = new Calculator();

         private int param;

         private int result;

         @Parameters

         public static Collection data(){

                return Arrays.asList(newObject[][]...{

                {2, 4},

                {0, 0},

                {-3, 9},

         });

  }

//构造函数,对变量进行初始化

六、断言和假设

断言:org.junit.Assert用于测试用例中,如果断言失败,用例即结束。

假设:org.junit.Assume用于在准备环境时判断环境是否符合要求,包括测试套的@BeforeClass,测试类的@BeforeClass,测试类的实例化,测试类的@Before。

如果假设失败,假设所处初始化代码方法立即结束,更深级别的后续工作也被忽略,相关测试用例被忽略,但与假设同级别的收尾工作还要继续执行。 
例如:如果在测试类的@BeforeClass中假设失败,该类的实例化及子级别将被忽略,@AfterClass会继续执行。
七、工程实例
     
 如果不想在单元测试中操作数据库中的数据。可以在测试方法上加 
     @Test

    @Transactional //单元测试  @Transactional 不会进行数据提交事物
    @Rollback(true) // 这个注释可以不用加(单元测试默认值)
    public void testaddUserPrivate()throws Exception{
        UserPrivate userPrivate=new UserPrivate();
        userPrivate.setTenantId("31");
        userPrivate.setMenuCode("7777888");
        userPrivate.setpUid("111222");
        userPrivate.setRoleId("3332277");
        userPrivate.setValue("99999");
        userPrivate.setUpdateDateTime(new Date());
        userPrivate.setCreateDateTime(new Date());
        int s=userPrivateService.addUserPrivate(userPrivate);
        Assert.assertEquals(1, s); // 这是断言的使用
    }
        

posted @ 2017-07-10 10:17 张钊钊 阅读(21) | 评论 (0)编辑 收藏

2017年7月4日

1: spring cloud eureka 如果出现某个应用实例 down(1), 说明 spring admin 健康检测没有通过导致 eureka 注册中心不会把这个实例从列表中删除掉。 这样所有使用这个实例的服务都会现404(前提是在应用中配置过spring admin); 2:spring admin 健康检测会检测*.properties里的所有连能性的配置(mysql,redis,短信服务,邮件服务),如果这些URL中有一个不通,则会导致eureka中出现, 这个实例down(1) 并且不会从列表中删除掉。 例: 应用中不使用reides,但是在pom.xml中引用reides的配置(只限于spring-boot redis配置) 这样spring admin 健康检测发现*.properties没配置redis,但是spring-boot-starter-data-redis 有默认配置(是localhost), 会导致检测不通过,eureka 显示状态为 down(1). 处理这样问题可以使用:http://eureakIP:port/health 如果没有问题会返回:{"description":"Spring Cloud Eureka Discovery Client","status":"UP"} 如果有问题会返回那个实例的检测什么配置项没有通过,只要修改后重启应用实例,这样eureka应用会显示UP(1);

posted @ 2017-07-04 18:30 张钊钊 阅读(449) | 评论 (0)编辑 收藏

2017年6月20日

spring boot + mybatis 配置; MybatisConfiguration 类 加 @EnableTransactionManagement spring boot 启动类 加 @EnableTransactionManagement 其实都不要配置,spring boot 默认配置。 一般 @Transactional 东西 加在,service 层。 如果在 controller 呢? 官方解释如下: spring-framework-reference.pdf 文档上有这样一段话: only looks for @Transactional on beans in the same application context it is defined in. This means that, if you put in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services. 意思就是:只会查找和它在相同的应用上下文件中定义的bean上面的@Transactional注解,如果你把它放在Dispatcher的应用上下文中,它只检查控制器(Controller)上的@Transactional注解,而不是你services上的@Transactional注解。 所以,可以确定的是我们是可以在Controller上使用事务注解的,但是我们不推荐这样做(本人也从来没有这样做过)。

posted @ 2017-06-20 17:03 张钊钊 阅读(36) | 评论 (0)编辑 收藏

2017年3月28日

package stacktest;

/**
* @Author: zzz
* @CreateTime: 2017/3/28 10:52
* @Description: 队列特点(先进先出),链表实现的队列 在队头删除元素,在队尾插入元素。
* 这样才能满足队列的特性。
*/
public class MyQueue<T> {
private Node<T> front; //队列头,只能删除元素

    private Node<T> rear; //队列尾,只能用来插入入元素

    private int size;//队列的长度

/**
* 初始化队列
*/
public MyQueue() {
front = new Node<T>();
rear = front;
}

/**
* 链表的数据结构
*/
private class Node<T> {
public T data;
public Node<T> next;

public Node(T data, Node next) {
this.data = data;
this.next = next;
}

public Node(T data) {
this.data = data;
}

public Node() {
}
}

public void add(T data) {
//新插入的节点永远是尾节点,它的next 指向null(即没有后继节点)
        Node newNode = new Node(data, null);
//让尾节点next指向新节点
        rear.next = newNode;
rear = newNode;
size++;
}

public T pop() throws Exception {
if (size < 1) {
throw new Exception("错误,队列为空。");
}
Node<T> nextNode = front.next;

front.next = nextNode.next;
size--;
if (size < 1) {
rear = front;
size = 0;
}
return nextNode.data;

}

//取队首元素

public T peek() throws Exception {
if (size < 1){
throw new Exception("错误,队列为空。");
};
return front.next.data;

}
//返回队列的大小
public int getSize() {
return size;
}

//判断队列是否为空
public boolean isEmpty() {
return size == 0;
}

/**
* 遍历算法,移动front指针,直到front指针追上rear指针
*/
public void traverse(){
for(Node currentNode=front.next; currentNode!=null; currentNode=currentNode.next ){
System.out.println(currentNode.data);
}
}

public static void main(String[] args)throws Exception{
MyQueue<String> queue=new MyQueue<>();
for(int i=0;i<10;i++){
queue.add("88888-"+i);
}

/* for(int i=0;i<10;i++){
String s=queue.pop();
System.out.print(s+";");
}*/
queue.traverse();

}
}

posted @ 2017-03-28 15:48 张钊钊 阅读(53) | 评论 (0)编辑 收藏

2017年3月27日

栈的特点:后进先出,所以一个线性链表实现的栈也只能在一端操作才能满足这种特性;


/**
* @Author: zzz
* @CreateTime: 2017/3/27 14:51
* @Description:
*/
public class MyStack<T> {

private Node top;//永远指向栈顶元素
//元素个数
private int size;


/**
* 内部类,定义节点
*/
private class Node {
public T data;

public Node next;

public Node(T data, Node next) {
this.data = data;
this.next = next;
}

}

public void push(T data) {
//next 指向当前元素top,如果是第一个元素next 指向null;
Node node = new Node(data, top);
//把当前元素指向top
top = node;
size++;
}


public T pop() {
Node oldNode = top;
top = top.next;
oldNode.next = null;
//释放引用
return oldNode.data;
}

//返回栈顶的元素,但不出栈
public T peek() {
return top.data;

}

// 判断链栈是否为空栈
public boolean empty() {
return size == 0;
}

public String toString() {
// 链栈为空链栈时
if (empty())
return "[]";
else {
StringBuilder sb = new StringBuilder("[");
for (Node current = top; current != null; current = current.next) {
sb.append(current.data.toString() + ", ");
}
int len = sb.length();
return sb.delete(len - 2, len).append("]").toString();

}
}

public static void main(String[] args) throws Exception {
MyStack stack = new MyStack<String>();
for (int i = 0; i <= 10; i++) {
stack.push("111111-" + i);
}
System.out.println(stack);
System.out.println("frist pop="+stack.pop());
System.out.println("second pop="+stack.pop());
System.out.println("thrid pop="+stack.pop());
System.out.println("pop 之后的"+stack);
}

posted @ 2017-03-27 15:43 张钊钊 阅读(129) | 评论 (0)编辑 收藏

2017年2月16日

gitlab 有两种提交代码方式 

1:把某一个分支clone到本地,然后修改和增加本地分支的代码,然后commit , 在pull , 在push(会自动合并),

2:把某一个分支clone到本地,然后修改和增加本地分支的代码,然后commit,在fetch , 在rebase 在push(不会动合并).


merge 现个参数: -squash 意思是某个一个分支多次commit被压缩当做一次提交,合并到另一个分支的时候,log 历史只有一次。

                          使用场景:例如一个开发分支可能经常多次commit(这是开发人员经常干的事),但是这么多commit基本上都没有意义。合并的时候压缩只记一次有意义提交历史。

                          - Fash forward 意思是合并的时候主分支快速向前(不记录提交历史),这样主分支如果相回退到某一个提交历史的话就不行了。

                            使用场景: 基本没有什么重大提交意义的合并和修改,可以选择使用。 


posted @ 2017-02-16 14:01 张钊钊 阅读(51) | 评论 (0)编辑 收藏

2017年2月9日

1.环境配置

首先安装GitTortoiseGit,不要问我为什么要装TortoiseGit,不知道为什么,就是喜欢小乌龟。

Git下载 
TortoiseGit下载 
这里有打包好的: 
32bit下载 / 64bit下载

安装还是比较简单的,一路默认选项下一步就可以了,因为的我的电脑系统是Windows 10的,安装的时候遇到了2502、2503报错,这是由于安装权限不足造成的,也很好解决,使用命令行安装就好了,戳这里查看解决方法 。

2.配置SSH Key

OK,到这里环境已经安装完成了,接下来就要生成SSH Key了。

首先在TortoiseGit的安装目录下的bin文件夹中找到puttygen.exe这个工具(如果你没有选择安装目录的话,默认路径应该是C:\Program Files\TortoiseGit\bin),这个工具是用来生成密钥对的,打开它点击Generate,然后鼠标在进度条下方不停的晃动,几秒后就会生成密钥对,点击Sava private key保存私钥到本地(输入一个名字,保存到一个你找的到的文件夹),不要关闭这个窗口,接下来还会用到。

生成密钥对

打开GitLab,找到Profile settings(右上角)下的SSH keys选项,选择Add SSH Key,Title输入框里输入一个名称(随便写),然后把上面生成的以ssh-rsa开头的一长串密钥复制到Key输入框,点击Add Key保存。

添加SSH Key

添加SSH Key

到这里SSH Key就配置成功了,刚才生成密钥对的窗口可以关闭了。

3.在本地的项目中配置SSH key

在项目的文件夹上右击鼠标,选择TortoiseGit—Settings—Remot,在Putty Key后选择刚才保存到本地的私钥,然后点击应用。

配置SSH key]

设置SSH客户端,选择Network选项,在下面的SSH Client选项中选择TortoiseGit的安装目录下bin文件夹中的TortoiseGitPlink.exe程序,如果已经默认选中,直接确定就可以了。

设置SSH客户端

在Pull或Push项目的时候,记得勾选Autoload Putty Key选项。

自动加载Putty Key

到这里,GitLab配置SSH Key就已经全部完成了,再也不用麻烦运维的小伙伴了。

GitHub也可以使用此方法配置SSH Key,在Personal settings—SSH and GPG keys—SSH keys选项下选择New SSH Key就可以了。

注意最后clone时候地址使用

URL:  git@git.XXXX.com:ybz/SSC_server.git 前面不用加任任何东西,我就加了ssh://东西弄了好久都clone不下来。

posted @ 2017-02-09 16:33 张钊钊 阅读(67) | 评论 (0)编辑 收藏

2016年12月26日

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * Created by Administrator on 2016/12/26.
 */
public class Test {
    public static void main(String[] args)throws Exception{
        final AtomicInteger sum=new AtomicInteger(0);
        ExecutorService executorService=Executors.newFixedThreadPool(4);
        BlockingQueue<String> queue=new LinkedBlockingDeque<String>(200);
        List<String> list=new LinkedList<String>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("40");
        queue.addAll(list);
        final CountDownLatch cdOrder = new CountDownLatch(list.size());
       for(int i=0 ; i< list.size() ; i++){
           final String sql=queue.poll();
           executorService.execute(new Runnable(){
               @Override
               public void run() {
                   System.out.println("线程" + Thread.currentThread().getName() +";"+sql);
                   cdOrder.countDown(); //任务执行完毕,返回给指挥官,cdAnswer减1。
                   sum.getAndAdd(Integer.parseInt(sql));
               }
           });
       }
       cdOrder.await(2000, TimeUnit.MILLISECONDS);//等待所有线程完成工作2秒内完工
       executorService.shutdown(); //任务结束,停止线程池的所有线程
       System.out.println(sum.get());
    }
}

posted @ 2016-12-26 16:21 张钊钊 阅读(31) | 评论 (0)编辑 收藏

2016年7月6日

首先使用ipconfig 查看 一共有多少个网卡,进行上网路由(其中包括:ip地址,子网掩码,网关)
   
  然后使用route print 命令浏览 路由信息,
  然后使用route -p add 10.12.0.0 mask 255.255.0.0 127.5.1.2  metric 1(路由级别)
  
  
  所以如果内外网都要上网,最好设置外网所有ip走外网网关,然后在指定内网固定IP走内网网关;
  
  即外网路由添加:
   route -p add 0.0.0.0 mask 0.0.0.0 127.5.1.2  metric 1 //是指所以ip走 127.5.1.2这个路由
   
   内网路由指定固定IP:
   
   然后使用route -p add 10.12.0.0 mask 255.255.0.0 127.5.1.2  metric 2(路由级别,一般内网路由级别低)
  
  这句的意思是-p 是永久路由,10.12.0.0 是网自 mask 255.255.0.0是子网掩码  127.5.1.2 是10.12.0.0 这个网段的Ip地址通过 127.5.1.2 这个网关路上发包出去,
  
  比如公司有一个无线外网,另一个是公司内部的研发网,可以用route 命令添加两条路由规则,外网网段的通过一个网关发包,研发网的能过另一个网关发包
  这时候,不用手动切换两个网,计算机会自动切换。这样就可以双网连接了 

posted @ 2016-07-06 11:50 张钊钊 阅读(44) | 评论 (0)编辑 收藏