使用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/

系统实现的功能是:

  1. 实现后台学院监考安排。
  2. 用户分为普通教师用户,管理员用户,超级管理员,三级权限。
  3. 将信息实时推送到安排监考的教师的微信手机端。
  4. 教师可以在微信手机端实时查看自己的相关监考信息。
  5. 扫描微信二维码后,需要管理员审核通过后才可以使用相关功能。

介绍一下整个架构
简单开发

微信用户通过关注微信公众号,可以实现跟系统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.微信手机端预览
这里写图片描述

0 0
原创粉丝点击