阿里云部署Java网站和微信开发调试心得技巧

news/2024/5/20 15:47:58/文章来源:https://blog.csdn.net/qq_41479464/article/details/86775042

阿里云部署Java网站和微信开发调试心得技巧(上)

阿里云部署Java网站和微信开发调试心得技巧(上)
本篇手记旨在帮助大家从0开始:

  1. 申请阿里云服务器
  2. 搭建出程序的执行环境
  3. 在服务器上发布并运行自己的web project
  4. 域名解析
  5. 微信测试号的申请与连接以获取微信用户信息
    全篇文章主要以如何去完成目标为主,因此会以流程的形式来展现,细节方面需要大家多多思考。其中文章的上集实现了1-4,文章的下集实现了5
    一、申请阿里云服务器
    (1)PC访问阿里云https://www.aliyun.com/,申请阿里云帐号(可以用您的支付宝帐号登录,因为支付宝帐号已经进行了实名认证,使用起来更方便)并登录
    (2)找到云服务器ECS购买页面(页面展现随时会变,当前为全部导航->产品->弹性计算->云服务器ECS->选择自己需要的型号(我选择的是入门级)),购买云服务器,这里主要有三种方式:9块9的学生服务器(大家如果不是学生的话可以用还在读大学的小伙伴的学生证来薅羊毛,购买)、包年包月的服务器(不管你怎么使用,按年按月收费)还有按量付费的服务器(按小时计费,不用可以随时注销掉)
    图片描述
    操作系统记得选择centos,这里我用的是最新的7.3版本
    图片描述
    上半部分的安全设置里面需要填写上root的登录密码,以后咱们需要用这个root帐号来远程登录服务器去做部署,下半部分主要显示的是您选择的阿里云清单
    图片描述
    开通成功后,服务器会启动并运行,同时会自动分配一个公网IP,咱们外网就可以通过这个公网IP访问服务器,同时也可以将域名解析到这个服务器中。
    图片描述
    这里翔仔的公网IP为47.104.1.235
    二、搭建程序的执行环境
    搭建程序的执行环境,咱们先列一下常用的执行环境清单:
    (1) JDK(这里选择的是JDK1.8)
    下载地址为
    http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
    选择的是jdk-8u144-linux-x64.rpm
    (2) Tomcat 8
    下载地址为
    http://tomcat.apache.org/download-80.cgi#8.0.46
    选择的是apache-tomcat-8.0.46.tar.gz
    (3) Mysql(这里选择的是Mysql5.7)repo源,后通过centos自带的yum安装
    下载的地址为
    https://dev.mysql.com/downloads/repo/yum/
    这里选择mysql57-community-release-el7-11.noarch.rpm
    (4) Redis(可选,最好预先安装上,这里选择的版本为4.0.2)
    下载地址为
    https://redis.io/download
    这里选择redis-4.0.2.tar.gz
    将上面的软件都下载到本地,并上传到服务器(如果您的系统为MAC或LINUX,直接使用SCP命令行上传,具体指令可以查询网上,如果您的系统为WIN,推荐使用filezilla可视化上传工具上传),或者您也可以直接登录服务器,wget+ftp地址直接下载这些软件;同时需要大家注意的是,我们在服务器上部署了数据库之后,需要往数据库里面去补充数据,我们的线上数据访问的是线上的数据库而非本地的数据库。图片包也需要上传到服务器并通过配置server.xml确保能读取到这些图片(前提是docBase配置上的路径已经在服务器上创建)
    图片描述
    可以在阿里云控制台进入终端
    图片描述
    在服务器的终端,正确的情况下就能看到这些软件了。
    图片描述
    接下来开始安装这些软件:
  6. 安装JDK
    Java程序需要运行在JRE里边,因此咱们需要安装JDK,在软件路径里执行
    //添加可执行权限
    chmod +x jdk-8u144-linux-x64.rpm
    //安装RPM软件包
    rpm -ivh jdk-8u144-linux-x64.rpm
    //查看java的版本信息,若出现版本信息则成功
    java –version
    图片描述
  7. 安装Mysql
    安装用来配置mysql的yum源的rpm包
    rpm -Uvh mysql57-community-release-el7-11.noarch.rpm
    安装Mysql
    yum install mysql-community-server
    图片描述
    开启mysql服务
    service mysqld start
    图片描述
    mysql安装成功后创建的超级用户’root’@‘localhost’的密码会被存储在/var/log/mysqld.log,可以使用如下命令查看密码
    grep ‘temporary password’ /var/log/mysqld.log
    图片描述
    使用mysql生成的’root’@‘localhost’用户和密码登录数据库,并修改 其密码,具体命令
    mysql -uroot -p
    ALTER USER ‘root’@‘localhost’ IDENTIFIED BY ‘Xiangze230!’;
    图片描述
    开启远程连接
    通过阿里云控制台开放3306端口
    在阿里云控制台咱们的实例页面下面选择安全组->配置规则
    图片描述
    进入到规则配置页面之后,咱们可以看到目前只有22端口和3389端口支持远程访问,咱们还需要额外开通80端口(微信公众号用),3306端口(mysql)以及6379端口(redis)
    图片描述
    配置一个支持远程登录的帐号,这里配置一个work帐号
    mysql -u root -p
    use mysql;
    grant SELECT,UPDATE,INSERT,DELETE on . to ‘work’@’%’ identified by ‘Xiangze230!’;//创建work帐号并授权,同时设置密码
    flush privileges;//生效配置
    之后便能在我们本地通过调用mysql指令远程登录阿里云服务器上的mysql server中,
    mysql -uwork -P3306 -h47.104.1.235 –p //本机远程登录mysql指令
    图片描述
  8. 安装redis
    redis安装真的特别简单,首先先解压redis安装包
    tar -zxvf redis-4.0.2.tar.gz
    设置redis以支持远程登录
    vi redis-4.0.2/redis.conf
    将bind 127.0.0.1这句话用井号注释掉,这样就能支持远程连接了
    图片描述
    此外,还需要给redis.conf添加配置以支持redis作为守护进程一直跑在后台
    需要加入『daemonize yes』
    图片描述
    安装redis
    去到解压后的目录里
    cd redis-4.0.2
    make //安装redis
    启动redis服务
    src/redis-server redis.conf
    图片描述
    redis连接测试
    通过redis-cli连接到redis服务器
    src/redis-cli
    当输入ping 得到pong的回应之后,证明redis配置已经完成
    图片描述
    4.安装tomcat 8
    tomcat 8的安装更为简单
    解压tomcat压缩包
    tar -zxvf apache-tomcat-8.0.46.tar.gz
    启动tomcat
    ./apache-tomcat-8.0.46/bin/startup.sh
    图片描述
    三、在服务器上发布并运行自己的web project
    修改tomcat默认启动端口,从8080修改为80端口,便于微信登录
    vi apache-tomcat-8.0.46/conf/server.xml
    图片描述
    重启tomcat
    ./apache-tomcat-8.0.46/bin/shutdown.sh
    ./apache-tomcat-8.0.46/bin/startup.sh
    修改自己本地的网站的配置
    这里由于大家自己的java网站项目的配置都不相同,只能说大概的,即把项目里的mysql配置(如果有的话),redis配置(如果有的话)修改为阿里云服务器对应的配置(即ip,端口,密码等配置修改成服务器里安装好的这些软件的对应的配置)
    图片描述
    打出自己项目的war包
    图片描述
    图片描述
    图片描述
    将export出来的war包上传到服务器tomcat的webapps目录下
    scp o2o.war root@47.104.1.235:/root/apache-tomcat-8.0.46/webapps
    图片描述
    上传成功后,没过几秒tomcat便会在webapps目录下自动从项目war包中解析出项目工程目录来
    图片描述
    之后通过ip+请求路径的形式便能访问到自己的项目(因为已经设置成80端口,这是http默认访问的端口,所以不需要在URL里添加端口信息了)
    图片描述
    四、域名解析
    如果通过ip连接微信号,则总会弹出烦人的警告窗口,因此咱们可以先购买一个域名并对域名进行认证(具体的备案步骤不同服务商有不同要求,大家可以按照他们的要求来,主要分有个人认证和企业认证两种,当然大家如果不嫌烦,可以直接用ip即跳过域名解析这一步),建议大家看看周围的朋友有谁已经有经过验证的域名了,这样可以直接借他的域名创建一个二级域名来用,方便省事,翔仔购买的是阿里云控制台里面的万网域名,购买并认证成功后,会有如下截图,选择购买好的域名并点击解析创建出二级域名
    图片描述
    进入到解析的页面,选择添加解析,并在A记录里面设置好O2O,IP里面设置咱们的阿里云服务器公网IP。这样就能创建出o2o.yitiaojieinfo.com这样的域名指向该公网IP
    图片描述
    隔一段时间,大概5-10分钟这样子,通过域名访问咱们的站点,就能发现访问是okay的

 

