2017 开发Fix集锦 - yiyixiaozhi/readingNotes GitHub Wiki


title: 开发Fix集锦 date: 2017-10-2 23:28:11 description: 17年开发过程中遇到的一些小问题的解决 categories:

  • 开发 tags:

2017-4-9 ubuntu服务器环境搭建

配置ssh链接,jdk,hadoop,Samba

配置Linux环境属性

  • 修改终端字体大小
sudo dpky-reconfigure console-setup
  • 第一次root用户解锁操作
    • 修改root密码
    sudo passwd root
    • 用户注销
    logout
    • ubuntu16.04切换到root用户登录
    su root
    • 以root用户进行登录
    • who命令来查看是谁登录。
  • 关闭Linux防火墙
    ufw disable
    • 卸载iptables组件
    apt-get remove iptables
    • 安装vim
    apt-get install vim
    • Hostname主机
    vim /etc/hosts

ssh连接配置

  • ssh工具:
apt-get install openssh-server
  • 启动ssh服务:
/etc/init.d/ssh start
  • 查看是否服务已经启动:
ps -e | grep sshd
  • 解决默认不能root用户登录使用ssh的问题:
vim /etc/ssh/sshd_config

随后修改PermitRootLogin,将内容设置为yes

ftp服务

  • 安装
apt-get install vsftpd
  • 修改默认ftp用户的密码
passwd ftp

ftp完成后,会自动创建目录 /srv/ftp,修改权限

chmod 777 /srv/ftp

如果要ftp正常工作,修改配置文件

vim /etc/vsftpd.conf

修改如下参数:

anonymous_enable NO //不允许匿名登录
...
local_enable YES //允许本地用户登录
...
write_enable=YES //用户具有写权限
...
chroot_local_user=YES //是否将所有用户限制在主目录
...
chroot_list_enable=YES //是否启动限制用户的名单
  • 定义名单设置的目录(名单中可以设置多个账号)
chroot_list_file=/etc/vsftpd.chroot_list
  • 增加一个服务配置 pam-service_name=vsftpd ,注意文件中不能存在此条信息的重复数据(我新增了一条,踩了个坑)。
  • 增加一个新的文件,写上一个用户
vim /etc/vsftpd.chroot_list
  • 在第一行写上ftp,表示新增一个用户
  • 修改 vim /etc/pam.d/vsftpd,注释掉以下内容:

# auth required pam_shells.so

  • 启动服务
service vsftpd start

JDK的安装与配置

  • 下载Linux版本jdk.
  • XShell使用rz命令传到服务器
  • 解压
root@ubuntu:/home/bianxh/Downloads# tar xzvf jdk-8u111-linux-x64.tar.gz -C /usr/local
  • 打开环境文件进行配置:
vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.8.0_111
export PATH=$PATH:$JAVA_HOME/bin:
export CLASS_PATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
  • 让配置立刻生效
source /etc/profile
  • 测试下是否生效成功
root@ubuntu:/usr/local/jdk1.8.0_111# java -version
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)

在Linux中安装Hadoop

  • 上传Hadoop文件并解压缩
root@ubuntu:/home/bianxh/Downloads# tar xzvf hadoop-2.6.0.tar.gz -C /usr/local
  • 配置环境变量,修改/etc/profile
export HADOOP_HOME=/usr/local/hadoop-2.6.0
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:
  • 让配置立刻生效
source /etc/profile
  • hadoop依赖jdk
root@ubuntu:/usr/local/hadoop-2.6.0/etc/hadoop# vim hadoop-env.sh
#export JAVA_HOME=${JAVA_HOME}
export JAVA_HOME=/usr/local/jdk1.8.0_111

Linux常用命令

  • 设置当前系统时间命令示例:
$ date –set “10/15/2009 20:18”
  • 递归解压bz2g格式压缩包示例:
tar -jxvf cygwin.tar.bz2 -C 指定目录
  • Samba服务器文件夹权限分配实例(修改/etc/samba/smb.conf):
[bianxh]
  comment = File Share of bianxh
  browseable = yes
  path = /home/bianxh/
  writable = yes
  create mask = 777
  valid users = public bianxh
  directory mask = 777
  available = yes

2017-04-28 Mac开发环境搭建

Mac下安装brew、Redis、zookeeper过程中踩过的坑。

Mac serria偏好设置找到“打开任意来源”命令

$ sudo spctl --master-disable

重建MAC的右键打开方式列表 Mac上选中一个文件点击右键会有一个“Open With”菜单,如果你装过多个虚拟机等,这个菜单会出现很多windows系统的程序,从而使这个菜单十分混乱,可以使用以下命令行来清除所有的重复项。

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -r -domain local -domain user;killall Finder;echo “Open With has been rebuilt, Finder will relaunch“

Mac Web开发环境配置

安装brew

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install\"

安装下载工具

brew install wget

安装Redis

$ wget http://download.redis.io/releases/redis-3.0.7.tar.gz
$ tar xzf redis-3.0.7.tar.gz
$ cd redis-3.0.7
$ make

启动redis

$ src/redis-server redis.conf

连接上以后,关闭redis

$ src/redis-cli
$ 127.0.0.1:6379> SHUTDOWN

测试redis

$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"

# Mac OS命令行下使用SublimeText打开文本文件

打开用户配置文件

vim ~/.bash_profile

添加如下alias

alias subl="'/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl'"
alias ll='ls -al'

如果不添加别名,也可以选择将路径添加到环境变量下。这里的路径根据实际情况可能会有所不同。

wq保存后回到命令行执行以下命令使其生效:

source ~/.bash_profile

命令行使用,这里我们假设在命令行用SublimeText打开.bash_profile,则执行如下:

subl ~/.bash_profile

安装zookeeper

$brew install zookeeper

启动服务

$ sudo zkServer start
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Starting zookeeper ... STARTED

在MAC下需要用sudo命令来启动此服务,否则会失败。

查看zookeeper运行及状态


$ zkServer status
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Mode: standalone
$zkCli
Connecting to localhost:2181

停止服务

$ zkServer stop
ZooKeeper JMX enabled by default
Using config: /usr/local/etc/zookeeper/zoo.cfg
Stopping zookeeper ... STOPPED

安装邮件服务 James server

$ subl ~/.bash_profile
export JAMES_SRC_HOME=/usr/local/james-project/james-project

安装maven,参考教程

$ brew install maven

默认安装位置是

$ /usr/local/Cellar/maven/3.3.9

Fix problems

maven报错:

Could not calculate build plan: Plugin org.apache.maven.plugins:maven-resources-plugin:2.6 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-resources-plugin:jar:2.6

解决方法:

1、查看windows -> Preferences -> maven 的settings.xml文件中.m2的位置

2、然后将.m2/repository/org/apache/maven/plugins目录下的文件夹全部删除

3、选中maven项目,右键 --> maven --> update,让maven重新下载依赖包

注:此IDE自带maven插件,不需要再自己下载安装maven插件

mac下,dubbo注册zookeeper,ip地址是一个虚拟的地址,并不是局域网的本机ip

在搭建zookeeper的过程中,使用dubbo获取的地址总是220.250.64.26,通过jdk代码调用来看,确实是这样:

InetAddress ia=null;
try {
ia=ia.getLocalHost();

String localname=ia.getHostName();
String localip=ia.getHostAddress();
System.out.println("本机名称是:"+ localname);
System.out.println("本机的ip是 :"+localip);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

cosole输出:

本机名称是:bogon
本机的ip是 :220.250.64.26

220.250.64.26是虚拟的地址,导致项目在tomcat下无法正常运行。 在mac终端可以看到,本机hostname是bogon,于是我们重设hostname,命令如下:

$ sudo scutil --set HostName bianxh
$ sudo scutil --set LocalHostName bianxh

然后修改hosts文件,

bogon:redis-3.0.7 bianxh$ subl /etc/hosts

在末位新增两行:

127.0.0.1 bianxh
::1 bianxh

重新运行上面的java代码,可以看到ip地址正常了:

本机名称是:bianxh
本机的ip是 :127.0.0.1

接下来,通过dubbo注册zookeeper,可以看到console输出的注册地址就正常了,变为局域网内的本机地址。

2017-09-16-微信开发:scope参数错误或没有scope权限解决方法

1、确保请求参数的顺序(注意response_type和scope前后顺序):

scope为snsapi_base https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect

scope为snsapi_userinfo https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

2、确保在合适的公众号上操作,比如我在正式公众服务号上进入一个需要经过OAuth的链接,却在代码中走的测试号的appid,那也会提示这个错误。

3、如果还是不行,那再到微信管理后台确认下,修改“网页帐号-->网页授权获取用户基本信息”,使其生效,如图:

参考文档:

微信公众平台

微信公众平台测试号管理配置页面。

2017-09-16-微信服务号绑定踩过的坑

首先绑定域名,方法:

设置-->公众号设置-->功能设置

然后可以设置业务域名、JS接口安全域名、网页授权域名。

将文件MP_***.txt(点击下载)例如wx.qq.com/MP_.txt;若填写路径,将文件放置在路径目录下,例如wx.qq.com/mp/.txt),并确保可以访问。

