2017年 的存档
20179 月15

使用Java API绘制验证码图片

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

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

/**
 * 生成验证码,将验证码绘制成一张图片返回浏览器
 * 
 * @author FreeDroid
 *
 */
public class CheckcodeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public void service(HttpServletRequest request, 
              HttpServletResponse response) throws 
                     ServletException, IOException {
        /*
         * step1.绘图
         */
        Random r = new Random();
        //从getString()方法取出A-Z,0-9的指定长度随机字符串
        String number = getString(5);
        //先创建一个画布(内存映像对象)
        BufferedImage image = new BufferedImage(80, 30, BufferedImage.TYPE_INT_BGR);
        //获得画笔
        Graphics g = image.getGraphics();
        //给画笔设置颜色
        g.setColor(new Color(255, 255, 255));
        //给画布设置背景颜色
        g.fillRect(0, 0, 80, 30);
        //设置字体
        g.setFont(new Font(null, Font.BOLD|Font.ITALIC, 20));
        //给每个字符设置随机颜色,并画到画布上
        for (int i = 0; i < number.length(); i++) {
            //给画笔设置颜色
            g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)));
            //在画布上画字符
            g.drawString(String.valueOf(number.charAt(i)), i*15, 25);
        }
        //加一些干扰线
        for (int i = 0; i < 8; i++) {
            //给画笔设置颜色
            g.setColor(new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)));
            //在画布范围内画线
            g.drawLine(r.nextInt(80), r.nextInt(30), r.nextInt(80), r.nextInt(30));
        }

        /*
         * step2.将图片压缩,然后输出
         */
        //设置响应内容类型为JPEG格式的图片
        response.setContentType("image/jpeg");
        //获得字节输出流(图片是二进制数据)
        OutputStream os = response.getOutputStream();
        //将原始图片(image)按照指定的算法压缩(jpeg)
                //然后将压缩之后得到的字节写入response对象。
        javax.imageio.ImageIO.write(image, "jpeg", os);
        os.close();     
    }

    /**
     * 随机生成指定长度的大写字母和数字组合
     * @param length
     * @return
     */
    private String getString(int length) {
        StringBuilder str = new StringBuilder();
        Random r = new Random();
        //取出大写字母
        for (int i = 0; i < 26; i++) {
            str.append((char) ('A' + i));
        }
        //取出数字
        for (int i = 0; i < 10; i++) {
            str.append((char) ('0' + i));
        }
        //从字符串str随机取length个字符放进str2组成新的字符串
        StringBuilder str2 = new StringBuilder();
        for (int i = 0; i < length; i++) {
            str2.append(str.charAt(r.nextInt(str.length())));
        }
        return str2.toString();
    }

}
20178 月11

UTF-8中文字符编码和解码,用位运算实现

/**
 * UTF中文字符编码和解码
 * 中文字符占3个字节,前缀分别是:1110XXXX 10XXXXXX 10XXXXXX
 * 
 * @author FreeDroid
 *
 */
public class Utf8codeANDdecode {

    public static void main(String[] args) {
        int ch = '我';
        byte[] bytes = codeUTF8(ch);
        char ch2 = decodeUTF8(bytes);
        System.out.println(ch2);
    }