五、微信测试号的申请与连接以获取微信用户信息
在咱们自己的程序里面编写servlet以响应微信号
在接下来的步骤中,我们将在测试号里面设置接口配置信息的URL,一经设置,微信公众号便会发请求到我们设置好的URL去,我们必须编写程序应答才能顺利连通微信公众号,因此咱们需要编写相应的响应程序
需要编写两个类
【SignUtil】

 
  1. package com.imooc.o2o.util.weixin;

  2.  
  3. import java.security.MessageDigest;

  4. import java.security.NoSuchAlgorithmException;

  5. import java.util.Arrays;

  6.  
  7. /**

  8. * 微信请求校验工具类

  9. */

  10. public class SignUtil {

  11. // 与接口配置信息中的Token要一致

  12. private static String token = "myo2o";

  13.  
  14. /**

  15. * 验证签名

  16. *

  17. * @param signature

  18. * @param timestamp

  19. * @param nonce

  20. * @return

  21. */

  22. public static boolean checkSignature(String signature, String timestamp, String nonce) {

  23. String[] arr = new String[] { token, timestamp, nonce };

  24. // 将token、timestamp、nonce三个参数进行字典序排序

  25. Arrays.sort(arr);

  26. StringBuilder content = new StringBuilder();

  27. for (int i = 0; i < arr.length; i++) {

  28. content.append(arr[i]);

  29. }

  30. MessageDigest md = null;

  31. String tmpStr = null;

  32.  
  33. try {

  34. md = MessageDigest.getInstance("SHA-1");

  35. // 将三个参数字符串拼接成一个字符串进行sha1加密

  36. byte[] digest = md.digest(content.toString().getBytes());

  37. tmpStr = byteToStr(digest);

  38. } catch (NoSuchAlgorithmException e) {

  39. e.printStackTrace();

  40. }

  41.  
  42. content = null;

  43. // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信

  44. return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;

  45. }

  46.  
  47. /**

  48. * 将字节数组转换为十六进制字符串

  49. *

  50. * @param byteArray

  51. * @return

  52. */

  53. private static String byteToStr(byte[] byteArray) {

  54. String strDigest = "";

  55. for (int i = 0; i < byteArray.length; i++) {

  56. strDigest += byteToHexStr(byteArray[i]);

  57. }

  58. return strDigest;

  59. }

  60.  
  61. /**

  62. * 将字节转换为十六进制字符串

  63. *

  64. * @param mByte

  65. * @return

  66. */

  67. private static String byteToHexStr(byte mByte) {

  68. char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

  69. char[] tempArr = new char[2];

  70. tempArr[0] = Digit[(mByte >>> 4) & 0X0F];

  71. tempArr[1] = Digit[mByte & 0X0F];

  72.  
  73. String s = new String(tempArr);

  74. return s;

  75. }

  76. }

