1.项目名:微信公众号后台管理系统
2.开发工具:eclipse+tomcat7.0
3.所用技术:jdbc+struts2
4.实现的主要功能:消息自动回复,自定义图文素材和文本素材,自定义公众号菜单,微信群管理功能。
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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<!-- 404 -->
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<!-- 欢迎页面 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置struts2核心过滤器 -->
<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>/*</url-pattern>
</filter-mapping>
<!-- 配置session超时时间 -->
<session-config>
<session-timeout>33</session-timeout>
</session-config>
<!-- 配置全局JSP页面参数 -->
<jsp-config>
<jsp-property-group>
<!-- 配置所有的JSP页面 -->
<url-pattern>*.jsp</url-pattern>
<!-- el表达式有效 -->
<el-ignored>false</el-ignored>
<!-- JSP脚本无效 -->
<scripting-invalid>true</scripting-invalid>
<!-- 所有JSP页面导入taglib.jsp -->
<include-prelude>/WEB-INF/jsp/taglib.jsp</include-prelude>
</jsp-property-group>
</jsp-config>
</web-app>
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 以下DTD从struts2-core-2.3.jar文件中可找到 -->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 是否支持动态方法调用,默认true -->
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<!-- 是否启用开发模式,默认false;开启时应用出错会显示更多详细信息 -->
<constant name="struts.devMode" value="false"/>
<!-- 指定需要struts2处理的请求后缀,默认为action -->
<constant name="struts.action.extention" value="jun"/>
<!-- 指定web应用的默认编码集 -->
<constant name="struts.i18n.encoding" value="utf-8"/>
<package name="dawen" namespace="/" extends="struts-default">
<!-- 配置拦截器 -->
<interceptors>
<!-- 拦截器名和拦截器对应的实现类 -->
<interceptor name="loginInterceptor" class="org.dawen.action.interceptor.LoginInterceptor"/>
<!-- 配置拦截器栈loginStack -->
<interceptor-stack name="loginStack">
<!-- 引入struts2框架默认的拦截器 defaultStack -->
<interceptor-ref name="defaultStack"/>
<!-- 引入自定义登录拦截器loginInterceptor -->
<interceptor-ref name="loginInterceptor"/>
</interceptor-stack>
</interceptors>
<!-- 把loginStack定义为默认的拦截器 -->
<default-interceptor-ref name="loginStack"/>
<!-- 全局结果集,name值对应拦截器实现类返回的字符串值,根据字符串跳转到对应视图 -->
<global-results>
<result name="error">/error.jsp</result>
<result name="user_login">/WEB-INF/jsp/admin/login.jsp</result>
</global-results>
<!-- 全局异常映射 -->
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.Exception"/>
</global-exception-mappings>
<!-- 异步登录loginAjax及实现类 --><!-- 注意:每个action执行前都会执行默认拦截器 -->
<action name="loginAjax" class="org.dawen.action.admin.LoginAjaxAction">
<!-- 引入拦截器栈defaultStack拦截loginAjaxAction -->
<interceptor-ref name="defaultStack"/>
</action>
<action name="*">
<!-- 通配符{1}指第一个*的参数;如果为{2}则指第二个*参数;result的name默认值是success-->
<result>/WEB-INF/jsp/admin/{1}.jsp</result>
</action>
</package>
<include file = "org/dawen/action/admin/keyword/struts_keyword.xml"/>
<include file = "org/dawen/action/admin/menu/struts_menu.xml"/>
<include file = "org/dawen/action/admin/group/struts_group.xml"/>
<include file = "org/dawen/action/admin/setting/struts_setting.xml"/>
</struts>
c3p0.properties
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/dawen
c3p0.user=root
c3p0.password=a123
c3p0.initialPoolSize=2
c3p0.maxIdleTime=30
c3p0.maxPoolSize=100
c3p0.minPoolSize=10
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>微信公众号管理后台登录</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/style/reset.css">
<link rel="stylesheet" href="${pageContext.request.contextPath}/style/login.css">
<script src="${pageContext.request.contextPath}/js/lib/jquery-1.9.1.min.js"></script>
<script src="${pageContext.request.contextPath}/js/lib/AntMove.js"></script>
<script>
$(function(){
$("#btn").click(function(){
var $_login = $("#loginForm").get(0);
var $_tip = $("#tip").get(0);
/*
*/
var userName = $(".userName");
var password = $(".password");
var tip = "";
if( $.trim( userName.val() ) == "" ){
tip = "帐号不能为空";
userName.focus();
}else if( !/^\w{5,20}$/.test( userName.val() ) ){
tip = "帐号长度必须5-20之间";
userName.focus();
}else if($.trim( password.val() ) == ""){
tip = "密码不能为空";
password.focus();
}
if(tip != ""){ //如果tip有值提示错误信息
alert(tip);
}else{ //发送ajax请求
$.ajax({
url:"${pageContext.request.contextPath}/loginAjax.action",//ajax的请求地址
type:"post",//请求方式
dataType:"json",//返回数据为json
data:$("#form").serialize(), //$("#loginForm").serialize() 序列化
async:true, //是否异步 true为异步,false为同步
success:function(data){ //异步成功回调
console.log(data);
if(data.success == "1"){
alert(data.tip);
//Dialog.alert("登录成功~~!");
window.location = "${pageContext.request.contextPath}/index.action";
}else if(data.success == "0"){
antMove($_login,{top:60},1000,"elasticOut",function(){
$(".tip").css("display","block");
antMove($_tip,{top:0},1000,"elasticOut");});
}
},
error:function(tip){ //ajax失败回调
alert("ajax发送失败:"+tip);
}
});
}
});
});
</script>
</head>
<body>
<div id="login">
<!--
<div class="logo">
<a href=""><img src="${pageContext.request.contextPath}/images/logo.png"></a>
</div>
-->
<div class="tipParent">
<div id="tip" class="tip">
<strong>错误 : </strong>
<span>用户名无效</span>
<a href="">忘记密码?</a>
</div>
</div>
<div class="formParent">
<form action= "?" id="form" method="post">
<div id="loginForm" class="loginForm">
<div class="loginName">
<label>用户名</label>
<input type="text" value="admin" class="userName" name="userName">
</div>
<div class="loginPassword">
<label>密码</label>
<input type="password" class="password" name="password">
</div>
<div class="loginBtn">
<input type="checkbox">
<span>记住我的登录信息</span>
<input type="button" value="" class="btn" id="btn">
</div>
</div>
</form>
</div>
</div>
</body>
</html>
LoginAjaxAction.java
package org.dawen.action.admin;
import org.dawen.action.base.AbstractAjaxAction;
/**
* 异步登录Ajax,接收用户名和密码参数
* @author jun
* @email 624664181@qq.com
* @date 2014 下午8:47:07
*/
public class LoginAjaxAction extends AbstractAjaxAction {
private static final long serialVersionUID = -1638526442566751841L;
protected String userName;
protected String password;
@Override
public String setJson() throws Exception {
String json = this.service.login(userName,password);
return json;
}
/** getter and setter method */
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
LoginInterceptor.java
package org.dawen.action.interceptor;
import org.dawen.commons.WebConstant;
import org.dawen.dto.User;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/**
* 自定义登录拦截器类继承struts2框架提供的拦截器类AbstractInterceptor,AbstractInterceptor类实现了Interceptor接口
* 接口Interceptor的默认方法有:init()、intercept(ActionInvocation arg0)、destroy()
* AbstractInterceptor有Interceptor的三个方法,不需要加载特殊资源时可以不用实现init()和destroy()方法,只需实现intercept(ActionInvocation invocation)
* @author jun
* @email 624664181@qq.com
* @date 2014 下午8:28:59
*/
public class LoginInterceptor extends AbstractInterceptor{
private static final long serialVersionUID = 6706022458603193697L;
/**
* 实现用户拦截的处理方法。类似action的execute()方法,返回String类型的结果来对应配置文件中的视图名。
* 如果该方法直接返回一个字符串,则框架跳转到该字符串对应的逻辑视图
*/
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("LoginInterceptor...interceptor.....");
//从session获取当前用户User对象
User user = (User) invocation.getInvocationContext().getSession().get(WebConstant.SESSION_USER);
if(user != null){
//调用被拦截的action
return invocation.invoke();
}
//不成功则直接返回一个字符串
return WebConstant.USER_LOGIN;
}
}
DBConnection.java
package org.dawen.dao.base;
import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
* 数据库连接类
* @author jun
* @email 624664181@qq.com
* @date 2014 下午4:52:30
*/
public class DBConnection {
//定义c3p0连接池
private static ComboPooledDataSource db = new ComboPooledDataSource();
/**
* 获取数据源连接
* @return
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{
return db.getConnection();
}
/**
* 关闭数据源
* @param connection
* @throws SQLException
*/
public static void close(Connection connection) throws SQLException{
if(connection != null){
connection.close();
}
}
}