使用structs2开源框架+tomcat开源服务+mysql开源数据库+微信开放接口构建考务信息推送平台
来源:互联网 发布:下载办公软件office 编辑:程序博客网 时间:2024/05/12 21:25
大二学生党一枚,这两个月一直在写一个用structs2框架实现微信二次开发的web程序,前几天将这个程序写完之后,在此沉淀一下。有不准确的地方希望大家指出。
在介绍之前先发送传送门:
由于所有的学习资源来自于google,所以就把干货也链过来了,希望以下各位博主支持。
gitlab代码传送http://mukever.online/root/kaowu
javaweb学习记录http://www.cnblogs.com/xdp-gacl/p/3760336.html
structs2拦截器http://blog.csdn.net/kiss_vicente/article/details/7597700
柳峰的微信开发教程http://blog.csdn.net/lyq8479/article/details/8937622
微信开发文档http://mp.weixin.qq.com/wiki/home/
git使用(多人协作)http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/
系统实现的功能是:
- 实现后台学院监考安排。
- 用户分为普通教师用户,管理员用户,超级管理员,三级权限。
- 将信息实时推送到安排监考的教师的微信手机端。
- 教师可以在微信手机端实时查看自己的相关监考信息。
- 扫描微信二维码后,需要管理员审核通过后才可以使用相关功能。
介绍一下整个架构
微信用户通过关注微信公众号,可以实现跟系统web通信,(学院管理员通过审核通过后才能使用相关的功能,否则会友情提示)。
微信开发步骤:
1.获得接口权限
在调用接口前,微信会通过get方式向你的服务器发送几个字符串参数,可以根据开发文档提示,得到这几个参数,
(如果加密之后还需要对数据解密得到)然后向微信服务器原样返回echostr参数内容,就能完成接口的调用。
2.保存accesstoken
每次调用接口时需要验证accesstoken是否有效,我的做法是将其存入数据库,下次需要时直接将其拿出,并比对时间戳,如果失效则重新获取accesstoken。
import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Date;import com.db.kaowu.sau.www.DBUnit;import com.pojo.wechat.kaowu.sau.www.AccessToken;/** * 保持token长期有效 * */public class GetExistAccessToken implements AppId { // 将AccessToken写进数据库 public static AccessToken getToken() { Connection connection = null; AccessToken token = new AccessToken(); connection = DBUnit.getConn(); String query_sql = "select * from db_accesstoken"; String delete_sql = "delete from db_accesstoken"; String insert_sql = ""; Date nowdate = new Date(); String dateformdb = ""; try { Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query_sql); // 当数据库中有数据时 if (resultSet.next()) { dateformdb = resultSet.getString(3); // 判断数据库中的数据是否有效 为了保存数据的有效性 将token的有效期缩短50秒 if (nowdate.getTime() - Long.parseLong(dateformdb) <= 7150000) { // System.out.println("数据库"); token.setToken(resultSet.getString(2)); token.setExpiresIn(7200); } else { // 数据库中的token失效了 // 调用接口获取access_token // System.out.println("获取"); AccessToken at = WeixinUtil.getAccessToken(appId, appSecret); // 删除原有token statement.executeUpdate(delete_sql); // 拼接inset_sql insert_sql = "insert into db_accesstoken (token, date) values('" + at.getToken() + "' ,'" + nowdate.getTime() + "')"; // 跟新token statement.executeUpdate(insert_sql); // 返回的token token = at; } } else { // 数据库没有数据时肯定直接从微信服务器获取 然后存入数据库 // 调用接口获取access_token AccessToken at = WeixinUtil.getAccessToken(appId, appSecret); // 拼接inset_sql insert_sql = "insert into db_accesstoken (token, date) values('" + at.getToken() + "' ,'" + nowdate.getTime() + "')"; // 跟新token // System.out.println("获取"); statement.executeUpdate(insert_sql); // 返回的token token = at; } // 关闭数据库连接 closeConnection(connection); } catch (SQLException e) { e.printStackTrace(); if (connection != null) { try { connection.close(); } catch (SQLException e1) { e1.printStackTrace(); } } } return token; } // 关闭数据库连接 public static void closeConnection(Connection connection) throws SQLException { connection.close(); }}这样能保证每次就不用从微信服务器那获取accesstoken,
3.微信接口的调用
在柳峰的博客中写的已经很详细了,他把所需要解析的各种信息基类都做了封装,我们完全可以利用嘛(没必要造重复的轮子)
4.微信开发中需要注意的问题:
1)接口权限问题,由于普通公众号没有高级权限,可以通过使用微信测试账号开发。
2)自己的服务器跟微信服务器是通过json数据传输。
3)在拦截请求时,需要放过处理微信服务器发送的请求。
4)手机端跟微信交互的时候 ,后台报错时,手机端的微信会提示无法响应。(正常情况下,服务器都会在5秒处理完请求)
5)不管是php还是java,开发的思路都是一样的。
后台开发步骤:
1.数据库设计:
2.前台页面与后台交互
前台页面通过js+jquery+ajax跟后台通过传递json数据做交互
3.action配置
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"><struts> <package name="struts" namespace="/" extends="struts-default,json-default"> <interceptors> <!-- 自定义拦截器 --> <interceptor name="permission" class="com.filter.kaowu.sau.www.SessionIterceptor" /> <!-- 配制默许的拦截器到拦截器栈 --> <interceptor-stack name="permissionStack"> <interceptor-ref name="defaultStack" /> <interceptor-ref name="permission" /> </interceptor-stack> </interceptors> <!-- 配置默认的拦截器 --> <default-interceptor-ref name="permissionStack" /> <!-- 设置全局的返回值 --> <global-results> <result name="nologin" type="redirect">/login.html</result> </global-results> <!-- 用户登录 --> <action name="Login" class="com.action.kaowu.sau.www.Login"> <result name = "success" type="json"> <param name="root">result</param> </result> <result name="input">/login.html</result> </action> <!-- 用户登录信息记录 --> <action name="Sign_*" class="com.action.kaowu.sau.www.Sign" method="{1}"> <result name="success">/idnex.html</result> <result type="json"> <param name="root">result</param> </result> </action> <!-- 微信服务器发送的信息请求处理action --> <action name="WeChat_*" class="com.action.kaowu.sau.www.WeChat" method="{1}"> </action> <!-- 教书监考用户注册 --> <action name="Register" class="com.action.kaowu.sau.www.Register"> <result name = "success" type="json"> <param name="root">result</param> </result> </action> <!-- 返回对应学院的所有用户信息 --> <action name="AuditUser" class="com.action.kaowu.sau.www.AuditUser"> <result name = "success" type="json"> <param name="root">result</param> </result> </action> <!-- 审核结果 --> <action name="Audit" class="com.action.kaowu.sau.www.Audit"> <result name = "success" type="json"> <param name="root">result</param> </result> </action> <!-- 返回用户相关信息 --> <action name="UserInfo" class="com.action.kaowu.sau.www.UserInfo"> <result name = "success" type="json"> <param name="root">result</param> </result> </action> <!-- 年级 --> <action name="Grade_*" class="com.action.kaowu.sau.www.Grade" method="{1}"> <!--添加信息 --> <result name="add" type="json"> <param name="root">result</param> </result> <!-- 删除信息 --> <result name="delete" type="json"> <param name="root">result</param> </result> <!-- 获取信息列表 --> <result name="getList" type="json"> <param name="root">result</param> </result> </action> <!-- 教室 --> <action name="ClassRoom_*" class="com.action.kaowu.sau.www.ClassRoom" method="{1}"> <!--添加信息 --> <result name="add" type="json"> <param name="root">result</param> </result> <!-- 删除教学楼教室信息 --> <result name="delete" type="json"> <param name="root">result</param> </result> <!-- 获取每个教学楼的教室信息 --> <result name="getList" type="json"> <param name="root">result</param> </result> <!-- 更新教学楼教室信息 --> <result name="update" type="json"> <param name="root">result</param> </result> </action> <!-- 第一步 获取对应时间段内没有被使用过的教室 --> <action name="NotUseRoom" class="com.action.kaowu.sau.www.NotUseRoom"> <result name="success" type="json"> <param name="root">result</param> </result> </action> <!-- 第二步 获取排考信息的信息 --> <action name="CreateNewTest" class="com.action.kaowu.sau.www.CreateNewTest"> <result name="success" type="json"> <param name="root">result</param> </result> </action> <!-- 获取再此期间没有被使用的教师--> <action name="NotUseTher" class="com.action.kaowu.sau.www.NotUseTher"> <result name="success" type="json"> <param name="root">result</param> </result> </action> <!-- 第三步 信息确定 --> <action name="AffirmTest" class="com.action.kaowu.sau.www.AffirmTest"> <result name="success" type="json"> <param name="root">result</param> </result> </action> <!-- 获取到所有的考试列表 --> <action name="TestList_*" class="com.action.kaowu.sau.www.TestList" method="{1}"> <!-- 得到从现在开始的所有的考试列表信息 --> <result name = "getlist" type="json"> <param name="root">result</param> </result> <result name = "delete" type="json"> <param name="root">status</param> </result> </action> <!-- 管理员 --> <action name="Admin_*" class="com.action.kaowu.sau.www.Admin" method="{1}"> <result name="updata" type="json"> <param name="root">result</param> </result> <result name="add" type="json"> <param name="root">result</param> </result> <result name="delete" type="json"> <param name="root">result</param> </result> <result name="list" type="json"> <param name="root">result</param> </result> </action> <!-- 用户更新密码 --> <action name="UserInfoupdata" class="com.action.kaowu.sau.www.UserInfoupdata"> <result name="updata" type="json"> <param name="root">result</param> </result> </action> <!-- 普通用户获取其考试列表 --> <action name="UserTest" class="com.action.kaowu.sau.www.UserTest"> <result name="success" type="json"> <param name="root">result</param> </result> </action> <!-- 退出操作 --> <action name="Quit" class="com.action.kaowu.sau.www.Quit"> <result name="success">/login.html </result> </action> </package>
4.jdbc连接数据库
1)将用户名和密码写在web.xml文件里面
package com.db.kaowu.sau.www;import java.sql.*;import javax.servlet.ServletContext;import org.apache.struts2.ServletActionContext;/* * * 数据库连接对象 */public class DBUnit { // 返回数据库连接对象 public static Connection getConn() { ServletContext context = ServletActionContext.getServletContext(); // 连接数据库 String url = context.getInitParameter("url"); String username = context.getInitParameter("username"); String psd = context.getInitParameter("password"); String jdbcName = context.getInitParameter("driver"); Connection conn = null; try { Class.forName(jdbcName); // System.out.println("驱动加载成功!"); } catch (Exception e) { } try { // 本地连接 // conn=DriverManager.getConnection(url); // 服务器连接 conn = DriverManager.getConnection(url, username, psd); } catch (SQLException ex) { } return conn; }}
5.web.xml文件配置
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>/login.html</welcome-file> </welcome-file-list> <!-- 配置session有效期 --> <session-config> <session-timeout>30</session-timeout> </session-config> <!-- wechat appid and appsecret --> <context-param> <param-name>appId</param-name> <param-value>wxd667c09a8220e9ea</param-value> </context-param> <context-param> <param-name>appSecret</param-name> <param-value>d3db5e22bfc9f761e4f70b3fe2bbd8b4</param-value> </context-param> <!--大小教室的分界 ==该值的教室为小教室--> <context-param> <param-name>demarcation</param-name> <param-value>100</param-value> </context-param> <!--配置以下代码--> <error-page> <error-code>404</error-code> <location>/404.html</location> </error-page> <!-- mysql --> <!-- 通过getServletContext().getInitParameter("XX")读取 --> <context-param> <param-name>driver</param-name> <param-value>com.mysql.jdbc.Driver</param-value> </context-param> <context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/kaowu</param-value> </context-param> <context-param> <param-name>username</param-name> <param-value>root</param-value> </context-param> <context-param> <param-name>password</param-name> <param-value></param-value> </context-param></web-app>
6.业务逻辑部分
1)审核
2.添加管理员
3.学院教务人员安排考试后台
4.新建考试完成后会向参加该门考试的教师托推送消息
package com.action.kaowu.sau.www;import java.util.ArrayList;import java.util.List;import javax.servlet.http.HttpSession;import org.apache.struts2.ServletActionContext;import com.CoreServer.wechat.kaowu.sau.www.HttpRequest;import com.bean.kaowu.sau.www.SpecificrecordBean;import com.bean.kaowu.sau.www.TestBean;import com.dao.kaowu.sau.www.OpenidDAO;import com.dao.kaowu.sau.www.RegisterDAO;import com.dao.kaowu.sau.www.SpecificrecordDAO;import com.dao.kaowu.sau.www.TestDAO;import com.opensymphony.xwork2.ActionSupport;import com.units.wechat.kaowu.sau.edu.www.GetExistAccessToken;import net.sf.json.JSONArray;import net.sf.json.JSONObject;public class AffirmTest extends ActionSupport { /** * */ private static final long serialVersionUID = 1L; private String testlist; private String testrecord; private String result; public String getTestlist() { return testlist; } public void setTestlist(String testlist) { this.testlist = testlist; } public String getTestrecord() { return testrecord; } public void setTestrecord(String testrecord) { this.testrecord = testrecord; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } public String execute() { synchronized (this) { // 获得到此次考试的时间+科目 HttpSession session = ServletActionContext.getRequest().getSession(); String Project = (String) session.getAttribute("Project"); String Starttime = (String) session.getAttribute("Starttime"); String Endtime = (String) session.getAttribute("Endtime"); String College = (String) session.getAttribute("College_num"); JSONObject jsonObject = JSONObject.fromObject(testlist); String testrecord = jsonObject.getString("testrecord"); String arr_temp = jsonObject.getString("testlist"); JSONArray array = JSONArray.fromObject(arr_temp); // 临时保存teacherid数据 List<String> ids = new ArrayList<>(); List<SpecificrecordBean> list = new ArrayList<>(); for (int i = 0; i < array.size(); i++) { JSONObject o = array.getJSONObject(i); SpecificrecordBean js = new SpecificrecordBean(); js.setClassid(o.getString("Classid")); js.setGradeid_1(o.getString("Gradeid_1")); js.setGradeid_2(o.getString("Gradeid_2")); js.setTeacherid_1(o.getString("Teacherid_1")); RegisterDAO.count(o.getString("Teacherid_1")); js.setTeacherid_2(o.getString("Teacherid_2")); RegisterDAO.count(o.getString("Teacherid_2")); js.setTestrecord(testrecord); list.add(js); // 向微信发送数据 ids.add(o.getString("Teacherid_1")); ids.add(o.getString("Teacherid_2")); } SpecificrecordBean[] temp = new SpecificrecordBean[array.size()]; for (int i = 0; i < temp.length; i++) { temp[i] = list.get(i); } TestBean testBean = new TestBean(); testBean.setProject(Project); testBean.setStarttime(Starttime); testBean.setEndtime(Endtime); testBean.setTestid(testrecord); testBean.setCollege(Integer.parseInt(College)); TestDAO.add(testBean); SpecificrecordDAO.add(temp); JSONObject jsonObject2 = new JSONObject(); jsonObject2.put("list", temp); // 前端的数据 result = jsonObject2.toString(); // 调用微信的高级接口推送消息 JSONArray Openid = new JSONArray(); // 构建openid数据库查找sql StringBuilder builder = new StringBuilder(); if (ids.size() > 0) { builder.append("where Therid in ("); // 构造查询字符串 int k = ids.size(); for (int i = 0; i < k; i++) { if (i == k - 1) { builder.append(" '" + ids.get(i) + "')"); } else { builder.append(" '" + ids.get(i) + "',"); } } } List<String> openids = OpenidDAO.getOpenid(builder.toString()); for (String s : openids) { Openid.add(s); } JSONObject ToAll = new JSONObject(); JSONObject content = new JSONObject(); content.put("content", "您近期有新的监考信息\n请点击考务助手\n我的监考查询"); ToAll.put("touser", Openid); ToAll.put("msgtype", "text"); ToAll.put("text", content); String url = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=ACCESS_TOKEN"; String access_token = GetExistAccessToken.getToken().getToken(); url = url.replace("ACCESS_TOKEN", access_token); HttpRequest.httpsRequest(url, "POST", ToAll.toString()); return SUCCESS; } }}
5.微信手机端预览
- 使用structs2开源框架+tomcat开源服务+mysql开源数据库+微信开放接口构建考务信息推送平台
- 微信公众号开放接口推送图文信息教程
- 微信开放平台接口java版
- .NET 微信开放平台接口
- .NET 微信开放平台接口
- 构建位置(地图)服务平台的相关开源资源
- tomcat+geoserver+postgis构建开源Webgis平台
- tomcat+geoserver+postgis构建开源Webgis平台(windows)
- Java:tomcat+geoserver+postgis构建开源Webgis平台(windows)
- AppCan 3.0:打造基于移动云服务的开源开放平台
- 微信开放平台- 使用 入门篇
- android微信开放平台使用
- 微信开放平台
- 如何开启微信开放平台的申请接口
- 微信开放平台的第三方平台微信开放平台帐号管理接口开发的两个错误
- 微信公众平台 开放平台 自定义回复和事件推送代码
- 微信公众平台 开放平台 自定义回复和事件推送代码
- 微信公众平台 开放平台 自定义回复和事件推送代码 .
- ACM程序设计选修课——1031: Hungar的得分问题(二)(杨辉三角+二进制转换)
- hdu1686 Oulipo--KMP
- PHP Switch 语句
- 能不能简单描述一下你在java web开发中需要用到多线程编程的场景?
- 用vlc搭建简单流媒体服务器(UDP和TCP方式)
- 使用structs2开源框架+tomcat开源服务+mysql开源数据库+微信开放接口构建考务信息推送平台
- 98. Validate Binary Search Tree LeetCode
- 安装 Apache 出现 <OS 10013> 以一种访问权限不允许的方式做了一个访问套接字的尝试
- 斐波那契数列的三种求法
- 养护眼睛
- 文章标题
- Java线程(七):Callable和Future
- JS二级联动
- qt编译运行错误—无法启动此应用程序,因为计算机中丢失XXX.dll