将txt拷贝到Tomcat下域名对应的路径下,配置server.xml,路径:C:\apache-tomcat-7.0.79\webapps\helloworld

2017-09-16-点击div标签下的href不跳转到目标页面,而是跳转到首页的问题

a标签如果不做任何定义,点击其中的元素时,会默认跳转到主页。

<a href="" class="stars">
...
</a>

上面点击star星,就会跳转到路径"/"下,解决办法如下:

<a href="javascript:void(0)" class="stars">
...
</a>

原理是:单击此处什么也不要做,让此区域下方的组件处理href事件。

2017-09-16-简单的整数或者小数判断正则表达式

/**
 * 正则表达式规则:-号出现0或者1次,0-9出现多次,小数点出现0或者1次,0-9出现多次
 * @param str
 * @return
 */
public static boolean isNumeric(String str) {
	if (str != null && !str.isEmpty()) {
		Pattern pattern = Pattern.compile("-?[0-9]*.?[0-9]*");
		Matcher isNum = pattern.matcher(str);
		if (isNum.matches()) {
			return true;
		}
	}
	return false;
}

2017-09-16-获取页面div下级的innerHtml

<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript">

function getValue()
{
var x=document.getElementById("myHeader")
var y= $("#test #myHeader")[0];
alert(x.innerHTML);
alert(y.innerHTML);
}
</script>
</head>
<body>

<div id="test">
<h1 id="myHeader" onclick="getValue()">这是标题</h1>
</div>

<p>点击标题,会提示出它的值。</p>

</body>
</html>

2017-09-16-获取高德地图定位的js源码

Key是我申请的,可以直接用。

<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
	content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>浏览器定位</title>
<link rel="stylesheet"
	href="http://cache.amap.com/lbs/static/main1119.css" />
<script type="text/javascript"
	src="http://webapi.amap.com/maps?v=1.3&key=b6df90d2cfda9508fb2106ae6273d7ea"></script>
<script type="text/javascript"
	src="http://cache.amap.com/lbs/static/addToolbar.js"></script>
<body>
	<div id='container'></div>
	<div id="tip"></div>
	<script type="text/javascript">  
    var map, geolocation;  
    //加载地图,调用浏览器定位服务  
    map = new AMap.Map('container', {  
        resizeEnable: true  
    });  
    map.plugin('AMap.Geolocation', function() {  
        geolocation = new AMap.Geolocation({  
            enableHighAccuracy: true,//是否使用高精度定位,默认:true  
            timeout: 10000,          //超过10秒后停止定位,默认:无穷大  
            buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)  
            zoomToAccuracy: true,      //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false  
            buttonPosition:'RB'  
        });  
        map.addControl(geolocation);  
        geolocation.getCurrentPosition();  
        AMap.event.addListener(geolocation, 'complete', onComplete);//返回定位信息  
        AMap.event.addListener(geolocation, 'error', onError);      //返回定位出错信息  
    });  
    //解析定位结果  
    function onComplete(data) {  
        var str=['定位成功'];  
        str.push('经度:' + data.position.getLng());  
        str.push('纬度:' + data.position.getLat());  
        if(data.accuracy){  
             str.push('精度:' + data.accuracy + ' 米');  
        }//如为IP精确定位结果则没有精度信息  
        str.push('是否经过偏移:' + (data.isConverted ? '是' : '否'));  

        var point = data.position.getLng()+","+data.position.getLat();  
        poiToaddress(point);  

        document.getElementById('tip').innerHTML = str.join('<br>');  
    }  
    //解析定位错误信息  
    function onError(data) {  
        document.getElementById('tip').innerHTML = '定位失败';  
    }  

//坐标点转地址  
function poiToaddress(poi) {  
    AMap.plugin(["AMap.Geocoder"], function () {  
        var geocoder = new AMap.Geocoder({  
            city: "0315", //城市,默认:“全国”  
            radius: 500 //范围,默认:500,以已知坐标为中心点,radius为半径,返回范围内兴趣点和道路信息   
        });  
        geocoder.getAddress(poi, function (status, result) {  
            if (status === 'complete' && result.info === 'OK') {  
                var address = result.regeocode.formattedAddress; //返回地址描述  
                address2point(address);   
                console.log("地址::"+address); 
                alert("当前地址:" + address);
            }  
        });  
    })  
}  

//地址转坐标  
function address2point(address) {  
    AMap.plugin(["AMap.Geocoder"], function () {  
        var geocoder = new AMap.Geocoder({  
            city: "0315", //城市,默认:“全国”  
            radius: 500 //范围,默认:500,以已知坐标为中心点,radius为半径,返回范围内兴趣点和道路信息   
        });  
        geocoder.getLocation(address, function (status, result) {  
            if (status === 'complete' && result.info === 'OK') {  
                var geocode = result.geocodes[0];  
                var resultStr = geocode.location.lng + "," + geocode.location.lat;  
                console.log(resultStr);  
                alert("resultStr" + resultStr);
            }  
        });  
    })  
}  
</script>
</body>
</html>

2017-09-16-解析微信xml消息使用的jar包

使用XStream,下载地址:XStream - Download

从里面找上门的3个jar包并加载。

image.png

2017-09-16-css图片资源加载失败?

之前的css代码是这样写(资源使用的是绝对路径):

background: url(resources/img/star2.png) no-repeat !important;

结果报资源找不见:

zepto.min.js:1 GET http://localhost:8080/helloworld/resources/static/css/resources/img/star2.png 404 (Not Found)

图片加载失败,找了一下,这个位置其实是有这个文件的:

改成相对路径就好了:

background: url(../img/star2.png) no-repeat !important;

2017-09-16-Eclipse-Java-EE找不到JSTL

在Eclipse下提示:

Can not find the tag library descriptor for “http://java.sun.com/jsp/jstl/core” 

访问对应的页面时,console控制台提示:

