微信扫码登录小dome

pom.xml  jar包
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>weixindemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>weixindemo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.40</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Constanst文件

        

package com.cskt.wxlogin.constanst;


public class Constanst {

    /**
     * 自定义加密措施
     */
    public static final String PWD_MD5 = "Cao#@Feng";
}

WeiXinController文件
package com.cskt.wxlogin.controller;

import com.cskt.wxlogin.constanst.Constanst;
import com.cskt.wxlogin.entity.AccessToken;
import com.cskt.wxlogin.entity.WechatUserUnionID;
import com.cskt.wxlogin.service.impl.WeixinLoginServiceImpl;
import com.cskt.wxlogin.util.AesUtil;
import com.cskt.wxlogin.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class WeiXinController {
    @Autowired
    private WeixinLoginServiceImpl weixinLoginService;

    @RequestMapping("/weixinLogin")
    public  String getWeixinUrl(){

      String url=  weixinLoginService.getLoginUrl();
      //http
        return  "redirect:"+url;
    }

    /**
     * 回调地址处理
     * @param code
     * @param state
     * @return
     */
    @GetMapping(value = "/weixinconnect")
    public ModelAndView callback(String code, String state) {
        String access_token=null;
        String openid=null;
        ModelAndView mav=new ModelAndView();
        if (code != null && state != null) {
            // 验证state为了用于防止跨站请求伪造攻击
            String decrypt = AesUtil.decrypt(AesUtil.parseHexStr2Byte(state), AesUtil.PASSWORD_SECRET_KEY, 16);
            if (!decrypt.equals(Constanst.PWD_MD5 + DateUtil.getYYYYMMdd())) {
                mav.addObject("error","登录失败,请联系管理员!");
                mav.setViewName("loginError");
                return mav;
            }
            AccessToken access = weixinLoginService.getAccessToken(code);
            if (access != null) {
                // 把获取到的access_token和openId赋值给变量
                access_token=access.getAccess_token();
                openid=access.getOpenid();
                // 存在则把当前账号信息授权给扫码用户
                WechatUserUnionID userUnionID = weixinLoginService.getUserUnionID(access_token,openid);
                mav.addObject("userInfo",userUnionID);
                mav.setViewName("main");
                return mav;

            }
        }
        return null;
    }

}

AccessToken文件
package com.cskt.wxlogin.entity;

/**
 * 通过code获取access_token
 */
public class AccessToken {

    /**
     * 接口调用凭证
     */
    private String access_token;

    /**
     * access_token接口调用凭证超时时间,单位(秒)
     */
    private Integer expires_in;

    /**
     * 用户刷新access_token
     */
    private String refresh_token;

    /**
     * 授权用户唯一标识
     */
    private String openid;

    /**
     * 用户授权的作用域,使用逗号(,)分隔
     */
    private String scope;

    /**
     * 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。
     */
    private String unionid;

    public String getAccess_token() {
        return access_token;
    }

    public void setAccess_token(String access_token) {
        this.access_token = access_token;
    }

    public Integer getExpires_in() {
        return expires_in;
    }

    public void setExpires_in(Integer expires_in) {
        this.expires_in = expires_in;
    }

    public String getRefresh_token() {
        return refresh_token;
    }

    public void setRefresh_token(String refresh_token) {
        this.refresh_token = refresh_token;
    }

    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public String getUnionid() {
        return unionid;
    }

    public void setUnionid(String unionid) {
        this.unionid = unionid;
    }

}

HttpParame文件
package com.cskt.wxlogin.entity;

/**
 * HttpParame Description: 请求参数
 */
public class HttpParame {

    // 应用唯一标识
    public static final String APPID = "appid";

    // 密匙
    public static final String SECRET = "secret";

    // 微信用户唯一标识
    public static final String OPENID = "openid";

    // 接口调用凭证
    public static final String ACCESS_TOKEN = "access_token";

    // 回调地址
    public static final String REDIRECT_URI = "redirect_uri";

    // 网页授权回调地址
    public static final String AUTHORIZATION_URL = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";

    // 通过code获取access_token
    public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

    // 此接口用于获取用户个人信息 UnionID机制
    public static final String GET_UNIONID_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";

}

Result文件
package com.cskt.wxlogin.entity;

/**
 * 返回结果包装对象使用
 */