【WechatController】

 
  1. package com.imooc.o2o.web.wechat;

  2.  
  3. import java.io.IOException;

  4. import java.io.PrintWriter;

  5.  
  6. import javax.servlet.http.HttpServletRequest;

  7. import javax.servlet.http.HttpServletResponse;

  8.  
  9. import org.slf4j.Logger;

  10. import org.slf4j.LoggerFactory;

  11. import org.springframework.stereotype.Controller;

  12. import org.springframework.web.bind.annotation.RequestMapping;

  13. import org.springframework.web.bind.annotation.RequestMethod;

  14.  
  15. import com.imooc.o2o.util.wechat.SignUtil;

  16.  
  17. @Controller

  18. //一会在设置的URL里面就设置上这个路由

  19. @RequestMapping("wechat")

  20. public class WechatController {

  21.  
  22. private static Logger log = LoggerFactory.getLogger(WechatController.class);

  23.  
  24. @RequestMapping(method = { RequestMethod.GET })

  25. public void doGet(HttpServletRequest request, HttpServletResponse response) {

  26. log.debug("weixin get...");

  27. // 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。

  28. String signature = request.getParameter("signature");

  29. // 时间戳

  30. String timestamp = request.getParameter("timestamp");

  31. // 随机数

  32. String nonce = request.getParameter("nonce");

  33. // 随机字符串

  34. String echostr = request.getParameter("echostr");

  35.  
  36. // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败

  37. PrintWriter out = null;

  38. try {

  39. out = response.getWriter();

  40. if (SignUtil.checkSignature(signature, timestamp, nonce)) {

  41. log.debug("weixin get success....");

  42. out.print(echostr);

  43. }

  44. } catch (IOException e) {

  45. e.printStackTrace();

  46. } finally {

  47. if (out != null)

  48. out.close();

  49. }

  50. }

  51. }

之后重新部署一版最新的程序

