前言
这是一个比较简单的会议OA系统。该项目是基于动态的Web工程完成OA会议系统,利用自定义MVC框架,数据库采用的是Mysql数据库,开发工具为eclipse。
一、OA系统的功能需求流程
1)用户登录:后台采用MD5密码加密,前端采用ajax无刷新及json交互
2)左侧菜单:登录成功后跳转到会议OA后台页面并完成左侧菜单初始化及动态选项卡绑定操作
3)系统管理:用户管理模块增删改查实现
4)会议发布:新增OA会议信息
5)我的会议:完成我的会议信息展示、会议排座、送审、反馈详情及召开会议等功能
注:
1)必须是会议的主持人才能看到会议信息;
2)在送审之前必须先完成会议排座任务
6)我的审批:完成会议审批操作:审批通过和审批驳回
注:
1)必须是会议的审批人是当前用户才能看到;
2)审批通过后会议进行待开状态;审批驳回后会议将被更改为驳回状态
7)会议通知:展示我需要参与的会议信息,并实现参会与不参会功能
注:
1)只有会议的参与者和列席者才能在会议通知中查看到我所需要参与的会议信息
8)待开会议:展示会议状态为待开的所有会议信息
9)历史会议:展示会议状态为已结束的所有会议信息
10)所有会议:展示所有的会议信息
二、今天任务(搭建项目,实现登录)
数据库表结构
1.用户表 t_oa_user
2.角色权限表 t_oa_role_permission
3.权限表 t_oa_permission
4.会议信息表 t_oa_meeting_info
5.会议通知审批表 t_oa_meeting_audit
6. 会议通知反馈表 t_oa_meeting_feedback
导入jar包与util工具类
util工具类
jar包
及最后的项目架构
功能编写
页面使用layui,现在需要点击登录然后登录到主页面
话不多说先从登录开始
先配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>oapro</display-name>
<!-- 中文乱码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.zking.oapro.util.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 自定义MVC的核心控制器 -->
<servlet>
<servlet-name>actionServlet</servlet-name>
<servlet-class>com.zking.mvc.framework.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>actionServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!-- 设置默认进入的页面 -->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
连接MySQL数据库:DBHelper 注:需要在util包下创建一个config.properties
package com.zking.oapro.util;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* 提供了一组获得或关闭数据库对象的方法
*
*/
public class DBHelper {
private static String driver;
private static String url;
private static String user;
private static String password;
static {// 静态块执行一次,加载 驱动一次
try {
InputStream is = DBHelper.class
.getResourceAsStream("config.properties");
Properties properties = new Properties();
properties.load(is);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("pwd");
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 获得数据连接对象
*
* @return
*/
public static Connection getConnection() {
try {
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static void close(ResultSet rs) {
if (null != rs) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
public static void close(Statement stmt) {
if (null != stmt) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
public static void close(Connection conn) {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
public static void close(Connection conn, Statement stmt, ResultSet rs) {
close(rs);
close(stmt);
close(conn);
}
public static boolean isOracle() {
return "oracle.jdbc.driver.OracleDriver".equals(driver);
}
public static boolean isSQLServer() {
return "com.microsoft.sqlserver.jdbc.SQLServerDriver".equals(driver);
}
public static boolean isMysql() {
return "com.mysql.jdbc.Driver".equals(driver);
}
public static void main(String[] args) {
Connection conn = DBHelper.getConnection();
DBHelper.close(conn);
System.out.println("isOracle:" + isOracle());
System.out.println("isSQLServer:" + isSQLServer());
System.out.println("isMysql:" + isMysql());
System.out.println("数据库连接(关闭)成功");
}
}
连接数据库依赖config.properties
#oracle9i
#driver=oracle.jdbc.driver.OracleDriver
#url=jdbc:oracle:thin:@localhost:1521:orcl
#user=scott
#pwd=123
#sql2005
#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
#url=jdbc:sqlserver://localhost:1433;DatabaseName=test1
#user=sa
#pwd=123
#sql2000
#driver=com.microsoft.jdbc.sqlserver.SQLServerDriver
#url=jdbc:microsoft:sqlserver://localhost:1433;databaseName=unit6DB
#user=sa
#pwd=888888
#mysql
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/oa?useUnicode=true&characterEncoding=UTF-8&useSSL=false
user=root
pwd=123
然后创建实体类User
package com.zking.oapro.entity;
public class User {
private Long id;
private String name;
private String loginName;
private String pwd;
private Long rid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Long getRid() {
return rid;
}
public void setRid(Long rid) {
this.rid = rid;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", loginName=" + loginName + ", pwd=" + pwd + ", rid=" + rid + "]";
}
}
接下来就是写dao方法了,首先导入通用dao类BaseDao(具有分页功能)
package com.zking.oapro.dao;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import com.zking.oapro.util.DBHelper;
import com.zking.oapro.util.PageBean;
public class BaseDao<T> {
public static interface CallBack<T> {
/**
* 循环遍历结果集并返回List<T>结果
* @param rs
* @return
* @throws SQLException
*/
public List<T> forEach(ResultSet rs) throws SQLException;
}
public void executeUpdate(String sql,Object[] params) {
Connection conn=null;
PreparedStatement stmt=null;
try {
conn=DBHelper.getConnection();
stmt=conn.prepareStatement(sql);
ParameterMetaData metaData = stmt.getParameterMetaData();
for (int i = 0; i < metaData.getParameterCount(); i++) {
stmt.setObject(i+1, params[i]);
}
int i = stmt.executeUpdate();
if(i<1)
throw new RuntimeException("执行失败,影响行数为0!");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
DBHelper.close(conn, stmt, null);
}
}
/**
* 事物处理
* @param sql
* @return
*/
public static int executeUpdateBatch(String[] sqlLst) {
Connection conn=null;
PreparedStatement stmt=null;
try {
conn=DBHelper.getConnection();
//设置不自动提交
conn.setAutoCommit(false);
for (String sql : sqlLst) {
stmt=conn.prepareStatement(sql);
stmt.executeUpdate();
}
conn.commit();
} catch (Exception e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
throw new RuntimeException(e1);
}
e.printStackTrace();
throw new RuntimeException(e);
}finally {
DBHelper.close(conn, stmt, null);
}
return 0;
}
/**
* 查询方法(支持分页)
* @param sql SQL语句
* @param pageBean
* @return 返回分页结果集
*/
public List<T> executeQuery(String sql,PageBean pageBean,
CallBack<T> callback){
Connection conn=null;
PreparedStatement stmt=null;
ResultSet rs=null;
try {
//获取连接
conn=DBHelper.getConnection();
//1.判断是否分页
if(null!=pageBean&&pageBean.isPagination()) {
//2.根据满足条件得到获取总记录数的SQL语句
String countSql=this.getCountSql(sql);
//创建PreparedStatement
stmt=conn.prepareStatement(countSql);
//执行SQL语句,返回结果集(总记录数)
rs=stmt.executeQuery();
//获取总记录数
if(rs.next()) {
Integer total=rs.getInt(1);
//将总记录数保存到PageBean中的total属性
pageBean.setTotal(total);
}
//3.根据满足条件得到获取分页结果集的SQL语句
sql=this.getPagerSql(sql, pageBean);
}
stmt=conn.prepareStatement(sql);
rs=stmt.executeQuery();
//遍历结果集
return callback.forEach(rs);
} catch (Exception e) {
e.printStackTrace();
} finally {
DBHelper.close(conn, stmt, rs);
}
return null;
}
/**
* 将普通的SQL语句转换成查询总记录数的SQL语句
* @param sql 普通SQL语句
* @return 查询总记录数的SQL语句
*/
private String getCountSql(String sql) {
//select * from t_book
//select * from t_book where
//limit
return "select count(0) from ("+sql+") temp";
}
/**
* 将普通的SQL语句转换成查询分页结果集的SQL语句
* @param sql 普通的SQL语句
* @param pageBean 分页对象PageBean
* @return 返回的查询分页结果集的SQL语句
*/
private String getPagerSql(String sql,PageBean pageBean) {
//select * from t_book ... limit
//select * from t_book where ... limit
return sql+" limit "+pageBean.getStartIndex()+","+pageBean.getRows();
}
}
然后创建一个用户实体类UserDao,要继承BaseDao,且给上泛型User
package com.zking.oapro.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import com.zking.oapro.entity.User;
import com.zking.oapro.util.CommonUtils;
public class UserDao extends BaseDao<User> {
/**
* 根据用户名查询对应的用户对象信息
* @param user
* @return
*/
public User userLogin(User user) {
String sql="select * from t_oa_user where"
+ " loginName='"+user.getLoginName()+"'";
System.out.println(sql);
List<User> lst=super.executeQuery(sql, null, new CallBack<User>() {
@Override
public List<User> forEach(ResultSet rs) throws SQLException {
return CommonUtils.toList(rs, User.class);
}
});
if(null!=lst&&lst.size()!=0)
return lst.get(0);
else
return null;
}
}
再到action中写登录,创建UserAction 注意:不要忘记配置mvc.xml
package com.zking.oapro.action;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.mysql.jdbc.StringUtils;
import com.zking.mvc.framework.DispatcherAction;
import com.zking.mvc.framework.DriverModel;
import com.zking.oapro.dao.UserDao;
import com.zking.oapro.entity.User;
import com.zking.oapro.util.CommonUtils;
import com.zking.oapro.util.MD5;
public class UserAction extends DispatcherAction implements DriverModel<User> {
private User user=new User();
private UserDao userDao=new UserDao();
@Override
public User getModel() {
return user;
}
/**
* 用户登录
* @param req
* @param resp
* @return
* @throws ServletException
* @throws IOException
*/
public String userLogin(HttpServletRequest req,
HttpServletResponse resp) throws ServletException,IOException{
//1.判断用户名和密码是否为空
if(StringUtils.isNullOrEmpty(user.getLoginName())
||StringUtils.isNullOrEmpty(user.getPwd())) {
CommonUtils.toJson(false,"账号或者密码不能为空!", resp);
}else {
//2.根据用户名获取数据库中对应的用户对象信息
User us = userDao.userLogin(user);
//3.判断查询出来的用户是否为空,为空则表示用户不存在
if(null==us) {
CommonUtils.toJson(false, "账号不存在!", resp);
}else {
//4.判断数据库密码与输入的密码是否正确
//us=数据库查询出来的对象 user=前端输入的用户对象
String pwd=new MD5().getMD5ofStr(user.getPwd());
if(!pwd.equals(us.getPwd())) {
CommonUtils.toJson(false, "密码错误!", resp);
}else {
//5.将当前登录用户对象保存到Session中
HttpSession session = req.getSession();
session.setAttribute("user", us);
CommonUtils.toJson(true, "OK", resp);
}
}
}
return null;
}
/**
* 用户退出
* @param req
* @param resp
* @return
* @throws ServletException
* @throws IOException
*/
public String logout(HttpServletRequest req,
HttpServletResponse resp) throws ServletException,IOException{
req.getSession().invalidate();
resp.sendRedirect("login.jsp");
return null;
}
}
mvc.xml(mvc.xml要放置到src的根路径下)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE config[
<!ELEMENT config (action*)>
<!ELEMENT action (forward*)>
<!ELEMENT forward EMPTY>
<!ATTLIST action
path CDATA #REQUIRED
type CDATA #REQUIRED
>
<!ATTLIST forward
name CDATA #REQUIRED
path CDATA #REQUIRED
redirect (true|false) "false"
>
]>
<config>
<action type="com.zking.oapro.action.UserAction" path="/userAction"></action>
</config>
后台接口已经准备好了,现在去前端写js,在js目录下创建login.js
let layer,$;
layui.use(['layer','jquery'],function(){
layer=layui.layer,$=layui.jquery;
//登录实现
$('#login').click(function(){
//1.获取登录账号和密码信息
let username=$('#username').val();
let password=$('#password').val();
//2.判断登录账号和密码是否为空
if(''==username){
layer.msg('登录账号不能为空!',function(){});
return false;
}
if(''==password){
layer.msg('登录密码不能为空!',function(){});
return false;
}
//3.准备请求参数
let params={
loginName:username,
pwd:password,
methodName:'userLogin'
};
console.log(params);
//4.发起ajax请求
$.post('userAction.action',params,function(data){
console.log(data);
if(data.success){
location.href="index.jsp";
}else{
layer.msg(data.msg,{icon:5},function(){});
}
},'json');
});
});
然后是登录页面login.jsp的代码
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<%@include file="/common/head.jsp" %>
<link rel="stylesheet" rev="stylesheet" href="css/iconfont.css" type="text/css" media="all">
<link rel="stylesheet" rev="stylesheet" href="css/login.css" type="text/css" media="all">
<style> body{color:#;}a{color:#;}a:hover{color:#;}.bg-black{background-color:#;}.tx-login-bg{background:url(images/bg.jpg) no-repeat 0 0;}</style>
<script type="text/javascript" src="js/login.js"></script>
</head>
<body class="tx-login-bg">
<div class="tx-login-box">
<div class="login-avatar bg-black"><i class="iconfont icon-wode"></i></div>
<ul class="tx-form-li row">
<li class="col-24 col-m-24"><p><input type="text" id="username" placeholder="登录账号" class="tx-input"></p></li>
<li class="col-24 col-m-24"><p><input type="password" id="password" placeholder="登录密码" class="tx-input"></p></li>
<li class="col-24 col-m-24"><p class="tx-input-full"><button id="login" class="tx-btn tx-btn-big bg-black">登录</button></p></li>
<li class="col-12 col-m-12"><p><a href="#" class="f-12 f-gray">新用户注册</a></p></li>
<li class="col-12 col-m-12"><p class="ta-r"><a href="#" class="f-12 f-gray">忘记密码</a></p></li>
</ul>
</div>
</body>
</html>
common目录下的head.jsp是通用的css与js的导入
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<base href="${pageContext.request.contextPath }/"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>微光云创会议OA系统</title>
<!-- Layui核心css文件 -->
<link href="js/layui/css/layui.css" rel="stylesheet" type="text/css"/>
<!-- Layui核心js文件 -->
<script type="text/javascript" src="js/layui/layui.js"></script>
到现在终于进入首页了