Solo  当前访客:4 登录 注册

喧哗博客-http://blog.xuahua.com

繁华过后的沉寂--技术经验分享
浏览次数: 94,390    文章总数: 91    评论总数: 3

httpclient4.x 模拟get请求

private static void postRequestconfig(HttpPost httppost){
		 //配置请求的超时设置
		RequestConfig requestConfig = RequestConfig.custom()
				.setConnectionRequestTimeout(Timeout)
				.setConnectTimeout(Timeout)  
				.setSocketTimeout(Timeout).build();
        httppost.setConfig(requestConfig);
	}
public static String getRequest(String url) { StringBuilder sb = new StringBuilder(); CloseableHttpClient httpclient = HttpClientBuilder.create().build(); HttpGet httpget = new HttpGet(url); getRequestconfig(httpget); try{ CloseableHttpResponse response = httpclient.execute(httpget); int statusOk = response.getStatusLine().getStatusCode(); if(logger.isInfoEnabled()){ logger.info(url+"result-statusCode=>>"+statusOk); } if(statusOk == HttpStatus.SC_OK){ HttpEntity entity = response.getEntity(); BufferedInputStream instream = new BufferedInputStream(entity.getContent()); byte[] chars = new byte[2048]; int len=0; while((len=instream.read(chars))!=-1){ sb.append(new String(chars,0,len)); } }else{ logger.error(url+"result->网络异常.."+statusOk); } if(logger.isInfoEnabled()){ logger.info(url+"result->"+sb.toString()); } }catch(Exception e){ e.printStackTrace(); }finally { httpget.releaseConnection(); try { httpclient.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return sb.toString(); }

Got an error reading communication packets 有更新!

 

具体表现

2016-08-11T17:34:01.264286Z 36668 [Note] Aborted connection 36668 to db: 'game' user: 'game28' host: 'localhost' (Got an error reading communication packets)
2016-08-11T17:34:01.264335Z 36672 [Note] Aborted connection 36672 to db: 'game' user: 'game28' host: 'localhost' (Got an error reading communication packets)
2016-08-11T17:34:01.264337Z 36671 [Note] Aborted connection 36671 to db: 'game' user: 'game28' host: 'localhost' (Got an error reading communication packets)
2016-08-11T17:35:01.424325Z 36678 [Note] Aborted connection 36678 to db: 'xx' user: 'xx' host: 'localhost' (Got an error reading communication packets)
2016-08-11T17:35:01.424335Z 36679 [Note] Aborted connection 36679 to db: 'xx' user: 'xx' host: 'localhost' (Got an error reading communication packets)
2016-08-11T17:35:01.424372Z 36685 [Note] Aborted connection 36685 to db: 'x' user: 'xx' host: 'localhost' (Got an error reading communication packets)
2016-08-11T17:35:01.424343Z 36680 [Note] Aborted connection 36680 to db: 'xx' user: 'xx' host: 'localhost' (Got an error reading communication packets 

解决方法

在my.cnf 文件中,增加 max_allowed_packet =256M

 原因 

http://dev.mysql.com/doc/refman/5.7/en/communication-errors.html

The max_allowed_packet variable value is too small or queries require more memory than you have allocated for mysqld

翻译出来就是,服务器端设定max_allowed_packet的值太小或者查询要求的缓冲内存区比mysqld设定的要大。

 

 

 

nginx+tomcat负载均衡配置

1,前提nginx安装完成;如果不知道,可以请见http://blog.xuahua.com/articles/2016/08/24/1472024453381.html

示例Nginx安装目录为 /usr/local/nginx

2,jdk,tomcat安装完成。

下面要讲的是配置nginx 与tomcat的负载配置;本次示例使用的域名为 blog.xuahua.com

nginx的配置

/usr/local/nginx/conf/nginx.conf

user          root;
worker_processes  10;

#error_log  /var/log/nginx/error.log;
#error_log  /var/log/nginx/error.log  notice;
#error_log  /var/log/nginx/error.log  info;
error_log /data/logs/nginx/error.log error;

pid        /var/run/nginx.pid;


events {
    use epoll;
    worker_connections  65535;
}


http {
    include      mime.types;
    default_type  application/octet-stream;
        server_names_hash_bucket_size 128;
        #client_header_buffer_size 32k;
        #large_client_header_buffers 4 32k;
        #client_max_body_size 64m;
        #client_body_buffer_size 256k;
        sendfile on;
        tcp_nopush     on;
        keepalive_timeout 60;
        tcp_nodelay on;
        client_header_timeout   3m;
        client_body_timeout     3m;
        send_timeout    3m;

#FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
#
##gzip模块设置
gzip on; #开启gzip压缩输出
gzip_min_length 1k; #最小压缩文件大小
gzip_buffers 4 16k; #压缩缓冲区
gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_comp_level 2; #压缩等级
gzip_types text/plain application/x-javascript text/css application/xml;
##压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
gzip_vary on;
##limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用
##跨域访问
# add_header Access-Control-Allow-Origin *;
# add_header Access-Control-Allow-Headers X-Requested-With;
# add_header Access-Control-Allow-Methods GET,POST,OPTIONS;

             proxy_redirect off ;
             proxy_set_header Host $host;
             proxy_set_header X-Real-IP $remote_addr;
             proxy_set_header REMOTE-HOST $remote_addr;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             client_max_body_size 50m;
             client_body_buffer_size 256k;
             proxy_connect_timeout 30;
             proxy_send_timeout 30;
             proxy_read_timeout 60;
             proxy_buffer_size 256k;
             proxy_buffers 4 256k;
             proxy_busy_buffers_size 256k;
             proxy_temp_file_write_size 256k;
 proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
             proxy_max_temp_file_size 128m;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

   # access_log  /var/log/nginx/access.log  main;

    access_log  /data/logs/nginx/access.log  main;

 upstream blog.xuahua.com{
        server 10.116.21.192:9090;
        server 10.116.21.192:9090;
}

 

重点 upstream的server配置

server 10.116.21.192:9090 指向 tomcat的9090端口

server 10.116.21.193:9090 指向内网193 tomcat的9090端口。

 

而且针对server 的配置还有更多的参数,可根据实际情况增加。

 

nginx的https配置可见  http://blog.xuahua.com/articles/2016/03/01/1456812606792.html

liunx下的Nginx安装

1,nginx 下载
 
wget  http://nginx.org/download/nginx-1.9.9.tar.gz
先 安装pcre,libevent, OpenSSL
>yum install pcre*
>yum install libevent*
>yum install openssl*
 
解压nginx,进入目录。
>./configure   --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module   --with-pcre=pcre源目录
pcre 指向源文件目录,而不是编译后的目录

                        # --with-http_stub_status_module:这个模块用于获取nginx自上次启动以来的工作状态,非核心模块

                       # --with-http_ssl_module     :HTTPS 使用

                       # 上文中的--with-cc-opt='-O2' --with-cpu-opt=opteron 这是编译器优化,目前最常用的是-02 而不是3.后面对应CPU的型号,可参照:http://wiki.gentoo.tw/index.php/HOWTO_CFLAG

 

> make && make install

pcre-7.8-7.el6.x86_64
pcre-devel-7.8-7.el6.x86_64
pcre-static-7.8-7.el6.x86_64

代理配置

  proxy_redirect off ;
             proxy_set_header Host $host;
             proxy_set_header X-Real-IP $remote_addr;
             proxy_set_header REMOTE-HOST $remote_addr;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             client_max_body_size 50m;
             client_body_buffer_size 256k;
             proxy_connect_timeout 30;
             proxy_send_timeout 30;
             proxy_read_timeout 60;
             proxy_buffer_size 256k;
             proxy_buffers 4 256k;
             proxy_busy_buffers_size 256k;
             proxy_temp_file_write_size 256k;
             proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
             proxy_max_temp_file_size 128m;

 

        2.1 pcre 编译安装  安装pcre 让nginx支持rewrite 方便以后所需

 

        wget ftp://ftp.csx.cam.ac.uk//pub/software/programming/pcre/pcre-8.37.tar.gz
        tar zxvf pcre-8.37.tar.gz
        cd pcre-8.37/
       ./configure --prefix=/usr/local/pcre
编译完后可以执行make check进行测试(这一步非必须)
        make
  1. Skipping pcregrep UTF-8 tests: no UTF-8 support in PCRE library  
  2. Testing pcregrep newline settings  
  3. PASS: RunGrepTest  
  4. ==================  
  5. All 5 tests passed  
  6. ==================  
  7. make[2]: Leaving directory `/usr/local/pcre-8.32'  
  8. make[1]: Leaving directory `/usr/local/pcre
    加上对utf-8的支持可以在./configuration时加上参数: ./configure --enable-utf8  
make install
 
nginx -t -c /usr/local/nginx/conf/nginx.conf
    2.2 libevent 编译安装

        # wget http://www.monkey.org/~provos/libevent-2.0.12-stable.tar.gz
        # tar zxf libevent-2.0.12-stable.tar.gz 
        # cd libevent-2.0.12-stable
        #./configure  --prefix=/usr/local/lib
        # make && make install
     

githup-使用手记

经常使用SVN,身边也经常听人说githup如何高大上,今天有时间上来也折腾一下。。

1,首先注册 https://github.com

2,创建 repository 这个好像免费只能是public的。。不管他,先创建一个 xuahuaBlog

3,配置member ,这里好像需要邮箱认证通过才可以。我使用的是 service@xuahua.com

4,在客户端 liunx 上面默认安装了git..如果没有安装的请先安装。

root> mkdir xuahua //新建一个本地目录,准备当做本地仓库

root> git clone https://github.com/xuahuaBlog/home.git  //检出githup上面的仓库

root> git checkout https://github.com/xuahuaBlog/home.git home //切换仓库

root>git  config --global user.name xxx //githup账号

root>git config --global user.email xxx@xxx.com //邮箱账号

root >  git remote set-url origin https://xxx@github.com/xuahuaBlog/project.git

root>git push //默认是 origion/master

password> //会弹出来提示你输入密码

输入密码,提交,即可在githup上面看到本地仓库新增加的文件了。。

整个流程比较简单,但是已经通过了。

hh

hibnerate-createSQLQuery返回自定义对象 有更新!

SQLQuery query = createSQLQuery(sql, values).addEntity(XXX.class);
query.list();

或者

SQLQuery query = createSQLQuery(sql, values);
		
		List<Map<String,Object>> list = query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).setFirstResult(startIndex).setMaxResults(pageSize).list();
		List rlist =  new ArrayList();
		if(list!=null && !list.isEmpty()){
			for(Map<String,Object> m : list){
				try {
					Object obj = MapBeanUtils.toObject(clazz, m);
					rlist.add(obj);
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

nginx-最容易忽略的错误

场景:

当我访问子域名a.xxx 时,url 会自动跳转其他的子域名如admin.xxx ..

排查:

1,我怀疑工程代码里面做了跳转,检查所有代码发现并无此问题。(排除)

2,工程没有,那就是Nginx转发的问题。于是检查配置,

发现在nginx.conf 文件中,引入子域名的配置时,指定 include vhosts/sites_*.conf; 

但是在vhosts目录,访问的子域名 a.xxx 配置文件 为 sites_a.xx 

并不是指定的sites_*.conf 格式,导致Nginx并未生效此子域名配置。

才会导致访问子域名 a.xxx时,会跳转到一个其他的子域名。

原因:

nginx 引入子域名并未导入,只是在nginx.conf 中配置了upstream 才会导致可以访问,但是跳转又不正常。

 

以此为记!

java并发编程之栅栏(CyclicBarrier)与闭锁(Latch) 有更新!

如果想实现所有的线程一起等待某个事件的发生,当某个事件发生时,所有线程一起开始往下执行的话,有什么好的办法吗?

方法1,栅栏CyclicBarrier

方法2 ,闭锁 Latch


栅栏与闭锁(Latch)的差异在于:


    闭锁   Latch 


一种同步方法,可以延迟线程的进度直到线程到达某个终点状态。通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过,

但是一旦大门打开,所有线程都通过了,那么这个闭锁的状态就失效了,门的状态也就不能变了,只能是打开状态。

也就是说闭锁的状态是一次性的,它确保在闭锁打开之前所有特定的活动都需要在闭锁打开之后才能完成。


   应用场景:


  • 确保某个计算在其需要的所有资源都被初始化之后才继续执行。二元闭锁(包括两个状态)可以用来表示“资源R已经被初始化”,而所有需要R的操作都必须先在这个闭锁上等待。
  • 确保某个服务在其依赖的所有其他服务都已经启动之后才启动。
  • 等待直到某个操作的所有参与者都就绪在继续执行。(例如:多人游戏中需要所有玩家准备才能开始)


            CountDownLatch是JDK 5+里面闭锁的一个实现,允许一个或者多个线程等待某个事件的发生。CountDownLatch有一个正数计数器,countDown方法对计数器做减操作,await方法等待计数器达到0。

         所有await的线程都会阻塞直到计数器为0或者等待线程中断或者超时。


         代码例子: 

                   

    栅栏  CyclicBarrier


 栅栏类似于闭锁,它能阻塞一组线程直到某个事件发生。栅栏与闭锁的关键区别在于,所有的线程必须同时到达栅栏位置,才能继续执行。闭锁用于等待事件,而栅栏用于等待其他线程。


     场景:

 应用一些协议,比如几个家庭成员决定在某个地方集合,所有人在6:00在某地集合,到了以后要等待其他人,之后才能讨论去哪里吃饭。

 并行迭代,将一个问题分成很多子问题,当一系列的子问题都解决之后(所有子问题线程都已经await()),此时将栅栏打开,所有子问题线程被释放,而栅栏位置可以留着下次使用。



  例子:两个分别关于CountDownlatch和CyclicBarrier的例子

1、CountDownLatch


    有三个工人在为老板干活,这个老板有一个习惯,就是当三个工人把一天的活都干完了的时候,他就来检查所有工人所干的活。记住这个条件:三个工人先全部干完活,老板才检查。所以在这里用Java代码设计两个类,Worker代表工人,Boss代表老板,具体的代码实现如下:


    工人:


              

package LatchAndCyclicBarrier;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class Work implements Runnable{


        private CountDownLatch downLatch;
        private String name;

        public Work(CountDownLatch downLatch, String name){
            this.downLatch = downLatch;
            this.name = name;
        }

        public void run() {
            this.doWork();
            try{
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
            }catch(InterruptedException ie){
            }
            System.out.println(this.name + "活干完了!");
            this.downLatch.countDown();

        }

        private void doWork(){
            System.out.println(this.name + "正在干活!");
        }

    }


老板:

 

package LatchAndCyclicBarrier;

import java.util.concurrent.CountDownLatch;

public class Boss implements Runnable{

        private CountDownLatch downLatch;

        public Boss(CountDownLatch downLatch){
            this.downLatch = downLatch;
        }

        public void run() {
            System.out.println("老板正在等所有的工人干完活......");
            try {
                this.downLatch.await();
            } catch (InterruptedException e) {
            }
            System.out.println("工人活都干完了,老板开始检查了!");
        }

    }

测试代码: 




package LatchAndCyclicBarrier;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestLatch {

    public static void main(String[] args) {
            ExecutorService executor = Executors.newCachedThreadPool();

            CountDownLatch latch = new CountDownLatch(3);

            Work w1 = new Work(latch,"张三");
            Work w2 = new Work(latch,"李四");
            Work w3 = new Work(latch,"王二");

            Boss boss = new Boss(latch);

            executor.execute(w3);
            executor.execute(w2);
            executor.execute(w1);
            executor.execute(boss);

            executor.shutdown();
        }

    }
执行结果:
李四正在干活!
老板正在等所有的工人干完活......
王二正在干活!
张三正在干活!
李四活干完了!
王二活干完了!
张三活干完了!
工人活都干完了,老板开始检查了!

2、CyclicBarrier


接着上面的例子,还是这三个工人,不过这一次,这三个工人自由了,老板不用检查他们任务了,他们三个合作建桥,有三个桩,每人打一个,同时打完之后才能一起搭桥(搭桥需要三人一起合作)。也就是说三个人都打完桩之后才能继续工作。

   








package LatchAndCyclicBarrier;

import java.util.concurrent.CyclicBarrier;

public class CycWork implements Runnable {


        private CyclicBarrier cyclicBarrier ;
        private String name ;

        public CycWork(CyclicBarrier cyclicBarrier,String name)
       {
               this .name =name;
               this .cyclicBarrier =cyclicBarrier;
       }

        @Override
        public void run() {
               // TODO Auto-generated method stub

              System. out .println(name +"正在打桩,毕竟不轻松。。。。。" );

               try {
                     Thread. sleep(5000);
                     System. out .println(name +"不容易,终于把桩打完了。。。。" );
                      cyclicBarrier .await();

              } catch (Exception e) {
                      // TODO: handle exception
                     e.printStackTrace();
              }

              System. out .println(name +":其他逗b把桩都打完了,又得忙活了。。。" );


       }

}
测试程序:
 
package LatchAndCyclicBarrier;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CycTest {

        public static void main(String[] args)
       {
              ExecutorService executorpool=Executors. newFixedThreadPool(3);
              CyclicBarrier cyclicBarrier= new CyclicBarrier(3);

              CycWork work1= new CycWork(cyclicBarrier, "张三" );
              CycWork work2= new CycWork(cyclicBarrier, "李四" );
              CycWork work3= new CycWork(cyclicBarrier, "王五" );

              executorpool.execute(work1);
              executorpool.execute(work2);
              executorpool.execute(work3);

              executorpool.shutdown();

       }

}
运行结果:
 
李四正在打桩,毕竟不轻松。。。。。
张三正在打桩,毕竟不轻松。。。。。
王五正在打桩,毕竟不轻松。。。。。
李四不容易,终于把桩打完了。。。。
张三不容易,终于把桩打完了。。。。
王五不容易,终于把桩打完了。。。。
王五:其他逗b把桩都打完了,又得忙活了。。。
李四:其他逗b把桩都打完了,又得忙活了。。。
张三:其他逗b把桩都打完了,又得忙活了。。。 
 

CountDownlatch和CyclicBarrierde 源码部分

1、CountDownLatch中的两个关键方法

 public void countDown() {    //对计数器减一 表示有一个事件已经发生了
        sync.releaseShared(1); 
    }
public void await() throws InterruptedException { //等到计数器为0
        sync.acquireSharedInterruptibly(1);
    }
await方法调用了AbstractQueuedSynchronizer中的acquireSharedInterruptibly
 
public final void acquireSharedInterruptibly (int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }
public final boolean releaseShared (int arg) {
        if (tryReleaseShared(arg)) {   
            doReleaseShared();
            return true ;
        }
        return false ;
    }
protected boolean tryReleaseShared (int arg) {
        throw new UnsupportedOperationException();
    }
2、CyclicBarrier中的await()方法
 
public int await() throws InterruptedException, BrokenBarrierException {
        try {
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // cannot happen;
        }
    }
 private int dowait(boolean timed, long nanos)
        throws InterruptedException, BrokenBarrierException,
               TimeoutException {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            final Generation g = generation;

            if (g.broken)
                throw new BrokenBarrierException();

            if (Thread.interrupted()) {
                breakBarrier();
                throw new InterruptedException();
            }

           int index = --count;
           if (index == 0) {  // tripped
               boolean ranAction = false;
               try {
                   final Runnable command = barrierCommand;
                   if (command != null)
                       command.run();
                   ranAction = true;
                   nextGeneration();
                   return 0;
               } finally {
                   if (!ranAction)
                       breakBarrier();
               }
           }

            // loop until tripped, broken, interrupted, or timed out
            for (;;) {
                try {
                    if (!timed)
                        trip.await();
                    else if (nanos > 0L)
                        nanos = trip.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                    if (g == generation && ! g.broken) {
                        breakBarrier();
                        throw ie;
                    } else {
                        // We‘re about to finish waiting even if we had not
                        // been interrupted, so this interrupt is deemed to
                        // "belong" to subsequent execution.
                        Thread.currentThread().interrupt();
                    }
                }

                if (g.broken)
                    throw new BrokenBarrierException();

                if (g != generation)
                    return index;

                if (timed && nanos <= 0L) {
                    breakBarrier();
                    throw new TimeoutException();
                }
            }
        } finally {
            lock.unlock();
        }
    }
上面dowait方法中有一个index,index=--count而count的值在源码中来自

count = parties;
提到 parties就不得不看看构造函数了 

public CyclicBarrier(int parties) {
        this(parties, null);
    }
如上例子,我们构造了CyclicBarrier(3)那么此时的 count值为3,接着dowait源码,当index==0时,后面执行的

final Runnable command = barrierCommand;
其实是可以设置的,这个Runnable可以传进来,当我们希望所有线程都达到某一时刻之后,用什么线程执行接下来的工作,
当没有传Runnable进来时,就继续执行(唤醒其他线程),否则就runnable.run()(唤醒其他线程之前执行) 
原文:http://blog.csdn.net/yujin753/article/details/46125283


java进阶之一生成二维码

生成二维码图片,指定内容,生成图片提供下载。


/**
	 * 生成二维码并返回图片路径
	 * @param domain
	 * @param SERVER_PATH
	 * @param filepath
	 * @param content
	 * @param imgPath
	 * @param filename
	 * @param needCompress
	 * @return
	 * @throws Exception
	 * 
	 * String path_ = QRCodeUtil.buildcodeurl(Constants.getConfigkey("upload.image.base64.domain"),
					Constants.getConfigkey("common.file.path"),"/qrcode/user/",
					Constants.getConfigkey("h5.cus.url")+"/reg?cid="+o.getId()
					, null,o.getId()+".jpg");
	 */
	public static String buildcodeurl(String domain,String SERVER_PATH,String filepath,String content, String imgPath,String filename) throws Exception{
		String path = SERVER_PATH+filepath;
		QRCodeUtil.encode(content, imgPath, path,filename, true);
		String path_ = domain+filepath+filename;
		return path_;
		
	}

/**
	 * 生成二维码(内嵌LOGO)
	 * 
	 * @param content
	 *            内容
	 * @param imgPath
	 *            LOGO地址
	 * @param destPath
	 *            存放目录
	 * @param needCompress
	 *            是否压缩LOGO
	 * @throws Exception
	 */
	public static void encode(String content, String imgPath, String destPath,String filename,
			boolean needCompress) throws Exception {
		BufferedImage image = QRCodeUtil.createImage(content, imgPath,
				needCompress);
		mkdirs(destPath);
		String file = filename;
		File f = new File(destPath+"/"+file);
		if(!f.getParentFile().exists()){
			f.getParentFile().mkdirs();
		}
		ImageIO.write(image, FORMAT_NAME,f);
	}

整个源文件下载  http://file.xuahua.com/blog/2016/0806/QRCodeUtil.java


微信接口开发系列之八批量获取用户信息 有更新!

1,微信提供了批量获取用户信息以及union_id;

文档请见 https://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html 



批量获取用户基本信息

开发者可通过该接口来批量获取用户基本信息。最多支持一次拉取100条。

接口调用请求说明

http请求方式: POST
https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=ACCESS_TOKEN
POST数据示例

{
    "user_list": [
        {
            "openid": "otvxTs4dckWG7imySrJd6jSi0CWE", 
            "lang": "zh-CN"
        }, 
        {
            "openid": "otvxTs_JZ6SEiP0imdhpi50fuSZg", 
            "lang": "zh-CN"
        }
    ]
}
参数说明

参数	是否必须	说明
openid	是	用户的标识,对当前公众号唯一
lang	否	国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语,默认为zh-CN
返回说明

正常情况下,微信会返回下述JSON数据包给公众号(示例中为一次性拉取了2个openid的用户基本信息,第一个是已关注的,第二个是未关注的):

{
   "user_info_list": [
       {
           "subscribe": 1, 
           "openid": "otvxTs4dckWG7imySrJd6jSi0CWE", 
           "nickname": "iWithery", 
           "sex": 1, 
           "language": "zh_CN", 
           "city": "Jieyang", 
           "province": "Guangdong", 
           "country": "China", 
           "headimgurl": "http://wx.qlogo.cn/mmopen/xbIQx1GRqdvyqkMMhEaGOX802l1CyqMJNgUzKP8MeAeHFicRDSnZH7FY4XB7p8XHXIf6uJA2SCunTPicGKezDC4saKISzRj3nz/0", 
           "subscribe_time": 1434093047, 
           "unionid": "oR5GjjgEhCMJFyzaVZdrxZ2zRRF4", 
           "remark": "", 
           "groupid": 0
       }, 
       {
           "subscribe": 0, 
           "openid": "otvxTs_JZ6SEiP0imdhpi50fuSZg", 
           "unionid": "oR5GjjjrbqBZbrnPwwmSxFukE41U", 
       }
   ]
}
参数说明

参数	说明
subscribe	用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息,只有openid和UnionID(在该公众号绑定到了微信开放平台账号时才有)。
openid	用户的标识,对当前公众号唯一
nickname	用户的昵称
sex	用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
city	用户所在城市
country	用户所在国家
province	用户所在省份
language	用户的语言,简体中文为zh_CN
headimgurl	用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
subscribe_time	用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
unionid	只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。详见:获取用户个人信息(UnionID机制)
remark	公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注
groupid	用户所在的分组ID
错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):

{"errcode":40013,"errmsg":"invalid appid"}

实现代码要点:


//微信批量定义每次最多100条记录,做循环获取。
		    Page page = userService.findAllTMemBind(1, i, 100);
		    while(page!=null && page.getResult()!=null && !page.getResult().isEmpty()){
		    	count = count + page.getResult().size();
		    	
		    	//调用本地的方法,获取之前保存的access_token 此token也称为全局acess_token;区别于网页用户显示授权acess_token
		    	String access_token = loadGZWXtoken();
		    	
		    	//具体拼接方法,并请求微信服务器,返回数据
		    	batchupdate(page.getResult(),access_token);
		    	
		    	//处理完成以后,再次拉取。重复循环
		    	page = userService.findAllTMemBind(1, i++, 100);
		    }
batchupdate 方法实现



private void batchupdate(List<TMemBinduser> userlist,String access_token){
		if(userlist ==null || userlist.isEmpty()) return ;
		
		JSONArray ary  =new JSONArray();
		for(TMemBinduser user:userlist){
			Map<String,String> openids = new HashMap<String,String>();
			openids.put("openid",user.getBindid());
			openids.put("lang","zh-CN");
			ary.add(JSON.toJSON(openids));
		}
		Map<String,Object> ulist = new HashMap<String,Object>();
		ulist.put("user_list",ary);
		String url = PropertiesUtil.getValue("wx.gz.batchget");
		url = url.replaceFirst("ACCESS_TOKEN", access_token);
		String result = Posturl.postRequestJson(url, ulist, "", "");
		//正确返回的
		//{"user_info_list":[{"subscribe":1,"openid":"oPMQVwqVrRlrr6Pdmgxr-P3Zh6aI","nickname":"kingman","sex":1,"language":"zh_CN","city":"Shenzhen","province":"Guangdong","country":"China","headimgurl":"http:\/\/wx.qlogo.cn\/mmopen\/6gxkh8CsLWewtkLGib6vxW6NrkJMgChp8ibAIH8SEBEKHYeADeibuDAAv8G5EibjvXAYbjQBwedoJD5lrVKSsic25Qx4smSxRQSqib\/0","subscribe_time":1458718222,"unionid":"oIzlcwLjHriVyXG9KsqJ6i7ggbjg","remark":"","groupid":0,"tagid_list":[]},{"subscribe":1,"openid":"oPMQVwlPuNN0Dztus7oGi2UeFv14","nickname":"Bdb","sex":0,"language":"zh_CN","city":"","province":"","country":"","headimgurl":"http:\/\/wx.qlogo.cn\/mmopen\/Q3auHgzwzM7VtmYVicjQhxcLJGkefRWz6HJN4PNmYibyKicB231FgOwj8dlxQTcDXAbIGN2a1SOgDy4ROJwaHXOzQ\/0","subscribe_time":1459932319,"unionid":"oIzlcwGRoh8JDn8rP3AXvSjSGOy4","remark":"","groupid":0,"tagid_list":[]}]}
		if(log.isInfoEnabled()){
			log.debug("==微信通知-批量拉取用户id==="+result);
		}
	}



微信开发系列 有更新!

1,配置 

               http://blog.xuahua.com/articles/2016/06/30/1467251027592.html

2,授权 

        http://blog.xuahua.com/articles/2016/06/30/1467254772371.html

3,获取用户信息 

        http://blog.xuahua.com/articles/2016/06/30/1467255584587.html

4,模版消息 

         http://blog.xuahua.com/articles/2016/06/30/1467256108292.html

5,微信支付服务器接收通知 

        http://blog.xuahua.com/articles/2016/06/30/1467256973822.html

6,移动应用获取微信用户信息 

        http://blog.xuahua.com/articles/2016/07/13/1468397068875.html

7,微信开放平台支付加密java类 

        http://blog.xuahua.com/articles/2016/07/13/1468399623674.html

8, 微信批量获取用户信息 

    http://blog.xuahua.com/articles/2016/07/30/1469860455915.html

spring实战汇总

1,
    spring实战系列一MAVEN工程建立
2,
    spring实战之二maven文件配置


3,

    spring实战之三web配置

4,



    spring实战之四run



完整工程源码下载

如果你也需要jar包,此处也有lib打包下载



spring实战之四run 有更新!

前面讲了这么多,到了最关键的时候了,让他跑起来吧。

1,生成文件路径,java ,source,webapp各目录下的文件。




文件目录路径必须与applicationContext.xml ,spring-webmvc.xml中配置的一致。



至此,已经编译成功。可以在工程target目录下的 把war复制到运行容器中即可运行。

效果图如下

spring实战之三web配置 有更新!

1,除了需要配置pom.xml需要引用的jar包以外,还需要配置其他的配置文件;如web.xml,spring-mvc.xml,applicationContext.xml等。

现在一一详细解说

web.xml



<!-- spring初始化时,容器调用监听 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
 <!--  spring初始化时,引用文件工程目录下所有以applicationContext_开头的.xml,包括jar包中也会搜索进来。
    	classpath:applicationContext.xml 仅指工程classes目录下的applicationContext.xml;
    	classpath:applicationContext_*.xml 仅指工程classes目录下的applicationContext_开头的.xml文件;
    	classpath*:applicationContext_.xml 指工程classes目录下包括lib包中,包含有application_开头的.xml文件。	
    	 文件以及全局参数,此处默认了一个参数product来控制是否使用生产联接串或开发联接串-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:applicationContext.xml
        </param-value>
    </context-param>
    <context-param>
        <param-name>spring.profiles.default</param-name>
        <param-value>product</param-value>
    </context-param>
  <!-- 不多说了,编码过滤器 -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter </filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 <!-- spring mvc的初始化,文件为classes目录下的 spring-webmvc.xml web请求处理参数,以及 -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-webmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
  <!--MySQL数据库JNDI数据  可在程序手动lookup 到数据源-->
    <resource-ref>
       <description>xuahua</description>
       <res-ref-name>jdbc/xuahua</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
       <res-auth>Container</res-auth>
   </resource-ref>
 <!-- druid web监控使用,如果不需要监控,可不用 -->
   <servlet>  
        <servlet-name>DruidStatView</servlet-name>  
        <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>  
    </servlet>    
    <servlet-mapping>  
        <servlet-name>DruidStatView</servlet-name>  
        <url-pattern>/druid/*</url-pattern>  
    </servlet-mapping> 
        
以上为一般工程所需要的基本文件.


其中文件提到了  applicationContext.xml  spring-webmvc.xml

applicationContext.xml 内容如下

<!-- 加载属性文件,如果没有,可不使用 -->
	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location">
			<value>classpath:parameter.properties</value>
		</property>
	</bean>


<!-- Hibernate 联接配置 -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		
		<!-- 指定数据源 -->
		<property name="dataSource">
			<ref bean="dataSource" />
		</property>
		
		<!-- 指定实体映射文件 -->
		<property name="packagesToScan">
			<list>
				<value>com.xuahua.model</value>
			</list>
		</property>
		
		<!-- 属性文件 -->
		<property name="hibernateProperties">
			<value>
				hibernate.dialect=org.hibernate.dialect.MySQLDialect
				hibernate.show_sql=true
				hibernate.format_sql=true
				hibernate.cache.use_second_level_cache=false
				hibernate.use_sql_comments=false
				hibernate.jdbc.batch_size=30
				hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
			</value>
		</property>
	</bean>
 <!-- hibernate事务管理 -->
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate4.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
<!-- 事务切入点 -->
	<aop:config>
		<aop:pointcut id="crudMethodsCoreMaster"
			expression="execution(* com.xuahua.service..*.*(..))" />
		<aop:advisor advice-ref="txAdviceCoreMaster" pointcut-ref="crudMethodsCoreMaster" />
	</aop:config>
	
<!-- hibernate 代理事务,定义哪些service 开头的应该需要事务。哪些只需要只读事务 -->
	<tx:advice id="txAdviceCoreMaster" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="mng*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="create*" propagation="REQUIRED"
				rollback-for="Exception" />
			<tx:method name="save*" propagation="REQUIRED"
				rollback-for="Exception" />
			<tx:method name="update*" propagation="REQUIRED"
				rollback-for="Exception" />
			<tx:method name="insert*" propagation="REQUIRED"
				rollback-for="Exception" />
			<tx:method name="delete*" propagation="REQUIRED"
				rollback-for="Exception" />
			<tx:method name="do*" propagation="REQUIRED" rollback-for="Exception" />
			<tx:method name="load*" read-only="true" />
			<tx:method name="get*" read-only="true" />
			<tx:method name="list*" read-only="true" />
			<tx:method name="find*" read-only="true" />
			<tx:method name="view*" read-only="true" />
			<tx:method name="show*" read-only="true" />
			<tx:method name="valid*" read-only="true" />
			<tx:method name="query*" read-only="true" />
		</tx:attributes>
	</tx:advice>

		<!-- 生产数据源(JNDI)(生产环境、UAT环境、测试环境用) -->
	<beans profile="product">
		<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
			<property name="jndiName">
				<value>${jndiName}</value>
			</property>
		</bean>
	</beans>
<!-- druid web监控使用。 -->
	<beans>
		<bean id="druid-stat-interceptor"
			class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor">
		</bean>
	
	
		<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"
			scope="prototype">
			<property name="patterns">
				<list>
					<value>com.xuahua.service.*</value>
				</list>
			</property>
		</bean>
	
		<aop:config>
			<aop:advisor advice-ref="druid-stat-interceptor"
				pointcut-ref="druid-stat-pointcut" />
		</aop:config>
 	</beans>


spring-mvc.xml文件内容如下

<!-- 定义自动代理 -->
	<aop:aspectj-autoproxy proxy-target-class="true" />
	
	<!-- spring 定义扫描的包,对应工程路径.com.xuahua.controller;dao;service,意味着这三个包下面的所有类,spring会把注解的类名,方法名都会扫描进来 -->
	<context:component-scan base-package="com.xuahua">
		<context:include-filter type="regex"
			expression=".controller..*" />
		<context:include-filter type="regex"
			expression=".dao..*" />
		<context:include-filter type="regex"
			expression=".service..*" />
	</context:component-scan>
    
	<!-- 启动注解的方式 -->
	<context:annotation-config />  
	
 <!-- spring mvc 请求映射处理默认-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
    
    <!-- spring mvc Adapter 请求适配 转换json使用-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <!-- 处理JSON数据转换的-->
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/html;charset=UTF-8</value>
                        </list>
                    </property>
                </bean>
            </list>
        </property>
    </bean>

	<!-- 使用默认的Servlet来响应静态文件-->
	<mvc:default-servlet-handler />
<!-- 视图解释类,定义文件路径,以及文件后缀。 -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
	<!-- 上传文件支持 -->
	<bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

完整文件下载地址  web.xml http://file.xuahua.com/images/blog/2016/0728/web.xml

                          applicationContext.xml  http://file.xuahua.com/images/blog/2016/0728/applicationContext.xml

                         spring-webmvc.xml   http://file.xuahua.com/images/blog/2016/0728/spring-webmvc.xml


spring实战系列一MAVEN工程建立 有更新!

1,前提,maven工程需要的nexus 另外自己搭建;

2,eclipse开发工具流程


2.1 选择maven project

maven-喧哗博客


 指定工程目录


maven-喧哗博客

 建立maven工程对应配置

maven-喧哗博客

maven pom.xml文件指定的groupid


点 Fisnish 。至此 maven工程已经建立起来了。。如果需要运行,请见spring实战系列二配置

spring实战之二maven文件配置

1,建立工程以后,就可以先运行pom.xml可以看到成功,并产生一个空的war包。 如何建工程?请见 spring实战之一maven工程建立

2, 打开编辑pom.xml

在根节点project下,dependencies 节点前添加以下内容

<modelVersion>4.0.0</modelVersion>
  <groupId>blog</groupId>
  <artifactId>com.xuahua</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>com.xuahua Maven Webapp</name>
  <url>http://maven.apache.org</url>
  
  <!-- 定义本pom.xml引用版本属性, org.springframework-version,org.hibernate-version,project.build.sourceEncodeing 此名可随便取,必须与下面引用相匹配。 -->
  <properties>
		<org.springframework-version>4.0.0.RELEASE</org.springframework-version>
		<org.hibernate-version>4.3.1.Final</org.hibernate-version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>
dependencies 节点内,可添加相关联的包

<!-- 下面是springframwork 4.xx 引用的包 -->
    <!-- spring 4 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
   	 <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

Apache Commons 基础组件


<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.6</version>
		</dependency>
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>3.2.1</version>
		</dependency>
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.8.3</version>
		</dependency>

		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3</version>
		</dependency>
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>1.8</version>
		</dependency>
		<dependency>
			<groupId>commons-configuration</groupId>
			<artifactId>commons-configuration</artifactId>
			<version>1.10</version>
		</dependency>
		
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.3.6</version>
		</dependency>
返回json串时,使用到的处理相关包 Jackson 

<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-annotations</artifactId>
			<version>2.5.1</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>2.5.1</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.5.1</version>
		</dependency>
		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-asl</artifactId>
			<version>1.9.13</version>
		</dependency>
slf4j 日志文件框架使用的jar包

<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.2</version>
		</dependency>
mysql driver 数据库驱动包

	<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.15</version>
		</dependency>
 数据库联接池使用的

<!-- c3p0 datasource  数据库联接池使用的,此处是c3p0-->
		<dependency>
			<groupId>c3p0</groupId>
			<artifactId>c3p0</artifactId>
			<version>0.9.1.2</version>
		</dependency>
		<!-- druid 联接池,同时也提供内部默认的监控,个人推荐 -->
		 <dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.23</version>
		</dependency>
		<!-- dbcp使用的默认联接池  配合 commons-pool 使用-->
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
		</dependency>
		<dependency>
			<groupId>commons-pool</groupId>
			<artifactId>commons-pool</artifactId>
			<version>1.5.4</version>
		</dependency>
		
		
		<!-- 中间件 ibatis -->
		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-core</artifactId>
			<version>3.0</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.2.3</version>
		</dependency>
 hiberante 4

<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>${org.hibernate-version}</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>${org.hibernate-version}</version>
		</dependency>
		<dependency>
			<groupId>org.javassist</groupId>
			<artifactId>javassist</artifactId>
			<version>3.18.1-GA</version>
		</dependency>
		<!-- http-client -->
		<dependency>
			<groupId>commons-httpclient</groupId>
			<artifactId>commons-httpclient</artifactId>
			<version>3.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpcore</artifactId>
			<version>4.3.3</version>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpmime</artifactId>
			<version>4.3.3</version>
		</dependency>
		
其他可以用到的

<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.7.4</version>
		</dependency>

		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.7.4</version>
		</dependency>
		<!-- json-lib -->
		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib</artifactId>
			<version>2.4</version>
			<classifier>jdk15</classifier>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.7</version>
		</dependency>
		<!-- memcached -->
		<dependency>
			<groupId>com.whalin</groupId>
			<artifactId>Memcached-Java-Client</artifactId>
			<version>3.0.2</version>
		</dependency>
		<dependency>
			<groupId>com.google.code.maven-play-plugin.spy</groupId>
			<artifactId>spymemcached</artifactId>
			<version>2.6</version>
		</dependency>
		
		<!-- servlet3 -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.0.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.3</version>
			<scope>provided</scope>
		</dependency>

完整的文件可以下载地址 http://file.xuahua.com/images/blog/2016/0728/pom.xml

spring3定时任务之定时任务管理(一) 有更新!

在web互联网时代,定时任务随处可见,做一个定时任务管理界面,由后端操作人员来控制可省不少事情,而且时间可动态变更。也可由开发人员根据业务需求手动动态变更时间。

现在提供一个简单的可用的定时任务管理。

定时任务把任务保存在数据库,也可保存在文件中。下面的例子为保存在服务器文件。

准备工作

1.定义定时任务--包括定时任务名称以及对应的执行方法类;此类任务保存在 taskClass.properties文件中。

2,定义定时任务运行的业务,包括定时任务名称,定时任务的分组,定时任务执行频率,开始执行时间;此类任务定义保存在task.properties文件中。

3,后端的管理操作界面有展示有定时任务名称,执行方法,定时任务操作有(增加,删除,修改,暂停)。

样例图片--喧哗-blog.xuahua.com

关键执行代码:


 @RequestMapping("/taskindex.shtml")
    public String index(Model model){
        try{
            Map<String,String > map= TaskClassPropertiesUtil.getTaskClass();
            model.addAttribute("selectClass",map);

        }catch (Exception e){

        }
        return "admin/task/taskindex";
    }
jsp  下载页面 http://file.xuahua.com/js/blog/taskindex.jsp


js  下载页面   http://file.xuahua.com/js/blog/taskindex.js


TaskClassPropertiesUtil类文件,关键代码


public static String pathUrl=TaskClassPropertiesUtil.class.getResource("/").getPath()+"taskClass.properties";
    public static Map<String ,String> getTaskClass() throws Exception {
        Map<String ,String> map=new HashMap<String ,String>();
            Properties properties =new Properties();
            InputStream in=new FileInputStream(pathUrl);
            BufferedReader bf = new BufferedReader(new  InputStreamReader(in));
            properties.load(bf);
            in.close();
            Enumeration enu=properties.keys();
            while(enu.hasMoreElements()){
                String key=enu.nextElement().toString();
                String value=properties.getProperty(key);
                map.put(key,value);
        
            }
           return  map;
    }

 taskClass.properties 示例下载 http://file.xuahua.com/blog/taskClass.properties

 后续的如何操作定时任务以及动态变更定时任务请见定时任务管理(二)


微信接口开发系列之七微信开放平台支付加密java类 有更新!

如题。微信开放平台支付加密类代码如下


// 微信支付 md5认证
	public static  String getMd5WeixinToPay(String str) {
		MessageDigest md;
		try {
			md = MessageDigest.getInstance("MD5");
			md.reset();
			md.update(str.getBytes("UTF-8"));
			return  byteToStr(md.digest()).toUpperCase();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}
/**
	* 将字节数组转换为十六进制字符串
	* 
	* @param byteArray
	* @return
	*/
	public static String byteToStr(byte[] byteArray) {
		 String strDigest = "";
		 for (int i = 0; i < byteArray.length; i++) {
			 strDigest += byteToHexStr(byteArray[i]);
		 }
	 return strDigest;
	}
/**
	* 将字节转换为十六进制字符串
	* 
	* @param btyes
	* @return
	*/
	public static String byteToHexStr(byte bytes) {
		 char[] Digit = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		 char[] tempArr = new char[2];
		 tempArr[0] = Digit[(bytes >>> 4) & 0X0F];
		 tempArr[1] = Digit[bytes & 0X0F];
		 String s = new String(tempArr);
		 return s;
	}
源地址 :http://blog.xuahua.com/articles/2016/07/13/1468399623674.html


微信接口开发系列之六微信开放平台-移动应用获取微信用户信息 有更新!

如题,如果之前已经申请了微信公众号并且通过审核。那么你还需要移动应用,网站以及其他的应用,那么申请一个微信开放平台账号是不二之选。

今天我们要讲的是微信开放平台移动应用获取微信用户信息。此获取方式有别于微信公众号获取。

具体步骤如下:

1,申请微信开放平台账号,并通过资质审核。

2,登录账号  ,点击 “管理中心”--》移动应用--》创建移动应用,提交相关资料等待微信审核通过。

3,此时,移动应用审核通过后,可以添加移动应用相关的开发信息。获取移动应用微信登录代码如下

1)移动应用获取服务器返回的appid,appsecret,通过此参数调用本地微信应用接口,获取微信应用用户临时授权code。

2)根据临时授权code,交互微信服务器取得登录用户access_token,openid,unionid,scope。

3)如果scope不包含有snsapi_userinfo授权说明用户禁止获取微信用户基本信息。如果有,则进入获取用户信息代码

关键代码:

//=================================================================================微信公众平台账号调用代码
	
	private String getGZURLTokenByCode(String code,String appid,String secret){
		String url = PropertiesUtil.getValue("wx.accessTokenCode");
		//https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
		// url = url.replace("CODE", code);
		String result = "";
		try {
			result = Posturl.getRequest(url);
			if (log.isInfoEnabled()) {
				log.info("根据网页授权code,获取openid,网页授权access_token:---------" + result);
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

//========
Object obj = resultmap.get("access_token");
						if (obj != null) {
							Object scope = resultmap.get("scope");
							Object openid = resultmap.get("openid");
							Object unionid = resultmap.get("unionid");
							result.put("openid", openid == null ? "" : openid);
							result.put("scope", scope == null ? "" : scope);
							result.put("unionid", unionid == null ? "" : unionid);
							if(scope!=null && scope.toString().indexOf("snsapi_userinfo")<0){
								result.put("status", "-1");
								result.put("msg", "用户禁止授权,无snsapi_userinfo权限");
								return result;
							}
							// D:获取微信用户信息
							Map<String,Object> resulttmp = getGZWeiXinUserinfo(obj.toString(), String.valueOf(openid));
							if(resulttmp.get("status") == null){
								result.put("data",JSON.toJSON(resulttmp));
							}else{
								result.putAll(resulttmp);
							}
						}else{
							result.putAll(resultmap);
						}
						return result;


注意:此处有坑,,,很大的坑

微信开放平台移动应用获取微信用户信息请求接口地址为  https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

而微信公众号获取微信用户信息请求接口为 https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

微信公众号需要通过code获取access_token以后,再根据微信基础接口调用的 access_token 去取微信用户信息。
d

数据库-改变字符校验规则

ALTER TABLE `t_mem_notify`
MODIFY COLUMN `openid` varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL AFTER `result`;

公告

喧哗博客--繁华过后的沉寂--技术经验分享^-^
Copyright (c) 2009-2019, b3log.org & hacpai.com