访问微信测试号登录页面,通过打开自己手机的微信,扫一扫登录
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
图片描述
进入到测试号页面后,分别看到如下信息
【测试号信息】
appID:开发者ID,是公众号开发识别码,配合开发者密码可以调用微信公众号接口,如获取微信昵称等
appsecret:开发者密码,是检验公众号开发者身份的密码,具有极高的安全性。切记不要把密码交给第三方开发者或者编写到代码里
图片描述
【接口配置信息】
URL: 是开发者用来接收微信消息和事件的接口URL
Token:由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
图片描述
【JS接口安全域名】
域名:想调用jssdk(如想要通过微信公众号js接口获取地图等工具)必须得填写此域名,在此域名的范围内才能调用jssdk工具,注意这里必须是域名,不是带有http之类的URL,这里直接填写o2o.yitiaojieinfo.com
图片描述
【测试号二维码】
里面包含了测试号二维码以及已经关注了的用户信息
图片描述
【体验接口权限表】
这里主要介绍【网页服务】里面的【网页帐号】
网页帐号主要用来设置OAuth2.0里面的网页授权域名,用户在网页授权页同意授权给公众号后,微信会将授权数据传给一个回调页面,回调页面需在此域名下,以确保安全可靠。沙盒号回调地址支持域名和ip,正式公众号回调地址只支持域名。这里直接设置为o2o.yitiaojieinfo.com
图片描述
图片描述
有不清楚的地方可以直接参考微信官方文档
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319
接下来需要编写自己的程序以获取关注此公众号的用户信息
需要编写5个类 WechatLoginController.java,UserAccessToken.java,WechatUser.java,WechatUtil.java以及MyX509TrustManager.java
【WechatLoginController】主要用来获取已关注此微信号的用户信息并做相应处理

 
  1. package com.imooc.o2o.web.wechat;

  2.  
  3. import java.io.IOException;

  4.  
  5. import javax.servlet.http.HttpServletRequest;

  6. import javax.servlet.http.HttpServletResponse;

  7.  
  8. import org.slf4j.Logger;

  9. import org.slf4j.LoggerFactory;

  10. import org.springframework.stereotype.Controller;

  11. import org.springframework.web.bind.annotation.RequestMapping;

  12. import org.springframework.web.bind.annotation.RequestMethod;

  13.  
  14. import com.imooc.o2o.dto.UserAccessToken;

  15. import com.imooc.o2o.dto.WechatUser;

  16. import com.imooc.o2o.util.wechat.WeiXinUserUtil;

  17.  
  18. @Controller

  19. @RequestMapping("wechatlogin")

  20. /**

  21. * 获取关注公众号之后的微信用户信息的接口,如果在微信浏览器里访问

  22. * https://open.weixin.qq.com/connect/oauth2/authorize?appid=您的appId&redirect_uri=http://o2o.yitiaojieinfo.com/o2o/wechatlogin/logincheck&role_type=1&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect

  23. * 则这里将会获取到code,之后再可以通过code获取到access_token 进而获取到用户信息

  24. *

  25. * @author xiangze

  26. *

  27. */

  28. public class WechatLoginController {

  29.  
  30. private static Logger log = LoggerFactory.getLogger(WechatLoginController.class);

  31.  
  32. @RequestMapping(value = "/logincheck", method = { RequestMethod.GET })

  33. public String doGet(HttpServletRequest request, HttpServletResponse response) {

  34. log.debug("weixin login get...");

  35. // 获取微信公众号传输过来的code,通过code可获取access_token,进而获取用户信息

  36. String code = request.getParameter("code");

  37. // 这个state可以用来传我们自定义的信息,方便程序调用,这里也可以不用

  38. // String roleType = request.getParameter("state");

  39. log.debug("weixin login code:" + code);

  40. WechatUser user = null;

  41. String openId = null;

  42. if (null != code) {

  43. UserAccessToken token;

  44. try {

  45. // 通过code获取access_token

  46. token = WeiXinUserUtil.getUserAccessToken(code);

  47. log.debug("weixin login token:" + token.toString());

  48. // 通过token获取accessToken

  49. String accessToken = token.getAccessToken();

  50. // 通过token获取openId

  51. openId = token.getOpenId();

  52. // 通过access_token和openId获取用户昵称等信息

  53. user = WeiXinUserUtil.getUserInfo(accessToken, openId);

  54. log.debug("weixin login user:" + user.toString());

  55. request.getSession().setAttribute("openId", openId);

  56. } catch (IOException e) {

  57. log.error("error in getUserAccessToken or getUserInfo or findByOpenId: " + e.toString());

  58. e.printStackTrace();

  59. }

  60. }

  61. // ======todo begin======

  62. // 前面咱们获取到openId后,可以通过它去数据库判断该微信帐号是否在我们网站里有对应的帐号了,

  63. // 没有的话这里可以自动创建上,直接实现微信与咱们网站的无缝对接。

  64. // ======todo end======

  65. if (user != null) {

  66. // 获取到微信验证的信息后返回到指定的路由(需要自己设定)

  67. return "frontend/index";

  68. } else {

  69. return null;

  70. }

  71. }

  72. }

【UserAccessToken】用户AccessToken实体类,用来接收accesstoken以及openid等信息

 
  1. package com.imooc.o2o.dto;

  2.  
  3. import com.fasterxml.jackson.annotation.JsonProperty;

  4.  
  5. /**

  6. * 用户授权token

  7. *

  8. * @author xiangze

  9. *

  10. */

  11. public class UserAccessToken {

  12.  
  13. // 获取到的凭证

  14. @JsonProperty("access_token")

  15. private String accessToken;

  16. // 凭证有效时间,单位:秒

  17. @JsonProperty("expires_in")

  18. private String expiresIn;

  19. // 表示更新令牌,用来获取下一次的访问令牌,这里没太大用处

  20. @JsonProperty("refresh_token")

  21. private String refreshToken;

  22. // 该用户在此公众号下的身份标识,对于此微信号具有唯一性

  23. @JsonProperty("openid")

  24. private String openId;

  25. // 表示权限范围,这里可省略

  26. @JsonProperty("scope")

  27. private String scope;

  28.  
  29. public String getAccessToken() {

  30. return accessToken;

  31. }

  32.  
  33. public void setAccessToken(String accessToken) {

  34. this.accessToken = accessToken;

  35. }

  36.  
  37. public String getExpiresIn() {

  38. return expiresIn;

  39. }

  40.  
  41. public void setExpiresIn(String expiresIn) {

  42. this.expiresIn = expiresIn;

  43. }

  44.  
  45. public String getRefreshToken() {

  46. return refreshToken;

  47. }

  48.  
  49. public void setRefreshToken(String refreshToken) {

  50. this.refreshToken = refreshToken;

  51. }

  52.  
  53. public String getOpenId() {

  54. return openId;

  55. }

  56.  
  57. public void setOpenId(String openId) {

  58. this.openId = openId;

  59. }

  60.  
  61. public String getScope() {

  62. return scope;

  63. }

  64.  
  65. public void setScope(String scope) {

  66. this.scope = scope;

  67. }

  68.  
  69. @Override

  70. public String toString() {

  71. return "accessToken:" + this.getAccessToken() + ",openId:" + this.getOpenId();

  72. }

  73.  
  74. }