public class Result {

    /**
     * 状态
     */
    private Object status;
    /**
     * 结果
     */
    private Object result;
    /**
     * 消息
     */
    private String message;

    public Result() {
    }

    public Result(Object status, String message) {
        this.status = status;
        this.message = message;
    }

    public Result(Object status, Object result) {
        this.status = status;
        this.result = result;
    }

    public Result(Object status, Object result, String message) {
        this.status = status;
        this.result = result;
        this.message = message;
    }

    public Object getStatus() {
        return status;
    }

    public void setStatus(Object status) {
        this.status = status;
    }

    public Object getResult() {
        return result;
    }

    public void setResult(Object result) {
        this.result = result;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

WechatUserUnionID文件
package com.cskt.wxlogin.entity;

import java.util.List;

/**
 * 获取用户个人信息(UnionID机制)
 */
public class WechatUserUnionID {

    /**
     * 普通用户的标识,对当前开发者帐号唯一
     */
    private String openid;

    /**
     * 普通用户昵称
     */
    private String nickname;

    /**
     * 普通用户性别,1为男性,2为女性
     */
    private Integer sex;

    /**
     * 普通用户个人资料填写的省份
     */
    private String province;

    /**
     * 普通用户个人资料填写的城市
     */
    private String city;

    /**
     * 国家,如中国为CN
     */
    private String country;

    /**
     * 用户头像,最后一个数值代表正方形头像大小 (有0、46、64、96、132数值可选,0代表640*640正方形头像) 用户没有头像时该项为空
     */
    private String headimgurl;

    /**
     * 用户特权信息,json数组,如微信沃卡用户为(chinaunicom)
     */
    private List<String> privilege;

    /**
     * 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。
     */
    private String unionid;

    public String getOpenid() {
        return openid;
    }

    public void setOpenid(String openid) {
        this.openid = openid;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public String getSexStr(){
        if (getSex() != null) return getSex() == 1 ? "男" : "女";
        return "";
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getHeadimgurl() {
        return headimgurl;
    }

    public void setHeadimgurl(String headimgurl) {
        this.headimgurl = headimgurl;
    }

    public List<String> getPrivilege() {
        return privilege;
    }

    public void setPrivilege(List<String> privilege) {
        this.privilege = privilege;
    }

    public String getUnionid() {
        return unionid;
    }

    public void setUnionid(String unionid) {
        this.unionid = unionid;
    }

}

WeixinLoginService文件
package com.cskt.wxlogin.service;

public interface WeixinLoginService {

    String getLoginUrl();

}

WeixinLoginServiceImpl文件
package com.cskt.wxlogin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cskt.wxlogin.constanst.Constanst;
import com.cskt.wxlogin.entity.AccessToken;
import com.cskt.wxlogin.entity.HttpParame;
import com.cskt.wxlogin.entity.WechatUserUnionID;
import com.cskt.wxlogin.service.WeixinLoginService;
import com.cskt.wxlogin.util.AesUtil;
import com.cskt.wxlogin.util.DateUtil;
import com.cskt.wxlogin.util.HttpClientUtil;
import com.cskt.wxlogin.util.PropertiesUtil;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;


@Service
public class WeixinLoginServiceImpl implements WeixinLoginService {

    @Override
    public String getLoginUrl() {
        //第一步    加密
        String content = Constanst.PWD_MD5 + DateUtil.getYYYYMMdd();
        //第二步   加密密钥
        byte[] encrypt = AesUtil.encrypt(content, AesUtil.PASSWORD_SECRET_KEY, 16);
        //把密钥装成二进制
        String parseByte2HexStr = AesUtil.parseByte2HexStr(encrypt);
        //调取接口
        String url = HttpParame.AUTHORIZATION_URL;
        //输送参数
        url = url.replaceAll("APPID", PropertiesUtil.getValue(HttpParame.APPID));
        try {
            //调用回调地址 参数一定要用utf-8
            url = url.replaceAll("REDIRECT_URI", URLEncoder.encode(
                    PropertiesUtil.getValue(HttpParame.REDIRECT_URI), "UTF-8"));

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        url = url.replaceAll("SCOPE", "snsapi_login");
        url = url.replace("STATE", parseByte2HexStr);
        return url;
    }

    public AccessToken getAccessToken(String code) {
        // 调器Code 获取 AccessToken
        String accessTokenUrl = HttpParame.ACCESS_TOKEN_URL;
        //带入 appid 和密钥还有code
        accessTokenUrl = accessTokenUrl.replaceAll("APPID", PropertiesUtil.getValue(HttpParame.APPID));
        accessTokenUrl = accessTokenUrl.replaceAll("SECRET", PropertiesUtil.getValue(HttpParame.SECRET));
        accessTokenUrl = accessTokenUrl.replaceAll("CODE", code);
        String responseContent = HttpClientUtil.getInstance().sendHttpGet(accessTokenUrl);
        if (responseContent == null || responseContent == ""){
            return null;
        }
        JSONObject parseObject = JSONObject.parseObject(responseContent);
        AccessToken accessToken = JSONObject.toJavaObject(parseObject, AccessToken.class);
        return accessToken ;
    }

    public WechatUserUnionID getUserUnionID(String access_token, String openid) {
        //获取用户信息
        String unionIDUrl = HttpParame.GET_UNIONID_URL;
        //根据token获取  用户信息
        unionIDUrl = unionIDUrl.replace("ACCESS_TOKEN",access_token);
        //传入openid
        unionIDUrl = unionIDUrl.replace("OPENID",openid);
        //unionIDUrl = unionIDUrl.replace("CITY","上海");
        //发送请求
        String responseContent = HttpClientUtil.getInstance().sendHttpGet(unionIDUrl);
        //获取回调参数
        System.out.println("responseContent" + responseContent);
        if (responseContent == null || responseContent == "") {
            return null;
        }
        JSONObject parseObject = JSONObject.parseObject(responseContent);
        WechatUserUnionID userUnionID = JSONObject.toJavaObject(parseObject, WechatUserUnionID.class);
        return userUnionID;
    }
}

AesUtil文件
package com.cskt.wxlogin.util;


import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;


/**
 * AES加密解密
 */
public class AesUtil {

   public static void main(String[] args) {
      UUID uuid = UUID.randomUUID();
      String content = "token_"+ DateUtil.getYYYYMMdd()+"_"+uuid;
      System.out.println("内容:"+content);
      byte[] encrypt = AesUtil.encrypt(content, PASSWORD_SECRET_KEY, 16);//加密
      String parseByte2HexStr = AesUtil.parseByte2HexStr(encrypt);//转换为16进制字符串
      System.out.println("加密后:"+parseByte2HexStr);
      byte[] parseHexStr2Byte = AesUtil.parseHexStr2Byte(parseByte2HexStr);
      String decrypt = AesUtil.decrypt(parseHexStr2Byte, PASSWORD_SECRET_KEY, 16);
      System.out.println("解密后:"+decrypt);

      System.out.println("UUID:"+uuid);
   }

   /**
    * 秘钥
    */
   public static final String PASSWORD_SECRET_KEY = "EasyRailEveryday";

   /**
    * 初始向量
    */
   public static final String INITIAL_VECTOR = "EasyRailEasyRail";

    /**
     * 加密
     * @param content 需要加密的内容
     * @param password  加密密码
     * @param keySize 密钥长度16,24,32(密码长度为24和32时需要将local_policy.jar/US_export_policy.jar两个jar包放到JRE目录%jre%/lib/security下)
     * @return
     */
    public static byte[] encrypt(String content, String password, int keySize){
       try {
           //密钥长度不够用0补齐。
          SecretKeySpec key = new SecretKeySpec(ZeroPadding(password.getBytes(Base64Util.DEFAULT_CHARSET), keySize), "AES");
          //定义加密算法AES、算法模式ECB、补码方式PKCS5Padding
            //Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
          //定义加密算法AES 算法模式CBC、补码方式PKCS5Padding
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //CBC模式模式下初始向量 不足16位用0补齐
            IvParameterSpec iv = new IvParameterSpec(ZeroPadding(INITIAL_VECTOR.getBytes(Base64Util.DEFAULT_CHARSET),16));
            byte[] byteContent = content.getBytes();
            //初始化加密
            //ECB
            //cipher.init(Cipher.ENCRYPT_MODE, key);
            //CBC
         cipher.init(Cipher.ENCRYPT_MODE, key,iv);
            byte[] result = cipher.doFinal(byteContent);
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
           e.printStackTrace();
        } catch (Exception e) {
           e.printStackTrace();
        }
        return null;
    }

    /**解密
     * @param content  待解密内容
     * @param password 解密密钥
     * @param keySize 密钥长度16,24,32(密码长度为24和32时需要将local_policy.jar/US_export_policy.jar两个jar包放到JRE目录%jre%/lib/security下)
     * @return
     */
    public static String decrypt(byte[] content, String password, int keySize) {
        try {
           //密钥长度不够用0补齐。
          SecretKeySpec key = new SecretKeySpec(ZeroPadding(password.getBytes(), keySize), "AES");
          //定义加密算法AES、算法模式ECB、补码方式PKCS5Padding
            //Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
          //定义加密算法AES 算法模式CBC、补码方式PKCS5Padding
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            //CBC模式模式下初始向量 不足16位用0补齐
            IvParameterSpec iv = new IvParameterSpec(ZeroPadding(INITIAL_VECTOR.getBytes(Base64Util.DEFAULT_CHARSET),16));
            // 初始化解密
            //ECB
            //cipher.init(Cipher.DECRYPT_MODE, key);
            //CBC
            cipher.init(Cipher.DECRYPT_MODE, key,iv);
            byte[] result = cipher.doFinal(content);
            return new String(result,Base64Util.DEFAULT_CHARSET);
        } catch (NoSuchAlgorithmException e) {
           e.printStackTrace();
        } catch (NoSuchPaddingException e) {
           e.printStackTrace();
        } catch (InvalidKeyException e) {
           e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
           e.printStackTrace();
        } catch (BadPaddingException e) {
           e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e){
           e.printStackTrace();
        } catch (Exception e){
           e.printStackTrace();
        }
        return null;
    }

    /**将二进制转换成16进制
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                    hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**将16进制转换为二进制
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1){
           return null;
        }
        byte[] result = new byte[hexStr.length()/2];
        for (int i = 0;i< hexStr.length()/2; i++) {
            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
            int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    /**
     * 字符达不到指定长度补0
     * @param in 字符数组
     * @param blockSize 长度
     * @return
     */
    public static byte[] ZeroPadding(byte[] in,Integer blockSize){
       Integer copyLen = in.length;
       if (copyLen > blockSize) {
         copyLen = blockSize;
      }
       byte[] out = new byte[blockSize];
       System.arraycopy(in, 0, out, 0, copyLen);
       return out;
    }

}

Base64Util文件
package com.cskt.wxlogin.util;

import org.apache.tomcat.util.codec.binary.Base64;

import java.nio.charset.Charset;


/**
 * Base64Util工具类 --- 加密和解密
 */
public class Base64Util {

   public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
   /**
     * 解密
     * @param str
     * @return
     */
    public static String decodeStr(String str){
        if (str == null) {
         return null;
      }
      if (str.length() == 0) {
         return "";
      }
      return new String(Base64.decodeBase64(new String(str).getBytes(DEFAULT_CHARSET)),DEFAULT_CHARSET).trim();
    }

    /**
     * 加密
     *
     * @param str
     * @return
     */
    public static String encodeStr(String str){
        if (str == null) {
         return null;
      }
      if (str.length() == 0) {
         return "";
      }
        return new String(Base64.encodeBase64Chunked(str.getBytes(DEFAULT_CHARSET)),DEFAULT_CHARSET).trim();
    }

}

DateUtil文件
package com.cskt.wxlogin.util;

import org.springframework.stereotype.Component;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;


/**
 * 日期工具类
 */
@Component // 加此注解是把此类实例化spring容器中
public class DateUtil {

   /**
    * 默认日期格式
    */
   public static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";

   /**
    * 如2018 0901 232211(年月日时分秒)
    *
    * @return
    */
   public String yyyyMMddHHmmss() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
      return sdf.format(Calendar.getInstance().getTime());
   }

   /**
    * 如20180901
    *
    * @return
    */
   public static String getYYYYMMdd() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
      return sdf.format(Calendar.getInstance().getTime());
   }

   /**
    * 如180901
    * @return
    */
   public String getYYMMdd() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
      return sdf.format(Calendar.getInstance().getTime());
   }

   /**
    * 如201809
    * @return
    */
   public String getYYYYMM() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
      return sdf.format(Calendar.getInstance().getTime());
   }

   /**
    * 如 2018/02/11
    * @return
    */
   public String getQueryEndDate() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      return sdf.format(Calendar.getInstance().getTime());
   }