The absolute uri: [http://java.sun.com/jsp/jstl/core] cannot be resolved in either web.xml or the jar files deployed with this application

从Tomcat官网去下载JSTL jar包,链接是:Apache Taglibs Downloads

注意这4个都下载:

拷贝下载后的文件到tomcat lib下,如图:

右键点击Eclipse下对应的Project,Build path --> Config Build Path,进入Liabraries标签页,添加Liabrary,如下:

2017-09-16-Eclipse-Java-EE-IDE修改web项目部署路径

如果添加了项目到tomcat下那么按照下面的步骤进行配置

1、找到Server面板,右击当前的那个Tomcat,先remove掉其中所有的工程。

2、再右击那个Tomcat,选择Clean,清空一下。

注意:只有clean之后,才能编辑Server Locations。

3、双击那个Tomcat,会打开属性面板,找到左边第二个Server Locations。

选择第二个会在Tomcat路径下创建一个名为wtpwebapps文件夹,存放Tomcat发布的web项目;

选择第三个,你可以在Server Path中输入你想要的路径,保存即可。

image.png

然后右击Server,Add and Remove...就可以添加项目来试试看了。

2017-09-16-EL表达式,结果取整

<fmt:formatNumber type="number" value="${8/7}" maxFractionDigits="0"/>

其中maxFractionDigits="0"表示保留0位小数,这样就可以实现取整了。同时这里是按照四舍五入的规则来进行取整的。如果是${2/6}结果就是0,如果是${6/7}结果就是1。 在这里我们同样也可以设置保留n为小数,仅需要设置maxFractionDigits="n"即可实现。

2017-09-16-Form表单提交后不跳转到新页面

去掉form表单的这个属性:

target='hiddenwin'

2017-09-16-hibernate-hql实战小结

表关联查询汇总排名

  • 查询报名记录
select o.id as id, o.name as org_name from t_sign_up t, t_student s, t_org o where t.student_id = s.id and s.org_id=o.id

结果如下,可以看到1个单位下有4条报名记录,另外一个单位下有2条:

image.png

  • 汇总报名记录,并按照统计次数降序:
select o.id as id, o.name as org_name, count(t.id) as org_count from t_sign_up t, t_student s, t_org o where t.student_id = s.id and s.org_id=o.id group by o.name order by org_count desc

效果如下:

image.png

如上sql,在Mysql测试成功,移植到hql时,需要给经过重名的orgCount加上引号,否则会报出现报错,报找不到orgCount字段,如下:

select o.id as id, o.name as orgName, count(t.id) as orgCount from SignUp t, Student s, Org o where t.studentId = s.id and s.orgId=o.id group by o.name order by 'orgCount' desc

数据比较多的时候,需要进行分页展示,相关的,我们要构建countQuery来查询结果总数目,在如上的sql上进行统计,如下:

String countQuery = "select count(*) from (select o.id as id, o.name as orgName, count(t.id) as orgCount from SignUp t, Student s, Org o where t.studentId = s.id and s.orgId=o.id group by o.name) as result"

执行过程中,会报错:

九月 08, 2017 3:22:22 下午 org.hibernate.hql.ast.ErrorCounter reportError
严重: line 1:61: unexpected token: count
ERROR 2017 09 08 15:22:22 com.opensymphony.xwork2.util.logging.commons.CommonsLogger.error(CommonsLogger.java:42) Exception occurred during processing request: unexpected token: ( near line 1, column 22 [select count(*) from (select o.id as id, o.name as orgName, count(t.id) as orgCount from com.lmscn.lms.model.SignUp t, com.lmscn.lms.model.Student s, com.lmscn.lms.model.Org o where t.studentId = s.id and s.orgId=o.id group by o.name) as result]; nested exception is org.hibernate.hql.ast.QuerySyntaxException: unexpected token: ( near line 1, column 22 [select count(*) from (select o.id as id, o.name as orgName, count(t.id) as orgCount from com.lmscn.lms.model.SignUp t, com.lmscn.lms.model.Student s, com.lmscn.lms.model.Org o where t.studentId = s.id and s.orgId=o.id group by o.name) as result] 
org.springframework.orm.hibernate3.HibernateQueryException: unexpected token: ( near line 1, column 22 [select count(*) from (select o.id as id, o.name as orgName, count(t.id) as orgCount from com.lmscn.lms.model.SignUp t, com.lmscn.lms.model.Student s, com.lmscn.lms.model.Org o where t.studentId = s.id and s.orgId=o.id group by o.name) as result]; nested exception is org.hibernate.hql.ast.QuerySyntaxException: unexpected token: ( near line 1, column 22 [select count(*) from (select o.id as id, o.name as orgName, count(t.id) as orgCount from com.lmscn.lms.model.SignUp t, com.lmscn.lms.model.Student s, com.lmscn.lms.model.Org o where t.studentId = s.id and s.orgId=o.id group by o.name) as result]
	at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:660)
	at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
	at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
	at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
	at javacommon.base.BaseHibernateDao$PageQueryUtils.pageQuery(BaseHibernateDao.java:151)
	at javacommon.base.BaseHibernateDao$PageQueryUtils.access$1(BaseHibernateDao.java:147)
	at javacommon.base.BaseHibernateDao.pageQuery(BaseHibernateDao.java:121)

还是hibernate解析过程中出了问题,主要是对中间产生的result虚拟临时表没有办法识别,难道这就要放弃,只能使用JDBC来进行分页了? 不然!经过思考,我们统计count的目的就是为了得到总数,也有一个折中的办法,如下: 使用distinct进行去重,这样查到两条记录(也就是说共有两个单位),如下:

select count(distinct o.id) from t_sign_up t, t_student s, t_org o where t.student_id = s.id and s.org_id=o.id

image.png 转换成hql,如下:

String countQuery = "select count(distinct o.id) from SignUp t, Student s, Org o where t.studentId = s.id and s.orgId=o.id";

结果如下:

image.png

可以看到,分页成功了:

image.png

2017-09-16-java去除HTML标签

   /**
     * 过滤html标签
     * @param htmlStr
     * @return
     */
    public synchronized static String delHTMLTag(String htmlStr){ 
        String regEx_script="<script[^>]*?>[\\s\\S]*?<\\/script>"; //定义script的正则表达式 
        String regEx_style="<style[^>]*?>[\\s\\S]*?<\\/style>"; //定义style的正则表达式 
        String regEx_html="<[^>]+>"; //定义HTML标签的正则表达式 

        Pattern p_script=Pattern.compile(regEx_script,Pattern.CASE_INSENSITIVE); 
        Matcher m_script=p_script.matcher(htmlStr); 
        htmlStr=m_script.replaceAll(""); //过滤script标签 

        Pattern p_style=Pattern.compile(regEx_style,Pattern.CASE_INSENSITIVE); 
        Matcher m_style=p_style.matcher(htmlStr); 
        htmlStr=m_style.replaceAll(""); //过滤style标签 

        Pattern p_html=Pattern.compile(regEx_html,Pattern.CASE_INSENSITIVE); 
        Matcher m_html=p_html.matcher(htmlStr); 
        htmlStr=m_html.replaceAll(""); //过滤html标签 

        return htmlStr.trim(); //返回文本字符串 
    } 

2017-09-16-java字符串保存到Mysql中文乱码问题

最近遇到java中设置中文字符串到Mysql出现中文乱码问题。 之前的数据库链接是:

jdbcUrl=jdbc:mysql://192.168.1.123:3306/mydb?zeroDateTimeBehavior=convertToNull

改成如下就好了:

jdbcUrl=jdbc:mysql://192.168.1.123:3306/mydb?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8

2017-09-16-java获取当天24点

Calendar calendar = Calendar.getInstance();
	    calendar.setTime(new Date());
	    calendar.set(Calendar.HOUR_OF_DAY, 24);
	    calendar.set(Calendar.MINUTE, 0);
	    calendar.set(Calendar.SECOND, 0);
 Date start = calendar.getTime();

2017-09-16 Java 获取指定日期之前或者之后的多少分钟

/**
     * 计算指定日期之前或者之后的多少分钟
     * @param date
     * @param minute
     * @return
     */
    public static String getTimeByMinute(Date date, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());

    }

2017-09-16-java-获取编码转换为utf-8

try {
	address = new String(address.getBytes("ISO-8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}

2017-09-16 微信消息解析用到的Java enum 枚举

微信取得消息类型的时候会报错:

// 取得消息类型  
String msgType = inputMsg.getMsgType();
WXEventType.MsgType key = WXEventType.MsgType.valueOf(msgType);
switch (key) {
case WXEventType.MsgType.event:

	break;

default:
	break;
}

报错如下:

The qualified case label WXEventType.MsgType.event must be replaced with the unqualified enum constant event

定义中是有的,如下:

// / <summary>
	// / 消息类型枚举
	// / </summary>
	public enum MsgType {
		// / <summary>
		// /文本类型
		// / </summary>
		text,
		// / <summary>
		// / 图片类型
		// / </summary>
		IMAGE,
		// / <summary>
		// / 语音类型
		// / </summary>
		VOICE,
		// / <summary>
		// / 视频类型
		// / </summary>
		VIDEO,
		// / <summary>
		// / 地理位置类型
		// / </summary>
		location,
		// / <summary>
		// / 链接类型
		// / </summary>
		LINK,
		// / <summary>
		// / 事件类型
		// / </summary>
		event,
		// / <summary>
		// / 小视频
		// / </summary>
		SHORTVIDEO
	}
...
}

解决办法,删除WXEventType.MsgType,如下:

// 取得消息类型  
String msgType = inputMsg.getMsgType();
WXEventType.MsgType key = WXEventType.MsgType.valueOf(msgType);
switch (key) {
case event:

	break;

default:
	break;
}

2017-09-16-Java-Integer自增

Java Integer 类的对象创建之后他的值就不能被修改,在 Integer ++ 的时候Integer是创建一个新的对象 如果要自增,怎么办呢? 可以这样:

private void test(AtomicInteger index) {
  signUpStudentNum.getAndIncrement();
}

2017-09-16-JFinal传递map到JSP页面中

  1. 封装map
Map<String, Object> responseInfoMap = new HashMap<String, Object>();
responseInfoMap.put("testInfo", testInfo);
  1. 设置属性
setAttr("commentListInfo", responseInfoMap);
renderJsp("/WEB-INF/jsp/helloworld/hello.jsp");
  1. JSP页面通过EL表达式获取
${commentListInfo.testInfo.title}

2017-09-16-JFinal使用WebSocket

1、先建立一个Maven项目,如果是老项目,也可转成maven项目,参见我之前写的一篇帮助: Myeclipse普通java项目转maven项目

2、pom.xml引用相关jar包,1.7之后支持,配置如下:

	<dependencies>
<!--  		<dependency>
			<groupId>javax.websocket</groupId>
			<artifactId>javax.websocket-api</artifactId>
			<version>1.1</version>
			<scope>provided</scope>
		</dependency> -->
 		<dependency>
			<groupId>javax</groupId>
			<artifactId>javaee-api</artifactId>
			<version>7.0</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

tomcat7和jave EE 1.7都支持,注意引用一个,不要重复。

3、编写事件拦截处理代码: ZhiWebSocketHandler.java

package com.yyxz.main;

import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jfinal.handler.Handler;
import com.jfinal.kit.StrKit;

public class ZhiWebSocketHandler extends Handler {

	private Pattern filterUrlRegxPattern;
	
	public ZhiWebSocketHandler(String filterUrlRegx) {
		if (StrKit.isBlank(filterUrlRegx))
			throw new IllegalArgumentException("The para filterUrlRegx can not be blank.");
		filterUrlRegxPattern = Pattern.compile(filterUrlRegx);
	}
	@Override
	public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) {
		// TODO Auto-generated method stub
		if (filterUrlRegxPattern.matcher(target).find())
			return ;
		else {
			next.handle(target, request, response, isHandled);
		}
	}

}

在JFinal Config中进行注册:

public class DemoConfig extends JFinalConfig {
//...
	public void configHandler(Handlers me) {
		me.add(new ContextPathHandler("ctx"));
		me.add(new ZhiWebSocketHandler("^/websocket"));
// 也可以使用UrlSkipHandler,就不用编写Handler处理类了
//		me.add(new UrlSkipHandler("^/websocket", false));
	}
//...
}

4、后台监听websocket代码: WebSocketController.java

package com.yyxz.controller;

import java.io.IOException;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/websocket")
public class WebSocketController {
	public WebSocketController() {
		System.out.println(" WebSocket init~~~");
	}

	@OnOpen
	public void onOpen(Session session) {
		System.out.println("onOpen");
	}

	@OnClose

	public void onClose(Session session) {
		System.out.println("onClose");
	}
	
//	@OnError
//	public void onError(Session session) {
//		System.out.println("onError");
//	}

	@OnMessage
	public void onMessage(String requestJson, Session session)
			throws IOException {
		requestJson = "一一小知回复:" + requestJson; 
		System.out.println(requestJson);
		session.getBasicRemote().sendText(requestJson);
	}
}

5、在前端发起,编写页面: webSocketTest.jsp

<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- for HTML5 -->
<title>Java后端WebSocket的Tomcat实现</title>
</head>
<body>
	Welcome
	<br />
	<input id="text" type="text" />
	<button onclick="send()">发送消息</button>
	<hr />
	<button onclick="closeWebSocket()">关闭WebSocket连接</button>
	<hr />
	<div id="message"></div>
</body>

<script type="text/javascript">
    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://localhost:8080/yiyixiaozhi/websocket");
    }
    else {
        alert('当前浏览器 Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function () {
        setMessageInnerHTML("WebSocket连接发生错误");
    };

    //连接成功建立的回调方法
    websocket.onopen = function () {
        setMessageInnerHTML("WebSocket连接成功");
    }

    //接收到消息的回调方法
    websocket.onmessage = function (event) {
        setMessageInnerHTML(event.data);
    }

    //连接关闭的回调方法
    websocket.onclose = function () {
        setMessageInnerHTML("WebSocket连接关闭");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
        closeWebSocket();
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //关闭WebSocket连接
    function closeWebSocket() {
        websocket.close();
    }

    //发送消息
    function send() {
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
</script>
</html>

结果如下:

image.png

image.png

2017-09-16-JFinal-Controller中forwardAction的使用

请求转发使用forwardAction,请求参数会带过去,不要在请求中带参数,比如:

forwardAction("/api/test/toPage?openId=1");

正确的写法是:

forwardAction("/api/test/toPage");

2017-09-16-js中的“中文汉字”传到到java端乱码问题解决

使用的是高德地图,获取到中文地址后,传递到java端显示乱码,如何解决呢?

		String address = getPara("address");
		try {
			address = new String(address.getBytes("ISO-8859-1"),"UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

2017-09-16-Mac批量重命名文件

统一给文件加前缀,示例如下:

bianxh:2 bianxh$ ll
total 264
drwxr-xr-x  33 bianxh  staff  1122  9 16 13:43 .
drwxr-xr-x   9 bianxh  staff   306  9 16 13:44 ..
-rw-r--r--@  1 bianxh  staff   397  9 16 12:26 EL表达式,结果取整.md
-rw-r--r--@  1 bianxh  staff   801  9 16 12:26 Eclipse-Java-EE-IDE修改web项目部署路径.md
-rw-r--r--@  1 bianxh  staff  2607  9 16 12:27 小结:使用正则表达式提取时间中的数字.md
bianxh:2 bianxh$ for var in *.md; do mv "$var" "2017-09-16-${var%.md}.md";  done
bianxh:2 bianxh$ ll
total 264
drwxr-xr-x  33 bianxh  staff  1122  9 16 13:44 .
drwxr-xr-x   9 bianxh  staff   306  9 16 13:44 ..
-rw-r--r--@  1 bianxh  staff   397  9 16 12:26 2017-09-16-EL表达式,结果取整.md
-rw-r--r--@  1 bianxh  staff   801  9 16 12:26 2017-09-16-Eclipse-Java-EE-IDE修改web项目部署路径.md
-rw-r--r--@  1 bianxh  staff  2607  9 16 12:27 2017-09-16-小结:使用正则表达式提取时间中的数字.md

还有替换啊什么的,一些高级用法,参见: https://my.oschina.net/musings/blog/380939

比如,假如文件名称中有多个后缀怎么办呢?如下:

bianxh:一一小知的副本 bianxh$ ll
total 336
drwxr-xr-x  32 bianxh  staff   1088  9 16 14:04 .
drwxr-xr-x   6 bianxh  staff    204  9 16 13:59 ..
-rw-r--r--@  1 bianxh  staff   6148  9 16 13:21 .DS_Store
-rw-r--r--@  1 bianxh  staff    501  9 16 12:26 2015-09-16-git代码仓库如何迁移.md
-rw-r--r--@  1 bianxh  staff   3149  9 16 12:26 2015-12-18-读笔记:公司高速发展是对团队最好的管理.md.md
-rw-r--r--@  1 bianxh  staff   3014  9 16 12:26 2015-6-2-2-如何“有效地一对一会谈”.md.md
-rw-r--r--@  1 bianxh  staff   7447  9 16 12:26 2016-09-16-OSChina git 代码fork及PR指南.md.md
-rw-r--r--@  1 bianxh  staff    163  9 16 13:24 2016-09-16-空谷幽兰-第六章-登天之道-第二节.md.md
-rw-r--r--@  1 bianxh  staff   2159  9 16 12:26 2016-1-10-吐槽招商银行营业厅,赞一下微信客服.md
-rw-r--r--@  1 bianxh  staff   3898  9 16 12:26 2016-1-16-Hunt.md
-rw-r--r--@  1 bianxh  staff   1854  9 16 12:26 2016-1-17:喜欢?电子书:纸质书.md
-rw-r--r--@  1 bianxh  staff   3708  9 16 12:26 2016-1-25:新时代的企业架构师.md
-rw-r--r--@  1 bianxh  staff   1298  9 16 12:26 2016-1-26:实践应当从业务需求出发.md
-rw-r--r--@  1 bianxh  staff   1676  9 16 12:26 2016-1-28:图像压缩技术?Lena.md
-rw-r--r--@  1 bianxh  staff    661  9 16 12:26 2016-1-28:项目经理?产品经理.md
-rw-r--r--@  1 bianxh  staff   3076  9 16 12:26 2016-10-11-内置对象.md.md
-rw-r--r--@  1 bianxh  staff    572  9 16 12:26 2016-12-1-空谷幽兰-第六章-登天之道-第三节.md.md
-rw-r--r--@  1 bianxh  staff   2464  9 16 12:26 2016-12-5-坚持很难.md.md
-rw-r--r--@  1 bianxh  staff   1298  9 16 12:26 2016-2-5-对OKRs粗浅的理解.md.md
-rw-r--r--@  1 bianxh  staff   1129  9 16 12:26 2016-4-25:软件模块的3项职责.md
-rw-r--r--@  1 bianxh  staff   2126  9 16 12:26 2016-4-27:我眼中“项目经理”需要知道的.md.md
-rw-r--r--@  1 bianxh  staff   8678  9 16 12:26 2016-5-10-“深淘滩,低作堰”-华为公司的战略创新和机制创新.md
-rw-r--r--@  1 bianxh  staff    760  9 16 12:26 2016-5-3-曲江海洋馆简游.md.md
-rw-r--r--@  1 bianxh  staff  10040  9 16 12:26 2016-5-4-樊登速读-重新定义公司.md.md
-rw-r--r--@  1 bianxh  staff    802  9 16 12:26 2016-6-14-端午节日小记.md.md
-rw-r--r--@  1 bianxh  staff    422  9 16 12:26 2016-6-15:刺猬心态.md
-rw-r--r--@  1 bianxh  staff    829  9 16 12:26 2016-6-16:球队思维.md
-rw-r--r--@  1 bianxh  staff   1011  9 16 12:26 2016-6-19:没有什么不同.md
-rw-r--r--@  1 bianxh  staff   6380  9 16 12:26 2016-7-6-OKR管理方法.md
-rw-r--r--@  1 bianxh  staff   7415  9 16 12:26 2016-9-9-[焦英俊]-阿里巴巴店铺的十年技术演变之路.md.md
-rw-r--r--@  1 bianxh  staff   8300  9 16 12:26 2017-2-1-每个程序员都应读的10本经典书籍.md.md
-rw-r--r--@  1 bianxh  staff   8833  9 16 13:25 2017-4-1-JSP.md.md
bianxh:一一小知的副本 bianxh$ rename 's/\.md.md$/\.md/' *.md
bianxh:一一小知的副本 bianxh$ ll
total 336
drwxr-xr-x  32 bianxh  staff   1088  9 16 14:05 .
drwxr-xr-x   6 bianxh  staff    204  9 16 13:59 ..
-rw-r--r--@  1 bianxh  staff   6148  9 16 13:21 .DS_Store
-rw-r--r--@  1 bianxh  staff    501  9 16 12:26 2015-09-16-git代码仓库如何迁移.md
-rw-r--r--@  1 bianxh  staff   3149  9 16 12:26 2015-12-18-读笔记:公司高速发展是对团队最好的管理.md
-rw-r--r--@  1 bianxh  staff   3014  9 16 12:26 2015-6-2-2-如何“有效地一对一会谈”.md
-rw-r--r--@  1 bianxh  staff   7447  9 16 12:26 2016-09-16-OSChina git 代码fork及PR指南.md
-rw-r--r--@  1 bianxh  staff    163  9 16 13:24 2016-09-16-空谷幽兰-第六章-登天之道-第二节.md
-rw-r--r--@  1 bianxh  staff   2159  9 16 12:26 2016-1-10-吐槽招商银行营业厅,赞一下微信客服.md
-rw-r--r--@  1 bianxh  staff   3898  9 16 12:26 2016-1-16-Hunt.md
-rw-r--r--@  1 bianxh  staff   1854  9 16 12:26 2016-1-17:喜欢?电子书:纸质书.md
-rw-r--r--@  1 bianxh  staff   3708  9 16 12:26 2016-1-25:新时代的企业架构师.md
-rw-r--r--@  1 bianxh  staff   1298  9 16 12:26 2016-1-26:实践应当从业务需求出发.md
-rw-r--r--@  1 bianxh  staff   1676  9 16 12:26 2016-1-28:图像压缩技术?Lena.md
-rw-r--r--@  1 bianxh  staff    661  9 16 12:26 2016-1-28:项目经理?产品经理.md
-rw-r--r--@  1 bianxh  staff   3076  9 16 12:26 2016-10-11-内置对象.md
-rw-r--r--@  1 bianxh  staff    572  9 16 12:26 2016-12-1-空谷幽兰-第六章-登天之道-第三节.md
-rw-r--r--@  1 bianxh  staff   2464  9 16 12:26 2016-12-5-坚持很难.md
-rw-r--r--@  1 bianxh  staff   1298  9 16 12:26 2016-2-5-对OKRs粗浅的理解.md
-rw-r--r--@  1 bianxh  staff   1129  9 16 12:26 2016-4-25:软件模块的3项职责.md
-rw-r--r--@  1 bianxh  staff   2126  9 16 12:26 2016-4-27:我眼中“项目经理”需要知道的.md
-rw-r--r--@  1 bianxh  staff   8678  9 16 12:26 2016-5-10-“深淘滩,低作堰”-华为公司的战略创新和机制创新.md
-rw-r--r--@  1 bianxh  staff    760  9 16 12:26 2016-5-3-曲江海洋馆简游.md
-rw-r--r--@  1 bianxh  staff  10040  9 16 12:26 2016-5-4-樊登速读-重新定义公司.md
-rw-r--r--@  1 bianxh  staff    802  9 16 12:26 2016-6-14-端午节日小记.md
-rw-r--r--@  1 bianxh  staff    422  9 16 12:26 2016-6-15:刺猬心态.md
-rw-r--r--@  1 bianxh  staff    829  9 16 12:26 2016-6-16:球队思维.md
-rw-r--r--@  1 bianxh  staff   1011  9 16 12:26 2016-6-19:没有什么不同.md
-rw-r--r--@  1 bianxh  staff   6380  9 16 12:26 2016-7-6-OKR管理方法.md
-rw-r--r--@  1 bianxh  staff   7415  9 16 12:26 2016-9-9-[焦英俊]-阿里巴巴店铺的十年技术演变之路.md
-rw-r--r--@  1 bianxh  staff   8300  9 16 12:26 2017-2-1-每个程序员都应读的10本经典书籍.md
-rw-r--r--@  1 bianxh  staff   8833  9 16 13:25 2017-4-1-JSP.md

2017-09-16-MAC通过Microsoft-Remote-Desktop控制windows按键找回

由于MAC默认将F1、F2等按键使用了。所以正常情况下,需要通过fn+F1、F2等实现正常windows系统上的按键效果。

这个按键功能如果要和windows体验一致,操作如下:

系统偏好设置-->键盘:

但是发现还有F11、F12无法使用,比如在Chrome调试过程中,由于要使用F12键来调出开发者工具。解决办法如下:

好,我们来在Mac下远程连接Windows,打开Chrome浏览器试试:

2017-09-16-Mac-下安装Java-EE

下载的是:sh文件

bianxh:java_ee_sdk bianxh$ sudo chmod +x ./java_ee_sdk-7-jdk7-macosx-x64-ml.sh
bianxh:java_ee_sdk bianxh$ ./java_ee_sdk-7-jdk7-macosx-x64-ml.sh 
This program requires DISPLAY environment variable to be set.
Please re-run after assigning an appropriate value to DISPLAY.
bianxh:java_ee_sdk bianxh$ DISPLAY=:0 ./java_ee_sdk-7-jdk7-macosx-x64-ml.sh 
Extracting the installer archive...
Extracting the installer runtime...
Extracting the installer resources...
Extracting the installer metadata...

Welcome to GlassFish installer

Using the user defined JAVA_HOME : /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home
Entering setup...
SwixML 1.5 (#144)

2017-09-16-Mac-安装多个jdk踩过的坑

我是先安装了jdk 8,然后安装了jdk7,通过命令可以看到,默认链接的是jdk8

bianxh:Versions bianxh$ which java
/usr/bin/java
bianxh:Versions bianxh$ ls -l /usr/bin/java
lrwxr-xr-x  1 root  wheel  74  9 22  2016 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
bianxh:Versions bianxh$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home
bianxh:Versions bianxh$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

配置~/.bash_profile

export PATH=${PATH}:/Users/bianxh/Library/Android/sdk//platform-tools
export PATH=${PATH}:/Users/bianxh/Library/Android/sdk//tools
export PATH=${PATH}:/usr/local/apache-tomcat-7.0.77/bin
export JAMES_SRC_HOME=/usr/local/james-project/james-project
# 设置 JDK 8
export JAVA_8_HOME=$(/usr/libexec/java_home -v 1.8)
# 设置 JDK 7
export JAVA_7_HOME=$(/usr/libexec/java_home -v 1.7)
export JAVA_HOME=$JAVA_7_HOME
#alias命令动态切换JDK版本
alias jdk7="export JAVA_HOME=$"JAVA_7_HOME"
alias jdk8="export JAVA_HOME=$"JAVA_8_HOME"
alias subl="'/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl'"
alias ll='ls -al'

使用命令生效配置:

bianxh:Versions bianxh$ source ~/.bash_profile 

现在查看:

bianxh:Versions bianxh$ java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
bianxh:Versions bianxh$ /usr/libexec/java_home -v 1.7
/Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home
bianxh:Versions bianxh$ /usr/libexec/java_home -v 1.8
/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home

以后就可以通过命令自由切换了,效果如下:

bianxh:libexec bianxh$ jdk8
bianxh:libexec bianxh$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
bianxh:libexec bianxh$ jdk7
bianxh:libexec bianxh$ java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

当然,如果用eclipse,注意修改JAVA_HOME,在~/.bash_profile中修改。

2017-09-16-mac-chrome-开发者工具-快捷键

开发者工具:option+command+i javascript控制台:option+command+j 或者按option+command+c也可以打开

2017-09-16-Myeclipse普通java项目转maven项目

1、先解决在项目上右键单击,没有出现Configure菜单的问题,因为此菜单的下级有Convert to Maven Project 解决办法: window-->Preferences-->General-->Capabilities-->My Eclipse Standard Tools-->Advenced,勾选如下两项:

image.png

2、转maven项目,自己输入

<name>yiyixiaozhi-maven</name>
<description>maven配置</description>

3、以要使用websoket为例,添加依赖关系

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>yiyixiaozhi</groupId>
	<artifactId>yiyixiaozhi</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>yiyixiaozhi-maven</name>
	<description>maven配置</description>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>javax.websocket</groupId>
			<artifactId>javax.websocket-api</artifactId>
			<version>1.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax</groupId>
			<artifactId>javaee-api</artifactId>
			<version>7.0</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
</project>

备注:自己也可以设定maven的配置文件,settings.xml

image.png 建立一个C:\Users\zqzx.m2\settings.xml,源码如下:

<?xml version="1.0"?>  
<settings>  
<localRepository>~/.m2/repository</localRepository><!--需要改成自己的maven的本地仓库地址-->  
    <mirrors>  
        <mirror>  
            <id>alimaven</id>  
            <name>aliyun maven</name>  
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>  
            <mirrorOf>central</mirrorOf>  
        </mirror>  
    </mirrors>  
  <profiles>  
    <profile>  
       <id>nexus</id>   
        <repositories>  
            <repository>  
                <id>nexus</id>  
                <name>local private nexus</name>  
                <url>http://maven.oschina.net/content/groups/public/</url>  
                <releases>  
                    <enabled>true</enabled>  
                </releases>  
                <snapshots>  
                    <enabled>false</enabled>  
                </snapshots>  
            </repository>  
        </repositories>  
          
        <pluginRepositories>  
            <pluginRepository>  
            <id>nexus</id>  
            <name>local private nexus</name>  
            <url>http://maven.oschina.net/content/groups/public/</url>  
            <releases>  
                <enabled>true</enabled>  
            </releases>  
            <snapshots>  
                <enabled>false</enabled>  
            </snapshots>  
            </pluginRepository>  
        </pluginRepositories>  
    </profile></profiles>  
</settings>  

下载成功了,如下:

image.png

2017-09-16-Mysql获取表中某个Datetime字段那天24点之前的数据

select * from t_class_info where date_format(now(),'%Y-%m-%d-%H-%i-%S')>=begin_date and date_format(now(),'%Y-%m-%d-%H-%i-%S')<=date_format(end_date,'%Y-%m-%d-24-00-00')

关键是这句:

date_format(now(),'%Y-%m-%d-%H-%i-%S')<=date_format(end_date,'%Y-%m-%d-24-00-00')

2017-09-16-Mysql-更新枚举enum类型

表定义如下:

CREATE TABLE `t_seat` (                                                                    
          `id` bigint(20) NOT NULL,                                                                
         ...                                
          `type` enum('seat','passage') DEFAULT NULL COMMENT '座位类型(座位、过道)',  
         ...                                                
          PRIMARY KEY (`id`),                                                                      
          KEY `place_id` (`place_id`)                                                              
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='座位表'      

如果要更新type,使用如下语句:

update t_seat a set a.type = 'seat' where a.type = ''

不能这么使用:

update t_seat a set a.type = 'seat' where a.type is null

2017-09-16-Mysql-获取某个时间之后一段时间的方法

select * from t_class_info where place_id = 10 and date_format(now(),'%Y-%m-%d-%H-%i-%S')>=begin_date and date_format(now(),'%Y-%m-%d-%H-%i-%S')<=date_add(end_date, interval '1 00:00:00' day_second)

参考:MySQL:日期函数、时间函数总结 - ggjucheng - 博客园

2017-09-16-web开发入门之中文乱码

假如jsp页面使用了utf-8编码。但是声明如下:

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>

实际运行过程就会中文乱码问题,改成如下就好了:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

2017-09-16-Windows查看端口占用

解决root账号无法登陆的问题: 修改my-default.ini,重命名为my.ini,修改文件内容:

# basedir = C:\Program Files\MySQL\MySQL Server 5.7
# datadir = C:\Program Files\MySQL\MySQL Server 5.7\data

在“C:\Program Files\MySQL\MySQL Server 5.7”下创建data文件夹 管理员运行cmd,输入:mysqld -install,显示安装成功;再输入:net start mysql 输入:mysqld --initialize --user=mysql --console 得到临时密码 启动服务net start mysql; 进入mysql命令下:mysql -u root -p,输入刚刚的密码; 更新root密码:mysql> set password for root@localhost = password('123');

解决无法在局域网通过sqlyog客户端链接mysql server的问题:

mysql>use mysql;
mysql>update user set host = '%' where user = 'root';

重启mysql服务后生效。

2017-9-13-Ubuntu环境初始化安装Mysql并配置外网访问

1、安装:

sudo apt-get install mysql-server

2.检查是否安装成功:

sudo netstat -tap | grep mysql

3.允许远程连接:

sudo vim /etc/mysql/my.cnf

把 bind-address这一行 注释掉,或者改为: bind-address = 0.0.0.0

4.重启 MySQL:

netstat -tap | grep mysql
tcp        0      0 localhost:mysql         *:*                     LISTEN      23381/mysqld    
root@jdu4e00u53f7:/# service mysql restart
mysql stop/waiting
mysql start/running, process 25300

5.授权用户能进行远程连接: 首先进入mysql命令行

mysql -u root -p
mysql> grant all privileges on *.* to root@"%" identified by "password" with grant option;
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Bye

输入root安装mysql时,password使用安装时候设置的root用户密码。 然后执行:

最后用SQLyog测试一下:

image.png

image.png

假如要授权某个用户访问,方法如下: 修改 Mysql-Server 用户配置 mysql> USE mysql; -- 切换到 mysql DB Database changed mysql> SELECT User, Password, Host FROM user; -- 查看现有用户,密码及允许连接的主机 +------+----------+-----------+ | User | Password | Host | +------+----------+-----------+ | root | | localhost | +------+----------+-----------+ 1 row in set (0.00 sec) mysql> -- 只有一个默认的 root 用户, 密码为空, 只允许 localhost 连接 mysql> -- 下面我们另外添加一个新的 root 用户, 密码为空, 只允许 192.168.1.100 连接 mysql> GRANT ALL PRIVILEGES ON . TO 'root'@'192.168.1.100' IDENTIFIED BY '' WITH GRANT OPTION; 或允许所有ip访问: mysql> GRANT ALL PRIVILEGES ON . TO root@"%" IDENTIFIED BY ''; mysql> -- 当然我们也可以直接用 UPDATE 更新 root 用户 Host, 但不推荐, SQL如下: mysql> -- UPDATE user SET Host='192.168.1.100' WHERE User='root' AND Host='localhost' LIMIT 1;

2017-9-19-Mysql group by报错

Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'information_schema.PROFILING.SEQ' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

解决办法,去掉ONLY_FULL_GROUP_BY,重新设置值。

select @@global.sql_mode
set @@global.sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

2017-09-16-微信公众号消息自动回复中文乱码问题

设置servlet请求和响应为utf-8,如下:

HttpServletRequest request = this.getRequest();
HttpServletResponse response = this.getResponse();
try {
	request.setCharacterEncoding("UTF-8");
	response.setCharacterEncoding("UTF-8");
} catch (UnsupportedEncodingException e1) {
	// TODO Auto-generated catch block
	e1.printStackTrace();
}

2017-09-16-小结:使用正则表达式提取时间中的数字

Quartz任务中对于时间的设定,有一定的规则,比如: "05 39 21 27 8 ? 2017" 从数据库取出来的时间格式不是这样的,是这样的: 2017-08-17 10:55:00 所以我们要提取其中的数字,代码如下:

// 分割符是 "-" 或 空格" " 或冒号 ":"
String time = "2017-08-17 10:55:00";
String[] times = time.split("[\\-:\\s]{1,}");

结果如下:

image.png

对了,还需要反转,才能对上:

List<String> timesList = Arrays.asList(times);
Collections.reverse(timesList);
times = (String[]) timesList.toArray();

如下:

image.png

什么?还缺一个问号? 由于Arrays.asList(times);返回的是一个固定长度的List,这次要折腾一下了:

String time = "2017-08-17 10:55:00";
// 分割符是 "-" 或 空格" " 或冒号 ":"
String[] times = time.split("[\\-:\\s]{1,}");
List<String> timesList = Arrays.asList(times);
List<String> flexibleTimesList = new ArrayList<String>();
flexibleTimesList.addAll(timesList);
flexibleTimesList.add(1,"?");
Collections.reverse(flexibleTimesList);
String[] resultTimes = new String[flexibleTimesList.size()];
for (String str : flexibleTimesList) {
	System.out.println(str);
}
resultTimes =  (String[]) flexibleTimesList.toArray();

打印都出来了,如下:

00
55
10
17
08
?
2017

但是走到最后一句,结果报错:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
	at com.test.hello.Main.main(Main.java:38)

为什么呢? 因为toArray()返回的是Object[] java.util.List.toArray(),强转String[]有问题。改用如下的办法:

flexibleTimesList.toArray(resultTimes);

OK了,看看结果:

image.png

最后,别忘了转换,如下:

StringBuffer sb = new StringBuffer();
for(String str : resultTimes) {
	sb.append(str + " ");
}
// 干掉最后一个空格
time = sb.toString().substring(0, sb.length() - 1);
System.out.println("{" + time + "}");

注:StringBuffer 比StringBuilder线程安全,比String +执行效率高,用这个连接字符串最合适。

打印结果如下,多余的空格也剔除了:

{00 55 10 17 08 ? 2017}

2017-09-16-定时获取微信的AccessToken

使用Quartz 2.2.3开启定时任务,每个整点获取一次,如下:

String jobName = "GetWeixinAccessToken";
String triggerName = jobName;
// 每个整点执行一次
quartzManager.addJob(jobName, triggerName, WeixinAccessTokenJob.class, "0 0 */1 * * ?", wxAccesstokenManager);

QuartzManager使用Spring注入:

import java.util.Date;
import java.util.List;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Service;

@Service
public class QuartzManager {
	public static SchedulerFactory schedulerFactory = new StdSchedulerFactory();  

	public void addJob(String jobName, String triggerName,
			Class jobClass, String cron, Object obj) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			// 任务名,任务组,任务执行类
			JobDetail jobDetail = JobBuilder.newJob(jobClass)
					.withIdentity(jobName).build();
			jobDetail.getJobDataMap().put("obj", obj);
			// 触发器
			TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder
					.newTrigger();
			// 触发器名
			triggerBuilder.withIdentity(triggerName);
			triggerBuilder.startNow();
			// 触发器时间设定
			triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
			// 创建Trigger对象
			CronTrigger trigger = (CronTrigger) triggerBuilder.build();

			// 调度容器设置JobDetail和Trigger
			sched.scheduleJob(jobDetail, trigger);

			// 启动
			if (!sched.isShutdown()) {
				sched.start();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	    /** 
	     * @Description: 添加一个定时任务 
	     *  
	     * @param jobName 任务名 
	     * @param jobGroupName  任务组名 
	     * @param triggerName 触发器名 
	     * @param triggerGroupName 触发器组名 
	     * @param jobClass  任务 
	     * @param cron   时间设置,参考quartz说明文档  
	     */  
	    @SuppressWarnings({ "unchecked", "rawtypes" })  
	    public void addJob(String jobName, String jobGroupName, 
	            String triggerName, String triggerGroupName, Class jobClass, String cron) {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  
	            // 任务名,任务组,任务执行类
	            JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();

	            // 触发器  
	            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
	            // 触发器名,触发器组  
	            triggerBuilder.withIdentity(triggerName, triggerGroupName);
	            triggerBuilder.startNow();
	            // 触发器时间设定  
	            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
	            // 创建Trigger对象
	            CronTrigger trigger = (CronTrigger) triggerBuilder.build();

	            // 调度容器设置JobDetail和Trigger
	            sched.scheduleJob(jobDetail, trigger);  

	            // 启动  
	            if (!sched.isShutdown()) {  
	                sched.start();  
	            }  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }  

	/**
	 * 修改任务的触发时间
	 * @param jobName
	 * @param triggerName
	 * @param cron
	 */
	public void modifyJobTime(String jobName, String triggerName,
			String cron) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);
			CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
			if (trigger == null) {
				return;
			}

			String oldTime = trigger.getCronExpression();
			if (!oldTime.equalsIgnoreCase(cron)) {
				/** 方式一 :调用 rescheduleJob 开始 */
				// 触发器
				TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder
						.newTrigger();
				// 触发器名,触发器组
				triggerBuilder.withIdentity(triggerName);
				triggerBuilder.startNow();
				// 触发器时间设定
				triggerBuilder.withSchedule(CronScheduleBuilder
						.cronSchedule(cron));
				// 创建Trigger对象
				trigger = (CronTrigger) triggerBuilder.build();
				// 方式一 :修改一个任务的触发时间
				sched.rescheduleJob(triggerKey, trigger);
				/** 方式一 :调用 rescheduleJob 结束 */

				/** 方式二:先删除,然后在创建一个新的Job */
				// JobDetail jobDetail =
				// sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
				// Class<? extends Job> jobClass = jobDetail.getJobClass();
				// removeJob(jobName, jobGroupName, triggerName,
				// triggerGroupName);
				// addJob(jobName, jobGroupName, triggerName, triggerGroupName,
				// jobClass, cron);
				/** 方式二 :先删除,然后在创建一个新的Job */
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	    /** 
	     * @Description: 修改一个任务的触发时间
	     *  
	     * @param jobName 
	     * @param jobGroupName
	     * @param triggerName 触发器名
	     * @param triggerGroupName 触发器组名 
	     * @param cron   时间设置,参考quartz说明文档   
	     */  
	    public void modifyJobTime(String jobName, 
	            String jobGroupName, String triggerName, String triggerGroupName, String cron) {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  
	            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
	            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);  
	            if (trigger == null) {  
	                return;  
	            }  

	            String oldTime = trigger.getCronExpression();  
	            if (!oldTime.equalsIgnoreCase(cron)) { 
	                /** 方式一 :调用 rescheduleJob 开始 */
	                // 触发器  
	                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
	                // 触发器名,触发器组  
	                triggerBuilder.withIdentity(triggerName, triggerGroupName);
	                triggerBuilder.startNow();
	                // 触发器时间设定  
	                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
	                // 创建Trigger对象
	                trigger = (CronTrigger) triggerBuilder.build();
	                // 方式一 :修改一个任务的触发时间
	                sched.rescheduleJob(triggerKey, trigger);
	                /** 方式一 :调用 rescheduleJob 结束 */

	                /** 方式二:先删除,然后在创建一个新的Job  */
	                //JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));  
	                //Class<? extends Job> jobClass = jobDetail.getJobClass();  
	                //removeJob(jobName, jobGroupName, triggerName, triggerGroupName);  
	                //addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron); 
	                /** 方式二 :先删除,然后在创建一个新的Job */
	            }  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }  

	/**
	 * @Description: 移除一个任务
	 * 
	 * @param jobName
	 * @param triggerName
	 */
	public void removeJob(String jobName, String triggerName) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName);
			sched.pauseTrigger(triggerKey);// 停止触发器
			sched.unscheduleJob(triggerKey);// 移除触发器
			sched.deleteJob(JobKey.jobKey(jobName));// 删除任务
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
 
	    /** 
	     * @Description: 移除一个任务 
	     *  
	     * @param jobName 
	     * @param jobGroupName 
	     * @param triggerName 
	     * @param triggerGroupName 
	     */  
	    public void removeJob(String jobName, String jobGroupName,  
	            String triggerName, String triggerGroupName) {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  

	            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

	            sched.pauseTrigger(triggerKey);// 停止触发器  
	            sched.unscheduleJob(triggerKey);// 移除触发器  
	            sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }  

	    /** 
	     * @Description:启动所有定时任务 
	     */  
	    public static void startJobs() {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  
	            sched.start();  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }  

	    /** 
	     * @Description:关闭所有定时任务 
	     */  
	    public static void shutdownJobs() {  
	        try {  
	            Scheduler sched = schedulerFactory.getScheduler();  
	            if (!sched.isShutdown()) {  
	                sched.shutdown();  
	            }  
	        } catch (Exception e) {  
	            throw new RuntimeException(e);  
	        }  
	    }
	    
	    /**
	     * 判断JobName是否在执行队列中
	     * @param jobName
	     * @return
	     */
	    public synchronized static boolean isJobExist(String jobName) throws SchedulerException {
	    	boolean isExistJob = false;
	    	Scheduler scheduler = schedulerFactory.getScheduler();
	    	for (String groupName : scheduler.getJobGroupNames()) {
	    		for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher
	    				.jobGroupEquals(groupName))) {
	    			String tmpJobName = jobKey.getName();
	    			String jobGroup = jobKey.getGroup();
	    			// get job's trigger
	    			@SuppressWarnings("unchecked")
	    			List<Trigger> triggers = (List<Trigger>) scheduler
	    			.getTriggersOfJob(jobKey);
	    			Date nextFireTime = triggers.get(0).getNextFireTime();
	    			System.out.println("[jobName] : " + tmpJobName
	    					+ " [groupName] : " + jobGroup + " - "
	    					+ nextFireTime);
	    			if (tmpJobName.equals(jobName)) {
	    				return true;
	    			}
	    		}
	    	}
			return isExistJob;
	    }
}

在Spring ApplicationContext注入后,才可获取bean,web.xml配置拦截如下:

<!--Spring ApplicationContext 载入 -->
<listener>
	<!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> -->
	<listener-class>com.test.hello.ContextLoaderListenerOverWrite</listener-class>
</listener>

拦截类是为了获取manager,然后存放AccessToken到数据库中。实现如下:

public class ContextLoaderListenerOverWrite extends ContextLoaderListener {

	@Override
	public void contextInitialized(ServletContextEvent event) {
		// TODO Auto-generated method stub
		super.contextInitialized(event);
		ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());  
      		startGetWeixinAccessTokenJobs(applicationContext);
	}
	/**
	 * 开启整点定时任务
	 */
	public void startGetWeixinAccessTokenJobs(ApplicationContext ctx) {
		WxBean currentBean = Utility.getAccessToken();
		WxAccesstoken currentToken = new WxAccesstoken();
		currentToken.setAccesstoken(currentBean.getAccess_token());
		currentToken.setExpiresIn(Integer.valueOf(currentBean.getExpires_in()));
		currentToken.setLastRequestTime(new Date());
		
		QuartzManager quartzManager = (QuartzManager)ctx.getBean("quartzManager");
		WxAccesstokenManager wxAccesstokenManager = (WxAccesstokenManager)ctx.getBean("wxAccesstokenManager");
		WxAccesstoken dbWxToken = wxAccesstokenManager.findFirst();
		if (dbWxToken == null) {	// 新增Token
			wxAccesstokenManager.save(currentToken);
			System.out.println("新增Token:" + currentToken);
		} else {	// 更新Token
			currentToken.setId(dbWxToken.getId());
			wxAccesstokenManager.update(currentToken);
			System.out.println("更新Token:" + currentToken);
		}
		String jobName = "GetWeixinAccessToken";
		String triggerName = jobName;
		// 每个整点执行一次
		quartzManager.addJob(jobName, triggerName, WeixinAccessTokenJob.class, "0 0 */1 * * ?", wxAccesstokenManager);
	}
}

获取微信AccessToken的办法如下:

/**
 * 获取微信的AccessToken
 * @return
 */
public static WxBean getAccessToken() {
	WxBean bean = null;
	Map<String, String> params = new HashMap<String, String>();
	params.put("grant_type", "client_credential");
	params.put("appid", Constants.WEIXIN_APPID);
	params.put("secret", Constants.WEIXIN_APPSECRET);
	try {
		String jstoken = HttpUtils.sendGet(
				"https://api.weixin.qq.com/cgi-bin/token", params);
		// String access_token = JSONObject.fromObject(jstoken).getString(
		// "access_token"); // 获取到token并赋值保存
		ObjectMapper objectMapper = JsonUtils.createObjectMapper();
		try {
			bean = objectMapper.readValue(jstoken, WxBean.class);
		} catch (JsonParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JsonMappingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	return bean;
}

对了,还有关键的部分,在这个Job里面每个整点更新AccessToken

public class WeixinAccessTokenJob implements Job{
	
	public WeixinAccessTokenJob() {
	}
	
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		//打印任务详情  
        System.out.println( "WeixinTokenJob:" + "-" +
                context.getJobDetail().getKey().getGroup() 
                +"——"+context.getJobDetail().getKey().getName()  
                +"——"+context.getTrigger().getKey().getName()  
                +"——"+context.getTrigger().getKey().getGroup() + new Date());
                JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
                WxAccesstokenManager wxAccesstokenManager = (WxAccesstokenManager)jobDataMap.get("obj");
		// Todo 使用wxAccesstokenManager来管理数据库存放的AccessToken
	}
}

2017-09-16-使用JFinal添加数据报id异常

使用Jfinal新增一条数据:

new CommentRecord().set("comment_time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).set("star_level", starLevel).set("comment", commentText).save();

结果报错如下:

com.jfinal.plugin.activerecord.ActiveRecordException: java.sql.SQLException: Field 'id' doesn't have a default value at com.jfinal.plugin.activerecord.Model.save(Model.java:424)...Caused by: java.sql.SQLException: Field 'id' doesn't have a default valueat com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)...

原因是数据库对应的Table表的主键id不是自增的,修改即可:

2017-09-16-使用jstl优化评论星标html代码

评论需要加5颗星的功能,之前代码是这么写的:

<c:if
	test="${star_level == 1}">
	<i class="ys"></i>
	<i></i>
	<i></i>
	<i></i>
	<i></i>
</c:if> <c:if
	test="${star_level == 2}">
	<i class="ys"></i>
	<i class="ys"></i>
	<i></i>
	<i></i>
	<i></i>
</c:if> <c:if
	test="${star_level == 3}">
	<i class="ys"></i>
	<i class="ys"></i>
	<i class="ys"></i>
	<i></i>
	<i></i>
</c:if> <c:if
	test="${star_level == 4}">
	<i class="ys"></i>
	<i class="ys"></i>
	<i class="ys"></i>
	<i class="ys"></i>
	<i></i>
</c:if> <c:if
	test="${star_level == 5}">
	<i class="ys"></i>
	<i class="ys"></i>
	<i class="ys"></i>
	<i class="ys"></i>
	<i class="ys"></i>
</c:if>
<c:if test="${curentCommentRecord == null || star_level == 0}">
	<i></i>
	<i></i>
	<i></i>
	<i></i>
	<i></i>
</c:if>

是不是看着很冗余?如果是10颗星呢?那代码就更长了,也不好维护,看着不舒服,那咋优化呢? 如下:

<c:forEach begin='1' end="5" var='item'>
	<c:choose>
		<c:when test="${item <= star_level }">
		 	<i class="ys"></i>
		</c:when>
		<c:otherwise>
			<i></i>
		</c:otherwise>
	</c:choose>
</c:forEach>

效果出来了,棒棒哒。

image.png

2017-09-16-关于Tomcat自动加载更新class的小技巧

在Tomcat的server.xml或者Tomcat.xxx\conf\Catalina\localhost\project.xml文件中里Context标签内:

第二步:debug方式启动Tomcat。如果你用的是eclipse Tomcat插件的话, 将Don't run tomcat debug mode取消勾选,就是将会是debug方式启动Tomcat了: window=>preferences=>Tomcat=>JVM Settings

如果是MyEclipse:

2017-09-16-内网穿透

使用frp进行内网穿透,可以很方便地进行调试,比如微信公众号。穿透前,需要有一台能连接公网的机器,京东云最近做活动,可以免费半年。我在这上面进行了实战。

原来用的是花生壳,但是有很多限制,还是自己弄了域名比较方便。

frp是什么,就不多说了,有兴趣的童鞋看这个:https://github.com/fatedier/frp

工具在上面的github地址上可以下载到,我提供一个X86 CPU版本的windows和linux版本的地址。 链接:http://pan.baidu.com/s/1kV7R39t 密码:md3a

在公网IP服务器配置frps.ini,如下:

[common]
bind_port = 7000
vhost_http_port = 80

本地局域网配置frpc.ini

[common]
server_addr = 111.61.131.13
server_port = 7000

[ssh]
type = tcp
local_ip = 192.168.3.133
local_port = 22
remote_port = 6000

[web]
type = http
local_port = 8080
custom_domains = test.bianxh.top

公网使用的是Linux,运行命令如下:

root@***:~/frp_0.13.0_linux_386# ./frps -c ./frps.ini
2017/09/12 12:37:50 [I] [service.go:83] frps tcp listen on 0.0.0.0:7000
2017/09/12 12:37:50 [I] [service.go:108] http service listen on 0.0.0.0:80
2017/09/12 12:37:50 [I] [main.go:112] Start frps success
2017/09/12 12:37:50 [I] [main.go:114] PrivilegeMode is enabled, you should pay more attention to security issues

本地是Windows,运行命令如下:

D:\GreenSoft\frp_0.13.0_windows_amd64>frpc.exe -c frpc.ini
2017/09/12 12:35:00 [I] [control.go:276] [ded5c9fb0d273509] login to server success, get run id [ded5c9fb0d273509]
2017/09/12 12:35:01 [I] [control.go:411] [ded5c9fb0d273509] [ssh] start proxy success
2017/09/12 12:35:01 [I] [control.go:411] [ded5c9fb0d273509] [web] start proxy success

下来去服务商管理后台,配置下域名解析:

记录类型 主机记录 记录值
A test 公网IP,比如:111.61.131.13

可以访问到本地了: http://test.bianxh.top/yiyixiaozhi/webSocketTest.jsp 和本地访问一样,如下: image.png

刚刷新两次,就提示无法访问了,没有备案的域名果然不好使啊: http://illegalitydomain.jcloud.com/

换个地址,使用端口访问了一下,是通的。

image.png

下来还是要乖乖备案去。 image.png

⚠️ **GitHub.com Fallback** ⚠️