【WechatUser】微信用户实体类,用来接收昵称 openid等用户信息

 
  1. package com.imooc.o2o.dto;

  2.  
  3. import java.io.Serializable;

  4.  
  5. import com.fasterxml.jackson.annotation.JsonProperty;

  6.  
  7. /**

  8. * 微信用户实体类

  9. *

  10. * @author xiangze

  11. *

  12. */

  13. public class WechatUser implements Serializable {

  14.  
  15. /**

  16. *

  17. */

  18. private static final long serialVersionUID = -4684067645282292327L;

  19.  
  20. // openId,标识该公众号下面的该用户的唯一Id

  21. @JsonProperty("openid")

  22. private String openId;

  23. // 用户昵称

  24. @JsonProperty("nickname")

  25. private String nickName;

  26. // 性别

  27. @JsonProperty("sex")

  28. private int sex;

  29. // 省份

  30. @JsonProperty("province")

  31. private String province;

  32. // 城市

  33. @JsonProperty("city")

  34. private String city;

  35. // 区

  36. @JsonProperty("country")

  37. private String country;

  38. // 头像图片地址

  39. @JsonProperty("headimgurl")

  40. private String headimgurl;

  41. // 语言

  42. @JsonProperty("language")

  43. private String language;

  44. // 用户权限,这里没什么作用

  45. @JsonProperty("privilege")

  46. private String[] privilege;

  47.  
  48. public String getOpenId() {

  49. return openId;

  50. }

  51.  
  52. public void setOpenId(String openId) {

  53. this.openId = openId;

  54. }

  55.  
  56. public String getNickName() {

  57. return nickName;

  58. }

  59.  
  60. public void setNickName(String nickName) {

  61. this.nickName = nickName;

  62. }

  63.  
  64. public int getSex() {

  65. return sex;

  66. }

  67.  
  68. public void setSex(int sex) {

  69. this.sex = sex;

  70. }

  71.  
  72. public String getProvince() {

  73. return province;

  74. }

  75.  
  76. public void setProvince(String province) {

  77. this.province = province;

  78. }

  79.  
  80. public String getCity() {

  81. return city;

  82. }

  83.  
  84. public void setCity(String city) {

  85. this.city = city;

  86. }

  87.  
  88. public String getCountry() {

  89. return country;

  90. }

  91.  
  92. public void setCountry(String country) {

  93. this.country = country;

  94. }

  95.  
  96. public String getHeadimgurl() {

  97. return headimgurl;

  98. }

  99.  
  100. public void setHeadimgurl(String headimgurl) {

  101. this.headimgurl = headimgurl;

  102. }

  103.  
  104. public String getLanguage() {

  105. return language;

  106. }

  107.  
  108. public void setLanguage(String language) {

  109. this.language = language;

  110. }

  111.  
  112. public String[] getPrivilege() {

  113. return privilege;

  114. }

  115.  
  116. public void setPrivilege(String[] privilege) {

  117. this.privilege = privilege;

  118. }

  119.  
  120. @Override

  121. public String toString() {

  122. return "openId:" + this.getOpenId() + ",nikename:" + this.getNickName();

  123. }

  124. }

