天道酬勤

天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。

0%

Neo4j使用笔记

1. Neo4j介绍

Neo4j是一种NoSQL数据库,原理是数学里的图论。
常见的SQL数据库有MySQL Oracle等
常见的NoSQL数据库有Redis ES Mongdb Neo4j等
近几年比较流行的的图数据库有Neo4j Titan OrientDB Sparksee Virtuso ArangoDb Airaph GraphDB GraphBase等

Neo4j数据库比较适合处理关系,比如人和人之间的社交关系。
比较成功的应用有 领英 FaceBook Twitter

2. Neo4j下载、安装、配置

Neo4j是开源免费的图数据库,社区版代码开源,企业版代码除集群相关的代码,其余代码全部开源
还有一点,社区版免费,企业版收费。
社区版最多允许 2^35 个节点,2^35 个关系,2^36 个属性

阅读全文 »

有关Git使用的笔记

(1) Git是什么

Git是目前世界上最先进的分布式版本控制系统(没有之一)

(1.1) 配置Git

安装完git建议配置的选项

配置用户名 git config --global user.name "wkq"
配置邮箱 git config --global user.email "weikeqin.cn@gmail.com"
不忽略大小写 (文件名区分大小写) git config --global core.ignorecase false
不适用路径转义 (可以认为类似使用UTF-8) git config --global core.quotepath false

(1.2) 生成ssh

ssh-keygen -t rsa -C "weikeqin.cn@gmail.com"

阅读全文 »

Java调用JavaScript


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

/**
 * @version V1.0
 * @date 2017-09-21 20:58
 */
public class JsTest {

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

	public static void main(String[] args) {

		
		String url = "//flights.ctrip.com/domesticsearch/search/SearchFirstRouteFlights?DCity1=BJS&ACity1=KMG&SearchType=S&DDate1=2017-09-22&IsNearAirportRecommond=0&LogToken=1bd69145999c49d391102da28ded88fe&CK=1E1CDC6F399D26F328ACAB7254823FA5"
				+ "&rk=" + Math.random() * 10 + "204001";
		String r = "0.4229086476791374857311";

		ScriptEngineManager manager = new ScriptEngineManager();
		// nashorn javascript
		ScriptEngine engine = manager.getEngineByName("javascript");

		String jsFileName = "doc/html/xiecheng/ajaxRequest.js"; // 读取js文件
		// 执行指定脚本
		BufferedReader br = null;
		Invocable invoke = null;
		try {
			br = new BufferedReader(new FileReader(jsFileName));
			engine.eval(br);
			invoke = (Invocable) engine;
		} catch (FileNotFoundException e) {
			logger.error("", e);
		} catch (ScriptException e) {
			logger.error("", e);
		}

		Object o = null;
		try {
			// 调用方法,并传入两个参数
			o = invoke.invokeFunction("ajaxRequest", url, r);
		} catch (ScriptException e) {
			logger.error("", e);
		} catch (NoSuchMethodException e) {
			logger.error("", e);
		}

		logger.info("执行js后的结果:\r\n{}", o);

	}

}

JDBC

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

String driverClassName = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false";
String user = "user01";
String password = "user01";
	
Class.forName(driverClassName).newInstance();
Connection con = DriverManager.getConnection(url, user, password);

// 插入 
String sql = "insert into user(name, password, age) values (?, ?, ?) ;";
PreparedStatement pst = con.prepareStatement(sql);
pst.setString(1, name);
pst.setString(2, password);
pst.setInt(3, age);
num = pst.executeUpdate();
pst.close();
con.close();			
			
// 查询
String sql = "select count(*) as count from table_user ;";
PreparedStatement pst = secondCon.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
while (rs.next()) {
	// TODO
}			
rs.close();
pst.close();
con.close();

jdbc-pool

Tomcat 在 7.0 以前的版本都是使用 commons-dbcp 做为连接池的实现,但是 dbcp 饱受诟病,原因有:

dbcp 是单线程的,为了保证线程安全会锁整个连接池
dbcp 性能不佳
dbcp 太复杂,超过 60 个类
dbcp 使用静态接口,在 JDK 1.6 编译有问题
dbcp 发展滞后