    /**
     * 解码
     * @param bytes
     * @return
     */
    public static char decodeUTF8(byte[] bytes) {
        int ch = (bytes[0]<<12&0xffff)|(bytes[1]<>> 6 & 0x3f | 0x80;
        int b1 = ch >>> 12 & 0xf | 0xe0;
        return new byte[] { (byte) b1, (byte) b2, (byte) b3 };
    }

}
20177 月30

同名文件自动建立副本递归实现

public void newFile(File file){
    try {
        if (file.createNewFile()) {
            System.out.println("文件创建成功!");
        } else {
            String cName = changeName(file);
            File files = new File("." + File.separator + cName);
            newFile(files);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
public String changeName(File file) {
    String name = file.getName();
    int index = name.lastIndexOf('.');
    int index2 = name.lastIndexOf("_副本");
    if (index2 < 0) {
        return name.substring(0, index) + "_副本1" + name.substring(index);
    } else {
        String num = name.substring(index2+3, index);
        int i = Integer.valueOf(num)+1;
        return name.substring(0, index2) + "_副本" + i + name.substring(index);
    }
}
20177 月4

分享:微信电子导航DEMO

后台JAVA代码:

 

package cn.wizzer.app.web.modules.controllers.front.wx;

import cn.wizzer.app.web.commons.base.Globals;
import cn.wizzer.app.wx.modules.services.WxAddressService;
import cn.wizzer.app.wx.modules.services.WxConfigService;
import org.nutz.dao.Cnd;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.weixin.at.impl.MemoryJsapiTicketStore;
import org.nutz.weixin.spi.WxApi2;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * Created by wizzer on 2017/6/27.
 */
@IocBean
@At("/public/wx/add")
public class AddController {
    private static final Log log = Logs.get();
    @Inject
    private WxConfigService wxConfigService;
    @Inject
    private WxAddressService wxAddressService;

    @At("/index/?")
    @Ok("beetl:/public/add/index.html")
    public void index(String wxid,HttpServletRequest req, HttpSession session) {
        WxApi2 wxApi2 = wxConfigService.getWxApi2(wxid);
        if (Lang.isEmpty(Globals.memoryJsapiTicketStore.get(wxid))) {
            Globals.memoryJsapiTicketStore.put(wxid, new MemoryJsapiTicketStore());
        }
        MemoryJsapiTicketStore memoryJsapiTicketStore = Globals.memoryJsapiTicketStore.get(wxid);
        wxApi2.setJsapiTicketStore(memoryJsapiTicketStore);
        String url = "http://" + Globals.AppDomain + Globals.AppBase + "/public/wx/add/index/"+wxid;
        NutMap jsConfig = wxApi2.genJsSDKConfig(url, "getLocation");

        req.setAttribute("list", wxAddressService.query(Cnd.orderBy().asc("opAt")));
        req.setAttribute("jsConfig", Json.toJson(jsConfig));
    }
}

前台代码:



    
    电子导航

    
    
    
    
    
    
    
    
    
    
        var base = '${base!}';
    
    
    
    



公司检索

公司名称:
当前位置:
  • ${oLP.index}、${o.name}
    lng:${o.lng}, lat:${o.lat}
  • 没有检索到结果
function goTo(type,name,lng,lat) { var longitude=$("#longitude").val(); var latitude=$("#latitude").val(); window.location.href="http://apis.map.qq.com/uri/v1/routeplan?type="+type+"&from=我的位置&fromcoord="+latitude+","+longitude+"&to="+name+"&tocoord="+lat+","+lng+"&policy=1&referer=电子导航"; //window.location.href="http://api.map.baidu.com/direction?origin=latlng:"+latitude+","+longitude+"|name:我的位置&destination=latlng:"+lat+","+lng+"|name:"+name+"&mode=driving&region=合肥&output=html&src=电子导航"; } wx.config(${jsConfig}); wx.ready(function(){ wx.getLocation({ type: 'gcj02', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02' success: function (res) { var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90 var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。 var speed = res.speed; // 速度,以米/每秒计 var accuracy = res.accuracy; // 位置精度 $("#latitude").val(latitude); $("#longitude").val(longitude); } }); });
20173 月23

NutzWk: 微信AccessToken没有持久化造成超出调用限制的问题解决

1、wx_config 实体类添加三个字段,对应的表结构也要手动修改:

    @Column
    @Comment("access_token")
    @ColDefine(type = ColType.VARCHAR, width = 255)
    private String access_token;

    @Column
    @Comment("access_token_expires")
    @ColDefine(type = ColType.INT)
    private Integer access_token_expires;

    @Column
    @Comment("access_token_lastat")
    @ColDefine(type = ColType.VARCHAR, width = 50)
    private String access_token_lastat;

    get  set ...方法生成出来

2、nutzwx版本升级为1.r.61-SNAPSHOT

        
            org.nutz
            nutzwx
            1.r.61-SNAPSHOT
        

3、nutz版本升级为1.r.60

        
            org.nutz
            nutz
            1.r.60
        

4、WxConfigService 类getWxApi2替换为如下代码(主要是DaoAccessTokenStore从数据库取access_token)

    public WxApi2 getWxApi2(String wxid) {
        Wx_config appInfo = this.fetch(Cnd.where("id", "=", wxid));
        DaoAccessTokenStore myDaoAccessTokenStore = new DaoAccessTokenStore(dao());
        Map params = new HashMap();
        params.put("id", appInfo.getId());
        myDaoAccessTokenStore.setTableAccessToken("access_token");
        myDaoAccessTokenStore.setTableAccessTokenExpires("access_token_expires");
        myDaoAccessTokenStore.setTableAccessTokenLastat("access_token_lastat");
        myDaoAccessTokenStore.setFetch("select access_token,access_token_expires,access_token_lastat from wx_config where id=@id");
        myDaoAccessTokenStore.setUpdate("update wx_config set access_token=@access_token, access_token_expires=@access_token_expires, access_token_lastat=@access_token_lastat where id=@id");
        myDaoAccessTokenStore.setParams(params);
        WxApi2Impl wxApi2 = new WxApi2Impl();
        wxApi2.setAppid(appInfo.getAppid());
        wxApi2.setAppsecret(appInfo.getAppsecret());
        wxApi2.setEncodingAesKey(appInfo.getEncodingAESKey());
        wxApi2.setToken(appInfo.getToken());
        wxApi2.setAccessTokenStore(myDaoAccessTokenStore);
        return wxApi2;
    }
20173 月17

log4j 换成 logback 注意事项

pom.xml

 

  
    ch.qos.logback  
    logback-classic  
    1.2.2  
  
  
    org.logback-extensions  
    logback-ext-spring  
    0.1.4  
  
  
    org.slf4j  
    jcl-over-slf4j  
    1.7.25  

  
    org.slf4j  
    log4j-over-slf4j  
    1.7.25  

 

排除其他包的log4j引用,特别是dubbo的、shiro的

 

        
            com.alibaba
            dubbo
            2.8.4
            
                
                    log4j
                    log4j
                
            
        
        
            javax.ws.rs
            javax.ws.rs-api
            2.0
            
                
                    log4j
                    log4j
                
            
        
        
            org.apache.shiro
            shiro-ehcache
            1.3.2
            
                
                    log4j
                    log4j
                
            
        
        
            org.apache.shiro
            shiro-web
            1.3.2
            
                
                    log4j
                    log4j
                
            
        

配置文件:










    
        /monitor.log

        
        
        
            /monitor.%i.log.gz
            
            
            1
            5
        

        
        
            300MB
        

        
        true
        GBK

        
        
            [%-5level] %d{HH:mm:ss.SSS} [%thread] %logger %caller{2} - %msg%n
        
    
    
    
    
    
    
    
    
    
        
    
20173 月8

怀孕

“医生,你得救救我们啊,我们在一起三年了都没有怀孕,父母还等着抱孙子呢!”医生:“这我也没办法啊,这都是你们自己的问题。”“不行啊,医生你帮帮我们吧。”医生:“首先,你们得各自找个女朋友。”

20171 月12

培训班

记得初入公司时,写的代码乱七八糟,错误百出,bug连连,不仅项目经理骂我,其他同事也对我怨声载道。后来听朋友介绍,就报了一个培训班。经过1个月的刻苦学习,终于功夫不负有心人啊—他们都骂不过我了。