【WechatUtil】主要用来提交https请求给微信获取用户信息

 
  1. package com.imooc.o2o.util.wechat;

  2.  
  3. import java.io.BufferedReader;

  4. import java.io.IOException;

  5. import java.io.InputStream;

  6. import java.io.InputStreamReader;

  7. import java.io.OutputStream;

  8. import java.net.ConnectException;

  9. import java.net.URL;

  10.  
  11. import javax.net.ssl.HttpsURLConnection;

  12. import javax.net.ssl.SSLContext;

  13. import javax.net.ssl.SSLSocketFactory;

  14. import javax.net.ssl.TrustManager;

  15.  
  16. import org.slf4j.Logger;

  17. import org.slf4j.LoggerFactory;

  18.  
  19. import com.fasterxml.jackson.core.JsonParseException;

  20. import com.fasterxml.jackson.databind.JsonMappingException;

  21. import com.fasterxml.jackson.databind.ObjectMapper;

  22. import com.imooc.o2o.dto.UserAccessToken;

  23. import com.imooc.o2o.dto.WechatUser;

  24.  
  25. /**

  26. * 微信工具类

  27. *

  28. * @author xiangze

  29. *

  30. */

  31. public class WechatUtil {

  32.  
  33. private static Logger log = LoggerFactory.getLogger(WechatUtil.class);

  34.  
  35. /**

  36. * 获取UserAccessToken实体类

  37. *

  38. * @param code

  39. * @return

  40. * @throws IOException

  41. */

  42. public static UserAccessToken getUserAccessToken(String code) throws IOException {

  43. // 测试号信息里的appId

  44. String appId = "您的appId";

  45. log.debug("appId:" + appId);

  46. // 测试号信息里的appsecret

  47. String appsecret = "您的appsecret";

  48. log.debug("secret:" + appsecret);

  49. // 根据传入的code,拼接出访问微信定义好的接口的URL

  50. String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appsecret

  51. + "&code=" + code + "&grant_type=authorization_code";

  52. // 向相应URL发送请求获取token json字符串

  53. String tokenStr = httpsRequest(url, "GET", null);

  54. log.debug("userAccessToken:" + tokenStr);

  55. UserAccessToken token = new UserAccessToken();

  56. ObjectMapper objectMapper = new ObjectMapper();

  57. try {

  58. // 将json字符串转换成相应对象

  59. token = objectMapper.readValue(tokenStr, UserAccessToken.class);

  60. } catch (JsonParseException e) {

  61. log.error("获取用户accessToken失败: " + e.getMessage());

  62. e.printStackTrace();

  63. } catch (JsonMappingException e) {

  64. log.error("获取用户accessToken失败: " + e.getMessage());

  65. e.printStackTrace();

  66. } catch (IOException e) {

  67. log.error("获取用户accessToken失败: " + e.getMessage());

  68. e.printStackTrace();

  69. }

  70. if (token == null) {

  71. log.error("获取用户accessToken失败。");

  72. return null;

  73. }

  74. return token;

  75. }

  76.  
  77. /**

  78. * 获取WechatUser实体类

  79. *

  80. * @param accessToken

  81. * @param openId

  82. * @return

  83. */

  84. public static WechatUser getUserInfo(String accessToken, String openId) {

  85. // 根据传入的accessToken以及openId拼接出访问微信定义的端口并获取用户信息的URL

  86. String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId

  87. + "&lang=zh_CN";

  88. // 访问该URL获取用户信息json 字符串

  89. String userStr = httpsRequest(url, "GET", null);

  90. log.debug("user info :" + userStr);

  91. WechatUser user = new WechatUser();

  92. ObjectMapper objectMapper = new ObjectMapper();

  93. try {

  94. // 将json字符串转换成相应对象

  95. user = objectMapper.readValue(userStr, WechatUser.class);

  96. } catch (JsonParseException e) {

  97. log.error("获取用户信息失败: " + e.getMessage());

  98. e.printStackTrace();

  99. } catch (JsonMappingException e) {

  100. log.error("获取用户信息失败: " + e.getMessage());

  101. e.printStackTrace();

  102. } catch (IOException e) {

  103. log.error("获取用户信息失败: " + e.getMessage());

  104. e.printStackTrace();

  105. }

  106. if (user == null) {

  107. log.error("获取用户信息失败。");

  108. return null;

  109. }

  110. return user;

  111. }

  112.  
  113. /**

  114. * 发起https请求并获取结果

  115. *

  116. * @param requestUrl

  117. * 请求地址

  118. * @param requestMethod

  119. * 请求方式(GET、POST)

  120. * @param outputStr

  121. * 提交的数据

  122. * @return json字符串

  123. */

  124. public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {

  125. StringBuffer buffer = new StringBuffer();

  126. try {

  127. // 创建SSLContext对象,并使用我们指定的信任管理器初始化

  128. TrustManager[] tm = { new MyX509TrustManager() };

  129. SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");

  130. sslContext.init(null, tm, new java.security.SecureRandom());

  131. // 从上述SSLContext对象中得到SSLSocketFactory对象

  132. SSLSocketFactory ssf = sslContext.getSocketFactory();

  133.  
  134. URL url = new URL(requestUrl);

  135. HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();

  136. httpUrlConn.setSSLSocketFactory(ssf);

  137.  
  138. httpUrlConn.setDoOutput(true);

  139. httpUrlConn.setDoInput(true);

  140. httpUrlConn.setUseCaches(false);

  141. // 设置请求方式(GET/POST)

  142. httpUrlConn.setRequestMethod(requestMethod);

  143.  
  144. if ("GET".equalsIgnoreCase(requestMethod))

  145. httpUrlConn.connect();

  146.  
  147. // 当有数据需要提交时

  148. if (null != outputStr) {

  149. OutputStream outputStream = httpUrlConn.getOutputStream();

  150. // 注意编码格式,防止中文乱码

  151. outputStream.write(outputStr.getBytes("UTF-8"));

  152. outputStream.close();

  153. }

  154.  
  155. // 将返回的输入流转换成字符串

  156. InputStream inputStream = httpUrlConn.getInputStream();

  157. InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");

  158. BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

  159.  
  160. String str = null;

  161. while ((str = bufferedReader.readLine()) != null) {

  162. buffer.append(str);

  163. }

  164. bufferedReader.close();

  165. inputStreamReader.close();

  166. // 释放资源

  167. inputStream.close();

  168. inputStream = null;

  169. httpUrlConn.disconnect();

  170. log.debug("https buffer:" + buffer.toString());

  171. } catch (ConnectException ce) {

  172. log.error("Weixin server connection timed out.");

  173. } catch (Exception e) {

  174. log.error("https request error:{}", e);

  175. }

  176. return buffer.toString();

  177. }

  178. }