   /**
    * 如 2018/02/11
    * @return
    */
   public String getQueryStartDate() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      Calendar cal = Calendar.getInstance();
      cal.add(Calendar.DAY_OF_YEAR, -30);
      return sdf.format(cal.getTime());
   }

   /**
    * 如 2018/02/11 12:30:00
    * @return
    */
   public static String getQueryEndTime() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      return sdf.format(Calendar.getInstance().getTime());
   }

   /**
    * 如 2018/02/11
    * @return
    */
   public String getQueryStartTime() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      Calendar cal = Calendar.getInstance();
      cal.add(Calendar.DAY_OF_YEAR, -30);
      return sdf.format(cal.getTime());
   }

   public String getQueryTwoAgoDate() {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
      Calendar cal = Calendar.getInstance();
      cal.add(Calendar.DAY_OF_YEAR, -2);
      return sdf.format(cal.getTime());
   }

   /**
    * 字符串转换成日期
    *
    * @param str 字符串
    * @param format 日期格式
    * @return 日期
    */
   public static Date str2Date(String str, String format) {
      if (null == str || "".equals(str)) {
         return null;
      }
      // 如果没有指定字符串转换的格式,则用默认格式进行转换
      if (null == format || "".equals(format)) {
         format = DEFAULT_FORMAT;
      }
      SimpleDateFormat sdf = new SimpleDateFormat(format);
      Date date = null;
      try {
         date = sdf.parse(str);
         return date;
      } catch (ParseException e) {
      }
      return null;
   }

   /**
    * @param date 日期
    * @param format 日期格式
    * @return 字符串
    */
   public static String date2Str(Date date, String format) {
      if (null == date) {
         return null;
      }
      SimpleDateFormat sdf = new SimpleDateFormat(format);
      return sdf.format(date);
   }

   /**
    * 时间戳转换为字符串
    * @param time
    * @return
    */
   public static String timestamp2Str(Timestamp time) {
      Date date = new Date(time.getTime());
      return date2Str(date, DEFAULT_FORMAT);
   }

   /**
    * 字符串转换为时间
    * @param str
    * @return
    */
   public static Timestamp str2Timestamp(String str) {
      Date date = str2Date(str, DEFAULT_FORMAT);
      return new Timestamp(date.getTime());
   }

   /**
    * 字符串转换为时间
    * @param str
    * @return
    */
   public static Timestamp str2Timestamp(String str, String formatStr) {
      if (null == str) {
         return null;
      }
      Date date = str2Date(str, formatStr);
      return new Timestamp(date.getTime());
   }

   /**
    * 获取某年第一天日期
    * @param year 年份
    * @return Date
    */
   public static Date getYearFirst(int year) {
      Calendar calendar = Calendar.getInstance();
      calendar.clear();
      calendar.set(Calendar.YEAR, year);
      Date currYearFirst = calendar.getTime();
      return currYearFirst;
   }

   /**
    * 获取某年最后一天日期
    * @param year  年份
    * @return Date
    */
   public static Date getYearLast(int year) {
      Calendar calendar = Calendar.getInstance();
      calendar.clear();
      calendar.set(Calendar.YEAR, year);
      calendar.roll(Calendar.DAY_OF_YEAR, -1);
      Date currYearLast = calendar.getTime();

      return currYearLast;
   }

   @SuppressWarnings("static-access")
   public static Date getnextLast(String datetime, int year) {
      Calendar calendar = new GregorianCalendar();
      Date date = null;
      if (datetime.length() > 7) {
         date = str2Date(datetime, "yyyy-MM-dd");
      } else {
         date = str2Date(datetime, "yyyy-MM");
      }
      calendar.setTime(date);
      calendar.add(calendar.YEAR, year);// 把日期往后增加一年.整数往后推,负数往前移动
      date = calendar.getTime();
      return date;

   }

   public static String getrightDate(String datetime, int year) {
      String date = "";
      String years = datetime.substring(0, 4);
      String dates = datetime.substring(4, datetime.length());
      Integer s = new Integer(years) + year;
      date = s + dates;
      return date;
   }

   public static void main(String[] args) {
      System.out.println(getrightDate("2018-09", 4));
      System.out.println(date2Str(getnextLast("2018-09", 4), "yyyy-MM"));
   }

}