因此很多人会选择一些第三方的连接池组件,例如 c3p0 , bonecp, druid (@wenshao ) 等。

为此,Tomcat 从 7.0 开始引入一个新的模块:Tomcat jdbc pool

tomcat jdbc pool 近乎兼容 dbcp ,性能更高
异步方式获取连接
tomcat jdbc pool 是 tomcat 的一个模块,基于 tomcat JULI,使用 Tomcat 的日志框架
使用 javax.sql.PooledConnection 接口获取连接
支持高并发应用环境
超简单,核心文件只有8个,比 c3p0 还
更好的空闲连接处理机制
支持 JMX
支持 XA Connection

tomcat jdbc pool 的优点远不止这些,详情请看 官网

tomcat jdbc pool 可在 Tomcat 中直接使用,也可以在独立的应用中使用。

在独立的应用中使用

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;

public class SimplePOJOExample {

  public static void main(String[] args) throws Exception {
	  PoolProperties p = new PoolProperties();
	  p.setUrl("jdbc:mysql://localhost:3306/mysql");
	  p.setDriverClassName("com.mysql.jdbc.Driver");
	  p.setUsername("root");
	  p.setPassword("password");
	  p.setJmxEnabled(true);
	  p.setTestWhileIdle(false);
	  p.setTestOnBorrow(true);
	  p.setValidationQuery("SELECT 1");
	  p.setTestOnReturn(false);
	  p.setValidationInterval(30000);
	  p.setTimeBetweenEvictionRunsMillis(30000);
	  p.setMaxActive(100);
	  p.setInitialSize(10);
	  p.setMaxWait(10000);
	  p.setRemoveAbandonedTimeout(60);
	  p.setMinEvictableIdleTimeMillis(30000);
	  p.setMinIdle(10);
	  p.setLogAbandoned(true);
	  p.setRemoveAbandoned(true);
	  p.setJdbcInterceptors(
		"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
		"org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
	  DataSource datasource = new DataSource();
	  datasource.setPoolProperties(p);

	  Connection con = null;
	  try {
		con = datasource.getConnection();
		Statement st = con.createStatement();
		ResultSet rs = st.executeQuery("select * from user");
		int cnt = 1;
		while (rs.next()) {
			System.out.println((cnt++)+". Host:" +rs.getString("Host")+
			  " User:"+rs.getString("User")+" Password:"+rs.getString("Password"));
		}
		rs.close();
		st.close();
	  } finally {
		if (con!=null) try {con.close();}catch (Exception ignore) {}
	  }
  }

}

异步获取连接

Connection con = null;
try {
  Future<Connection> future = datasource.getConnectionAsync();
  while (!future.isDone()) {
      System.out.println("Connection is not yet available. Do some background work");
      try {
	  Thread.sleep(100); //simulate work
      }catch (InterruptedException x) {
	  Thread.currentThread().interrupted();
      }
  }
  con = future.get(); //should return instantly
  Statement st = con.createStatement();
  ResultSet rs = st.executeQuery("select * from user");
<dependency>  
	<groupId>org.apache.tomcat</groupId>  
	<artifactId>tomcat-jdbc</artifactId>  
	<version>7.0.29</version>  
</dependency>  
<dependency>  
	<groupId>org.apache.tomcat</groupId>  
	<artifactId>tomcat-juli</artifactId>  
	<version>7.0.29</version>  
</dependency>  
<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jdbc -->
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jdbc</artifactId>
    <version>8.5.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-juli -->
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-juli</artifactId>
    <version>8.5.15</version>
</dependency>

References

JDBC
[1] http://www.yiibai.com/jdbc/jdbc_quick_guide.html
[2] http://www.cnblogs.com/DreamDrive/p/5757693.html
[3] http://blog.csdn.net/whucyl/article/details/20838079
[4] http://javastudyeye.iteye.com/blog/835448

jdbc-pool
[1] https://stackoverflow.com/questions/24559468/neo4j-jdbc-connection-pool
[2] http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html
[3] https://www.oschina.net/question/12_36910
[4] https://github.com/alibaba/druid

Java解析xml

遇到一个问题,要解析一个xml,网上搜了搜,都说有4中方式,试了试dom解析,感觉解析的时候开发效率太低,忽然想到Jsoup,然后就用了第5种方式Jsoup解析XML。
用Jsoup解析XML,开发效率确实是高,但是运行效率太低了。解析一个10K左右的xml要0.2s左右。300万的xml文件要解析到什么时候呀。
然后试了试Dom解析xml,效率提高了不少,解析一个10K左右的xml 0.05s左右,效率提高的不少。
当然,还有其他3种方式解析。知道Sax解析时占用内存小,可能会快一点,但是着急处理文件,暂时没有测试。

DOM SAX JDOM DOM4J Jsoup


import javax.xml.parsers.DocumentBuilderFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;

import com.xxxx.usdp.odk.common.file.FileUtil;
import com.xxxx.usdp.xxxx.poc.yuyin.entity.XmlEntity;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

/**
 * DOM方式解析xml
 *
 * @version V1.0
 */

public class DomParserXml {
    
    private static final Logger log = LoggerFactory.getLogger(DomParserXml.class);
    
    /**
     * 测试解析
     */
    @Test
    public void testPaser(){
        String xmlFilePath = "src/main/resources/2018010109013384362390728_1522286730680.xml";
        xmlFilePath = "C:\\home\\user1\\xxxx\\2018010109000672062385406";
        //xmlFilePath = "src/main/resources/test.xml";
        XmlEntity xmlEntity = parserXml(xmlFilePath);
        log.info("xml数据:\r\n{}", xmlEntity);
    }
    
    /**
     * 批量解析
     */
    @Test
    public void batchParser(){
        String filePath = "D:\\data\\210_1\\210_test";
        String outDirPath = "D:\\data\\210_1\\210_201801_result";
        File outDir = new File(outDirPath);
        if(!outDir.exists()){
            outDir.mkdirs();
        }
        
        File dir = new File(filePath);
        File[] files = dir.listFiles();
        int length = files.length;
        for(int i = 0; i < 1000; i++){
            File f = files[i];
            XmlEntity xmlEntity = parserXml(f.getAbsolutePath());
            try {
                FileUtil.writeStringToFile(xmlEntity.getMix(), outDirPath+"/"+xmlEntity.getFileName()+".txt");
            } catch (IOException e) {
                log.error("写文件出错 {}", e.toString());
            }
        }
    }
    
    /**
     * 把xml解析成对话格式
     *
     * @param xmlFilePath
     */
    public static XmlEntity parserXml(String xmlFilePath) {
        return parserXml(new File(xmlFilePath));
    }
    
    
    /**
     * 把xml解析成对话格式
     *
     * @param f
     */
    public static XmlEntity parserXml(File f) {
        
        long t1 = System.currentTimeMillis();
        long t2 = 0;
        //1、创建一个DocumentBuilderFactory的对象
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        //2、创建一个DocumentBuilder的对象
        Document document = null;
        XmlEntity xmlEntity = new XmlEntity();
    
        try {
            //创建DocumentBuilder对象
            DocumentBuilder db = dbf.newDocumentBuilder();
            //3、通过DocumentBuilder对象的parser方法加载books.xml文件到当前项目下
            /*注意导入Document对象时,要导入org.w3c.dom.Document包下的*/
            //传入文件名可以是相对路径也可以是绝对路径
            //document = db.parse(xmlFilePath);
            document = db.parse(f);
            xmlEntity.setFileName(f.getName().replace(".xml", ""));
            
            t2 = System.currentTimeMillis();
            log.info("读文件用时{}s", 1.0*(t2-t1)/1000);
        } catch (ParserConfigurationException e) {
            log.error("Dom解析Xml出错 {}", e.toString());
        } catch (SAXException e) {
            log.error("Dom解析Xml出错 {}", e.toString());
        } catch (IOException e) {
            log.error("Dom解析Xml出错 {}", e.toString());
        }
    
        
        Element instance = (Element) document.getElementsByTagName("instance").item(0);
        // 文件保存地址
        String waveuri = instance.getAttribute("waveuri");
        log.debug("waveuri:{}",waveuri);
        xmlEntity.setWaveuri(waveuri);
        String duration = instance.getAttribute("duration");
        log.debug("duration:{}",duration);
        xmlEntity.setDuration(duration);
        
        NodeList subjectNodes = document.getElementsByTagName("subject");
        if(subjectNodes == null || subjectNodes.getLength() < 2){
            log.error("文件格式错误,subject节点个数小于2个");
            return null;
        }
        log.debug("subject节点个数:{}", subjectNodes.getLength());
        
        
        /** 处理正文和时间片 */
        Element subject1 = (Element) subjectNodes.item(1);
        
        NodeList channels = subject1.getElementsByTagName("channel");
        log.debug("channels 节点个数:{}", channels.getLength());
        
        // channel0 n0
        Element c1 = (Element) channels.item(0);
        String tagname = c1.getTagName();
        log.debug("tagname:{}" ,tagname);
        Element textElementA = (Element) c1.getElementsByTagName("text").item(0);
        Element timeElementA = (Element) c1.getElementsByTagName("time").item(0);
        String textA = textElementA.getTextContent().trim();
        log.debug("textA:|{}|", textA);
        xmlEntity.setN0(textA);
        String timeA = timeElementA.getTextContent().trim();
        log.debug("timeA:|{}|", timeA);
        String[] textArrayA = textA.split(" ");
        String[] timeArrayA = timeA.split(" ");
        int textLengthA = textArrayA.length;
        log.debug("textLengthA:{}", textLengthA);
    
    
        // channel1  n1
        Element c2 = (Element) channels.item(1);
        String tagname2 = c2.getTagName();
        log.debug("tagname2:{}" ,tagname2);
        Element textElementB = (Element) c2.getElementsByTagName("text").item(0);
        Element timeElementB = (Element) c2.getElementsByTagName("time").item(0);
        String textB = textElementB.getTextContent().trim();
        log.debug("textB:|{}|", textB);
        xmlEntity.setN1(textB);
        String timeB = timeElementB.getTextContent().trim();
        log.debug("timeB:|{}|", timeB);
    
        String[] textArrayB = textB.split(" ");
        String[] timeArrayB = timeB.split(" ");
        int textLengthB = textArrayB.length;
        log.debug("textLengthB:{}", textLengthB);
    
        String n0 = "n0";
        String n1 = "n1";
        List<TimeTextEntity> timeTextList = new ArrayList<>(textLengthA +textLengthB);
        
        if(textLengthA > 1){
            // A
            for(int i = 0; i < textLengthA; i++){
                // 一个词语
                String oneTerm = textArrayA[i];
                // 时间片
                String oneTime = timeArrayA[i];
                String[] timeArraySub = oneTime.split(",");
                int start = Integer.parseInt(timeArraySub[0]);
                int end = Integer.parseInt(timeArraySub[1]);
                TimeTextEntity t = new TimeTextEntity(start, end, oneTerm, n0);
                timeTextList.add(t);
            }
        }
    
    
        if(textLengthB >1){
            // B
            for(int i =0; i <textLengthB; i++){
                // 一个词语
                String oneTerm = textArrayB[i];
                // 时间片
                String oneTime = timeArrayB[i];
                String[] timeArraySub = oneTime.split(",");
                int start = Integer.parseInt(timeArraySub[0]);
                int end = Integer.parseInt(timeArraySub[1]);
                TimeTextEntity t = new TimeTextEntity(start, end, oneTerm, n1);
                timeTextList.add(t);
            }
        }
    
        long t4 = System.currentTimeMillis();
        // 升序
        Collections.sort(timeTextList, new Comparator<TimeTextEntity>() {
            @Override
            public int compare(TimeTextEntity o1, TimeTextEntity o2) {
                return new Integer(o1.getStart()).compareTo(o2.getStart());
            }
        });
        long t5 = System.currentTimeMillis();
        log.info("排序用时{}s", 1.0*(t5-t4)/1000);
    
        int allCount = timeTextList.size();
        StringBuilder sb = new StringBuilder();
        String flag = null;
        for(int i =0; i < allCount; i++){
        
            log.debug("{}  {}", i, timeTextList.get(i));
        
            TimeTextEntity entity = timeTextList.get(i);
            String who = entity.getWho();
            if(who.equals(flag)){
                sb.append(entity.getText());
                sb.append(" ");
            }else{
                sb.append("\r\n");
                flag = who;
                sb.append(flag);
                sb.append(" : ");
                sb.append(entity.getText());
                sb.append(" ");
            }
        
        
        } // end for
        
        xmlEntity.setMix(sb.toString());
        
    
        long t3 = System.currentTimeMillis();
        log.info("解析用时{}s", 1.0*(t3-t2)/1000);
    
        log.info("总共用时{}s", 1.0*(t3-t1)/1000);
        
        log.debug("对话:{}", sb);
    
        return xmlEntity;
    }
    
    
}


/**
 * 时间段对象<br>
 */
class TimeEntity{
    
    private int start;
    private int end;
    
    public TimeEntity(){
    
    }
    
    public TimeEntity(int start, int end){
        this.start = start;
        this.end = end;
    }
    
    public int getStart() {
        return start;
    }
    
    public void setStart(int start) {
        this.start = start;
    }
    
    public int getEnd() {
        return end;
    }
    
    public void setEnd(int end) {
        this.end = end;
    }
    
    @Override
    public String toString() {
        return "TimeEntity{" + "start='" + start + '\'' + ", end='" + end +
            '\'' + '}';
    }
    
}

/**
 *
 */
class TimeTextEntity{
    
    private int start;
    private int end;
    private String text;
    /** n0 n1 */
    private String who;
    
    public TimeTextEntity(){
    
    }
    
    public TimeTextEntity(int start, int end, String text, String who){
        this.start = start;
        this.end = end;
        this.text = text;
        this.who = who;
    }
    
    public int getStart() {
        return start;
    }
    
    public void setStart(int start) {
        this.start = start;
    }
    
    public int getEnd() {
        return end;
    }
    
    public void setEnd(int end) {
        this.end = end;
    }
    
    public String getText() {
        return text;
    }
    
    public void setText(String text) {
        this.text = text;
    }
    
    public String getWho() {
        return who;
    }
    
    public void setWho(String who) {
        this.who = who;
    }
    
    @Override
    public String toString() {
        return "TimeTextEntity{" + "start=" + start + ", end=" + end + ", " +
            "text='" + text + '\'' + ", who='" + who + '\'' + '}';
    }
}

  对决策树的学习 以及 决策树在文本分类中的应用。

(1) 生活实例

  通俗来说,决策树分类的思想类似于找对象。现想象一个女孩的母亲要给这个女孩介绍男朋友,于是有了下面的对话:

  女儿:多大年纪了?
  母亲:26。
  女儿:长的帅不帅?
  母亲:挺帅的。
  女儿:收入高不?
  母亲:不算很高,中等情况。
  女儿:是公务员不?
  母亲:是,在税务局上班呢。
  女儿:那好,我去见见。

  这个女孩的决策过程就是典型的分类树决策。相当于通过年龄、长相、收入和是否公务员
对将男人分为两个类别:见和不见。

生活实例1

阅读全文 »

本文主要介绍有关MySQL的内容,包括一些常用配置,常见问题。根据个人使用经验总结,希望可以帮到大家。

MySQL配置

下面是我的配置

[client]

port=3306

# utf8mb4 is a superset of utf8
default-character-set = utf8mb4


[mysql]

# utf8mb4 is a superset of utf8
default-character-set = utf8mb4


# SERVER SECTION
# ----------------------------------------------------------------------
#
# The following options will be read by the MySQL Server. Make sure that
# you have installed the server correctly (see above) so it reads this 
# file.
#
[mysqld]

# utf8mb4 is a superset of utf8
character-set-server=utf8mb4


#collation-server=utf8mb4_unicode_ci 
#collation-server=utf8_general_ci

#character-set-client-handshake = FALSE

#init_connect='SET NAMES utf8mb4'

# mkdir for every database
innodb_file_per_table=1

# ignore lowercase
lower_case_table_names=1

# all import biggest 1024M file to mysql
max_allowed_packet=1024M

# The TCP/IP Port the MySQL Server will listen on
port=3306

#log

# Binary Log
log-bin=mysql-bin
binlog-format=ROW 
server_id=1

# if query_time > 1s sql will log
long_query_time=1
# if query is slow, query will log   version 5.6
slow-query-log=1
slow-query-log-file = /usr/local/mysql/log/slow_query.log
# slow-query-log-file=c:/professionsofware/mysql/log/slow_query.log
# version5.0  log-slow-queries=c:/professionsofware/mysql/log/slow_query.log

# log all query  version5.6
general_log=ON
general_log_file = /usr/local/mysql/log/all_query.log
#general_log_file=c:/ProfessionSofware/MySQL/log/all_query.log
#version5.0 log=c:/ProfessionSofware/MySQL/log/all_query.log
# log error 
#log-error=c:/professionsofware/mysql/log/mysql_error.log

#Path to installation directory. All paths are usually resolved relative to this.
#basedir="C:/ProfessionSofware/MySQL/MySQLServer5.6/"
basedir=/usr/local/mysql 

#Path to the database root
#datadir="C:/ProgramData/MySQL/MySQL Server 5.6/Data/"
datadir=/usr/local/mysql/data

# The default character set that will be used when a new schema or table is
# created and no character set is defined
#character-set-server=gbk

# The default storage engine that will be used when create new tables when
default-storage-engine=INNODB

# The default storage engine that will be used for temporary tables
default-tmp-storage-engine=INNODB
阅读全文 »

原来在学会一些东西的时候总喜欢总结,做一些笔记。刚开始用txt做笔记。使用Git来管理版本。后来很多需要图片的,发现txt不方便,就开始用word。但是在用git提交的时候就发现word的不方便了。而且word不是纯文本文件,在其他电脑或者手机上打开不太方便。后来发现了markdown,就是用markdown来写博客。

在写博客前,在网上搜了好多写博客的方法。最后发现使用markdown格式的比较多。而且最近大家都用github + hexo来搭建自己的博客,教程也比较多,所以自己也想搭一个试试。

(1) 安装软件

(1.1) 安装git

Git官网下载,或者可以在百度下载。下载完以后双击运行。一直点next,直到完成安装。

通过 git --version 验证是否安装正确以及查看版本。

(1.2) 安装Node.js

 在Node.js官网下载,或者在百度下载。推荐使用zip包,解压完配置一下就能用。

下载完解压到一个目录,解压文件到 D:\ProfessionalSoftWare\Node , 并在解压后的目录下建立 node_global和node_cache (node_global: npm全局安装路径 node_cache: npm全局缓存路径)

新建环境变量 NODE_PATH = D:\ProfessionalSoftWare\Node\node-v10.16.0-win-x64
修改环境变量 PATH 增加 %NODE_PATH%;%NODE_PATH%\node_global;

通过 node -v 验证是否安装正确以及查看版本。

注意:npm其实是Node.js的包管理工具(package manager),刚开始一直不知道nmp和Node.js是什么关系,晕了半天

阅读全文 »

(1) SpringBoot以JSON格式返回对象

<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-core</artifactId>
	<version>${jackson.version}</version>
</dependency>
 
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>${jackson.version</version>
</dependency>
 
<dependency>
	<groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-annotations</artifactId>
	<version>${jackson.version</version>
</dependency>

(2) springboot hot deploy

  1. 添加对应jar包

  2. 添加插件

  3. 配置idea

  4. mvn dependencies 添加以下依赖

    <!-- add hot deployment -->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-devtools</artifactId>
    	<optional>true</optional>
    	<scope>runtime</scope>
    </dependency>
  5. build的时候添加以下plug

    <plugin>
    	<!-- hot deployment config -->
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-maven-plugin</artifactId>
    	<configuration>
    		<fork>true</fork>
    	</configuration>
    </plugin>
  6. 配置idea

  7. 1 File -> Settings -> Compiler 勾选 Build Project automatically

  8. 2 双击 Shift,输入 registry , 点击 Registry.. ,勾上 compiler.automake.allow.when.app.running

Allow auto-make to start even if developed application is currently running. Note that automatically started make may eventually delete some classes that are required by the application.

References

[1] Spring Boot Reference Documentation
[2] using-spring-boot
[3] spring-boot
[4] spring.io
[5] Spring Boot 学习笔记:以JSON格式返回对象
[6] springboot+idea热部署(自动刷新)
[7] spring-boot 速成(2) devtools之热部署及LiveReload