【MyX509TrustManager】主要继承X509TrustManager做https证书信任管理器

 
  1. package com.imooc.o2o.util.wechat;

  2.  
  3. import java.security.cert.CertificateException;

  4. import java.security.cert.X509Certificate;

  5.  
  6. import javax.net.ssl.X509TrustManager;

  7.  
  8. /**

  9. * 证书信任管理器(用于https请求)

  10. *

  11. * @author xiangze

  12. *

  13. */

  14. public class MyX509TrustManager implements X509TrustManager {

  15.  
  16. public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

  17. }

  18.  
  19. public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

  20. }

  21.  
  22. public X509Certificate[] getAcceptedIssuers() {

  23. return null;

  24. }

  25. }

之后重新打包一个新的war包并发布到服务器tomcat webapps目录下
发布成功后,关注你自己的测试号(即扫描测试号的那个二维码),然后在手机微信里面或者微信开发者工具里访问相应链接:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=您的appid&redirect_uri=http://o2o.yitiaojieinfo.com/o2o/wechatlogin/logincheck&role_type=1&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect
图片描述
之后查看日志信息,便能发现确实能够获取到用户的信息了
图片描述
至此咱们已经从无到有完成了阿里云部署Java网站和微信公众号的开发,文章虽长,但是干货多多,都是傻瓜式的配置,希望大家喜欢。
注意事项:

  1. 由于tomcat咱们没有调优,启动较慢,建议每次重启等待几分钟再去访问,否则会假死,需要kill掉再重启
  2. 经过认证的微信服务号跟测试号其实是一样的,大家可以按照上述去配置


作者: xiangzepro 
链接:http://www.imooc.com/article/20584
来源:慕课网
本文原创发布于慕课网 ,转载请注明出处,谢谢合作!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_794012.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探究 Stack Overflow 网站的热点问题排名算法

引入&#xff1a;几乎所有搞开发的人都对Stack Overflow不陌生&#xff0c;它是一个专门的Q&A类型的网站http://dbanotes.net/startup/stack_overflow_success.html &#xff08;类似这种网站的例子还有很多&#xff0c;比如新浪问问&#xff0c;百度搜搜等&#xff09;你如…

为什么别人做小说网站轻易IP上万,自己做甚至不收录

2019独角兽企业重金招聘Python工程师标准>>> 最近与博客联盟(blogunion.org)的老曾好友聊了下关于小说网站&#xff0c;听说小说网站轻易IP上万&#xff0c;而自己做甚至不收录(当然不是老曾本人的)&#xff0c;感到十分困惑。于是深度了解下&#xff0c;后来发现&a…

公司网站,邮箱,文件服务器搭建实战

项目案例&#xff1a;Tarena公司要求实现公司网站&#xff0c;邮箱&#xff0c;文件服务器的运营&#xff0c;并保证安全可靠&#xff0c;方便管理。项目分析&#xff1a;为实现要求我们首先要购买域名tarena.com。然后配置一台DNS和WEB服务器&#xff0c;因为这是公司的主要业…

网站安全狗Apache 3.5版升级 新增网站后台防护功能

2019独角兽企业重金招聘Python工程师标准>>> 网站安全狗是一款集网站内容安全防护、网站资源保护及网站流量保护功能为一体的服务器网站安全防护软件。功能涵盖了网马/木马扫描、防SQL注入、防盗链、防CC攻击、网站后台防护、一句话木马防护、网站流量实时监控、网站…

【python 3.6】从网站抓图并存放到本地路径

#!/usr/bin/python # -*- coding: UTF-8 -*- _author_ BH8ANKimport urllib.request import re import os import time#os.rmdir("D:/images")#1&#xff0c;打开页面&#xff0c;读取图片张数,抓html wangzhi "https://www.zhihu.com/question/43551423"…

如何把不同尺寸ico格式图标_网站ico 图标不会做?用这个小工具轻松搞定

给自己的网站加上一个小图标&#xff0c;显示既专业又美观。网站左上角显示的小图标一般是ico格式的图片&#xff0c;然后在HTML里使用代码去设置ico小图片为该网站的小标。设计软件设计出来的图标一般是png、jpg这等格式的&#xff0c;但ico图标不同于png、jpg这类常见的图片格…

seo日常工作表_谷歌SEO优化工具大全

在做谷歌SEO工作的时候&#xff0c;我们经常性会强调SEO是一个细节性很强的工作&#xff0c;因此&#xff0c;有的时候我们不能进行批量自动化的工作&#xff0c;比如&#xff1a;①外链自动群发②内容批量伪原创在某种情况下&#xff0c;我们认为这是一种相对情况&#xff0c;…

发布原型html文件_Axure教程:高效访问的原型托管网站(1)