HttpClientUtil文件
package com.cskt.wxlogin.util;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.util.PublicSuffixMatcher;
import org.apache.http.conn.util.PublicSuffixMatcherLoader;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * httpClient 工具类
 */
public class HttpClientUtil {

   /**
    * 默认参数设置
    * setConnectTimeout:设置连接超时时间,单位毫秒。
    * setConnectionRequestTimeout:设置从connect Manager获取Connection 超时时间,单位毫秒。
    * setSocketTimeout:请求获取数据的超时时间,单位毫秒。访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。 暂时定义15分钟
    */
   private RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(600000).setConnectTimeout(600000).setConnectionRequestTimeout(600000).build();

   /**
    * 静态内部类---作用:单例产生类的实例
    * @author Administrator
    *
    */
   private static class LazyHolder {
       private static final HttpClientUtil INSTANCE = new HttpClientUtil();

    }
   private HttpClientUtil(){}
   public static HttpClientUtil getInstance(){
      return LazyHolder.INSTANCE;
   }

   /**
    * 发送 post请求
    * @param httpUrl 地址
    */
   public String sendHttpPost(String httpUrl) {
      HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
      return sendHttpPost(httpPost);
   }

   /**
    * 发送 post请求
    * @param httpUrl 地址
    * @param params 参数(格式:key1=value1&key2=value2)
    */
   public String sendHttpPost(String httpUrl, String params) {
      HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
      try {
         //设置参数
         StringEntity stringEntity = new StringEntity(params, "UTF-8");
         stringEntity.setContentType("application/x-www-form-urlencoded");
         httpPost.setEntity(stringEntity);
      } catch (Exception e) {
         e.printStackTrace();
      }
      return sendHttpPost(httpPost);
   }