由于Axure自带的服务器 Axshare部署在海外的&#xff0c;导致国内的小伙伴在访问上传的项目原型链接时很慢&#xff0c;有时甚至打不开。接下来&#xff0c;推荐给大家几个国内的原型托管网站。第一个&#xff1a;axhub1、平台链接&#xff1a;https://axhub.imaxhub是一个原型…

企业域名备案流程_个人和企业网站申请公安备案的流程总结

我们常给网站备案是在工信部备案&#xff0c;但现在又多一个备案是在公安的备案&#xff0c;以下耀忠根据近期给客户网站进行公安备案的相关步骤流程简单整理一下&#xff0c;希望对大家有所帮助。1、注册账号。打开全国互联网安全管理服务平台网&#xff1a;www.beian.gov.cn&…

4.Windows Server2012 R2里面部署 MVC 的网站

网站部署之~Windows Server | 本地部署:http://www.cnblogs.com/dunitian/p/4822808.html#iis 后期会在博客首发更新&#xff1a;http://dnt.dkill.net 添加角色 基本功能 默认即可 装一下iis 选4.5和iis核心 其他的下面继续选 安全肯定全要的&#xff0c;常见HTTP和应用程序开…

网站制作流程

提出需求&#xff0d;> 解决方案 &#xff0d;> 工作交流 &#xff0d;> 确立合同 &#xff0d;> 支付定金 &#xff0d;> 安排设计 &#xff0d;> 确认首页  &#xff0d;> 网站制作 &#xff0d;> 客户验收 &#xff0d;> 网站维护 &#x…

服务器上无法重命名文件夹,linux如何重命名文件和文件夹_网站服务器运行维护...

win10显示网络电缆被拔出怎么办_网站服务器运行维护win10显示网络电缆被拔出的解决方法是&#xff1a;1、打开【设备管理器】&#xff0c;展开【网络适配器】选项&#xff1b;2、打开网卡属性窗口&#xff0c;切换到【电源管理】选项&#xff0c;并取消勾选【允许计算机关闭此设…

网站用户头像剪裁上传完整案例

做为网站前段开发人员来说&#xff0c;用户头像剪裁和上传是一个很常用的功能&#xff0c;一般这个功能涉及到图片的放大&#xff0c;缩小&#xff0c;移动&#xff0c;旋转&#xff0c;和剪裁。下面我们来做一个完整的demo&#xff0c;剪裁后的图片以base64的形式返回&#xf…

Ci分开配置网站前台后台的方法

CodeIgniter 是一个简单快速的PHP MVC框架。EllisLab 的工作人员发布了 CodeIgniter。许多企业尝试体验过所有 PHP MVC 框架之后&#xff0c;CodeIgniter 都成为赢家&#xff0c;主要是由于它为组织提供了足够的自由支持&#xff0c;允许开发人员更迅速地工作。 CI 2.0 多目录&…

使用Selenium爬取网站表格类数据

本文转载自一下网站:Python爬虫(5)&#xff1a;Selenium 爬取东方财富网股票财务报表 https://www.makcyun.top/web_scraping_withpython5.html 需要学习的地方: 1.Selenium的安装,配置 2.Selenium的初步使用(自动翻页) 利用Selenium爬取东方财富网各上市公司历年的财务报表数据…

H5竞价单页网站源码带订单系统

竞价单页一直都是比较火爆的一类源码&#xff0c;很多做产品竞价的朋友几乎都会找这样的源码&#xff0c;因为做搜索引擎的竞价推广&#xff0c;如果人工一一对接的话会很累&#xff0c;而且可能下单量要少得多&#xff0c;但是使用竞价单页就不一样了&#xff0c;很多消费者从…

网站本地优化方法与技巧

网站优化是一个比较复杂的过程&#xff0c;尤其是线上的一些细节优化&#xff0c;有很多学问&#xff0c;但是我们最基础的还是要做好网站的本地优化&#xff0c;今天友软科技就和大家一起分享学习一下网站本地优化的方法与技巧&#xff0c;大家有什么好的想法或者观点&#xf…

如何傻瓜式的创建网站地图

1 登陆: http://www.xml-sitemaps.com/ 网站,该网站可以以XML,ROR,TEXT,HTML四种格式创建地图. 2 填写一些参数,网址到下一步。 3 制作完成&#xff0c;下载所需格式&#xff0c;并保存到网站目录。 4 确认是否能正确浏览该地图。

linux 建站命令,关于linux基础命令的详解

关于linux基础命令的详解发布时间&#xff1a;2020-08-26 11:56:02来源&#xff1a;亿速云阅读&#xff1a;84作者&#xff1a;小新小编给大家分享一下关于linux基础命令的详解&#xff0c;希望大家阅读完这篇文章后大所收获&#xff0c;下面让我们一起去探讨吧&#xff01;lin…

电商网站秒杀倒计时实现

电商网站秒杀倒计时实现 CSS代码实现 <style> #container{ width: 190px; height: 275px; background: #e83632; color: #fff; position: relative; } #container .sk_title{ position: absolute; left:0; top: 42px; width: 100%; text-align: center; font-size: 34px;…