   /**
    * 发送 post请求
    * @param httpUrl 地址
    * @param maps 参数
    */
   public String sendHttpPost(String httpUrl, Map<String, String> maps) {
      HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
      // 创建参数队列
      List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
      for (String key : maps.keySet()) {
         nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
      }
      try {
         httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
      } catch (Exception e) {
         e.printStackTrace();
      }
      return sendHttpPost(httpPost);
   }

   /**
    * 发送Post请求
    * @param httpPost
    * @return
    */
   private String sendHttpPost(HttpPost httpPost) {
      CloseableHttpClient httpClient = null;
      CloseableHttpResponse response = null;
      HttpEntity entity = null;
      String responseContent = null;
      try {
         // 创建默认的httpClient实例
         httpClient = HttpClients.createDefault();
         httpPost.setConfig(requestConfig);
         // 执行请求
         long execStart = System.currentTimeMillis();
         response = httpClient.execute(httpPost);
         long execEnd = System.currentTimeMillis();
         System.out.println("=================执行post请求耗时:"+(execEnd-execStart)+"ms");
         long getStart = System.currentTimeMillis();
         entity = response.getEntity();
         responseContent = EntityUtils.toString(entity, "UTF-8");
         long getEnd = System.currentTimeMillis();
         System.out.println("=================获取响应结果耗时:"+(getEnd-getStart)+"ms");
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         try {
            // 关闭连接,释放资源
            if (response != null) {
               response.close();
            }
            if (httpClient != null) {
               httpClient.close();
            }
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
      return responseContent;
   }

   /**
    * 发送 get请求
    * @param httpUrl
    */
   public String sendHttpGet(String httpUrl) {
      HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
      return sendHttpGet(httpGet);
   }

   /**
    * 发送 get请求Https
    * @param httpUrl
    */
   public String sendHttpsGet(String httpUrl) {
      HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
      return sendHttpsGet(httpGet);
   }

   /**
    * 发送Get请求
    * @param httpPost
    * @return
    */
   private String sendHttpGet(HttpGet httpGet) {
      CloseableHttpClient httpClient = null;
      CloseableHttpResponse response = null;
      HttpEntity entity = null;
      String responseContent = null;
      try {
         // 创建默认的httpClient实例.


         httpClient = HttpClients.createDefault();

         httpGet.setConfig(requestConfig);
         // 执行请求
         response = httpClient.execute(httpGet);
         entity = response.getEntity();
         responseContent = EntityUtils.toString(entity, "UTF-8");
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         try {
            // 关闭连接,释放资源
            if (response != null) {
               response.close();
            }
            if (httpClient != null) {
               httpClient.close();
            }
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
      return responseContent;
   }

   /**
    * 发送Get请求Https
    * @param httpPost
    * @return
    */
   private String sendHttpsGet(HttpGet httpGet) {
      CloseableHttpClient httpClient = null;
      CloseableHttpResponse response = null;
      HttpEntity entity = null;
      String responseContent = null;
      try {
         // 创建默认的httpClient实例.
         PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpGet.getURI().toString()));
         DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
         httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
         httpGet.setConfig(requestConfig);
         // 执行请求
         response = httpClient.execute(httpGet);
         entity = response.getEntity();
         responseContent = EntityUtils.toString(entity, "UTF-8");
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         try {
            // 关闭连接,释放资源
            if (response != null) {
               response.close();
            }
            if (httpClient != null) {
               httpClient.close();
            }
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
      return responseContent;
   }



}
PropertiesUtil文件
package com.cskt.wxlogin.util;

import java.io.*;
import java.net.URI;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;


/**
 * properties资源文件解析工具
 */
public class PropertiesUtil {

   private static Properties props = null;
   private static URI uri;
   private static String fileName = "/weixinconnectconfig.properties";

   private static InputStream in = null;

   static {
      try {
         props = new Properties();
         InputStream fis = PropertiesUtil.class.getResourceAsStream(fileName);
         props.load(fis);
         uri = PropertiesUtil.class.getResource(fileName).toURI();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

   /**
    * 获取某个属性
    */
   public static String getProperty(String key) {
      try {
         props.load(PropertiesUtil.class.getResourceAsStream(fileName));
      } catch (IOException e) {
         e.printStackTrace();
      }
      return props.getProperty(key);
   }

   /**
    * 获取所有属性,返回一个map,不常用 可以试试props.putAll(t)
    */
   @SuppressWarnings("rawtypes")
   public static Map<String, String> getAllProperty() {
      Map<String, String> map = new HashMap<String, String>();
      Enumeration enu = props.propertyNames();
      while (enu.hasMoreElements()) {
         String key = (String) enu.nextElement();
         String value = props.getProperty(key);
         map.put(key, value);
      }
      return map;
   }

   /**
    * 在控制台上打印出所有属性,调试时用。
    */
   public static void printProperties() {
      props.list(System.out);
   }

   /**
    * 写入properties信息
    */
   public static void writeProperties(String key, String value) {
      try {
         OutputStream fos = new FileOutputStream(new File(uri));
         props.setProperty(key, value);
         // 将此 Properties 表中的属性列表(键和元素对)写入输出流
         props.store(fos, "『comments』Update key:" + key);
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

   /**
    * 取默认key的value
    * */
   public static String getValue(String key){
      String value = null;
      props = new Properties();
      in = PropertiesUtil.class.getResourceAsStream(fileName);
      try {
         props.load(in);
      } catch (IOException e) {
//       e.printStackTrace();
      }
      value = (String) props.get(key);
      return value;
   }

}

application.yml配置文件
server:
  port: 80
spring:
  thymeleaf:
    mode: HTML5
    prefix: classpath:/templates/
    suffix: .html
    cache: false

weixinconnectconfig.properties配置文件

appid=wx9dbc36f6430dc621

secret=11f48317f08fe2afbdf5cb80dcc4e99d

redirect_uri=http://www.csktedu.com/weixinconnect

templates文件夹

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title th:text="${title}"></title>
</head>
<body>
<div style="padding: 40px">
    <font color="black"><strong>微信扫码登录测试</strong></font><br/><br/><a href="/weixinLogin"><img src="/images/weixinlogin.png"/></a>
</div>
</body>
</html>

main

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<div style="padding: 20px">
    <p>微信唯一标识OpenId:&nbsp;<font th:text="${userInfo.openid}"></font></p>
<p>昵称:&nbsp;<font th:text="${userInfo.nickname}"></font></p>
<p>性别:&nbsp;<font th:text="${userInfo.sexStr}"></font></p>
<p><img th:src="${userInfo.headimgurl}"/></p>
</div>
ooxx
</body>
</html>

整体目录如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值