目录
1、会议发布功能演示
2、会议发布功能分析
- 参与者人员遍历 :只遍历最基层人员
- 列席者人员遍历 :只遍历中层人员
- 使用FormSelects插件
- 时间截取
- 时间转换date类型
- 将所有处理的数据添加到会议信息表中
2.1、会议表结构
3、FormSelects插件
文档地址https://hnzzmsf.github.io/example/example_v4.html#download
下载地址https://github.com/hnzzmsf/layui-formSelects
3.1、使用方式
1、下载之后直接解压放到对应存放静态文件的目录下
2、放到对应的文件夹之后,需要通过代码引入,我这里是通过公共界面引入的,然后需要用的话引入公共界面就可了,不一定要跟我一样,需要的界面引入就可以了,
注意:不同包下跟我的路径是不一样的
<!-- 引入formSelects核心css -->
<link rel="stylesheet" href="${pageContext.request.contextPath }/static/js/plugins/formSelects/formSelects-v4.css" />
<!-- 引入formSelects核心js -->
<script src="${pageContext.request.contextPath }/static/js/plugins/formSelects/formSelects-v4.js" type="text/javascript" charset="utf-8"></script>
最后在使用的时候,定义这个插件
var formSelects = layui.formSelects;
4、代码实现
4.1、sql语句分析:
在获取数据之前,插件告诉我们前台需要什么样的数据
官网中,可以看到这个插件所需要的数据格式是拥有 name,value,属性的格式,所以此时我们的sql语句不能只是简单的查询,是需要根据官网来的,但是我们的数据表中,没有value这个字段,只有id这个字段,所以取个别名,sql语句如下
//参与人员
select name,id as value from t_oa_user where rid=4
//列席人员
select name,id as value from t_oa_user WHERE rid <> 1 AND rid <> 4
4.2、dao层
package Dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.zking.util.BaseDao;
import com.zking.util.DBAccess;
import com.zking.util.PageBean;
import com.zking.util.StringUtils;
import Entity.Role_permission;
import Entity.User;
public class Userdao extends BaseDao<User>{
//遍历下拉框参与人员
public List<Map<String, Object>> listone() throws Exception {
String sql="select name,id as value from t_oa_user where rid=4";
return super.executeQuery(sql, null);
}
//遍历下拉框列席人员
public List<Map<String, Object>> listtwo() throws Exception {
String sql="select name,id as value from t_oa_user WHERE rid <> 1 AND rid <> 4";
return super.executeQuery(sql, null);
}
}
package Dao;
import java.util.List;
import java.util.Map;
import com.zking.util.BaseDao;
import com.zking.util.PageBean;
import com.zking.util.StringUtils;
import Entity.MeetingInfo;
import Entity.User;
public class Meetingdao extends BaseDao<MeetingInfo> {
// 添加会议信息
public int add(MeetingInfo info) throws Exception {
String sql = "insert into t_oa_meeting_info(title,content,canyuze,liexize,zhuchiren,\r\n"
+ "location,startTime,endTime,remark) values(?,?,?,?,?,?,?,?,?)";
return super.executeUpdate(sql, info, new String[] { "title", "content", "canyuze", "liexize", "zhuchiren",
"location", "startTime", "endTime", "remark" });
}
}
4.3 servlet层
package Servlet;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.ConvertUtils;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.Base64ImageUtils;
import com.zking.util.MyDateConverter;
import com.zking.util.PropertiesUtil;
import com.zking.util.R;
import com.zking.util.ResponseUtil;
import Dao.Meetingdao;
import Dao.Userdao;
import Entity.MeetingInfo;
public class addmeetingServlet extends ActionSupport implements ModelDriver<MeetingInfo> {
private Userdao u= new Userdao();
private Meetingdao m= new Meetingdao();
private MeetingInfo info= new MeetingInfo();
@Override
public MeetingInfo getModel() {
//方式二:
ConvertUtils.register(new MyDateConverter(),Date.class);
return info;
}
public void listone(HttpServletRequest req, HttpServletResponse resp) throws Exception {
// 查询所有的参与人员,所有的rid为4的人
List<Map<String, Object>> listone = u.listone();
// 工具类回显到前端
ResponseUtil.writeJson(resp, R.ok(0, "success", listone));
}
public String listtwo(HttpServletRequest req, HttpServletResponse resp) throws Exception {
// 查询所有的列席人员
List<Map<String, Object>> listtwo = u.listtwo();
// 工具类回显到前端
ResponseUtil.writeJson(resp, R.ok(0, "success", listtwo));
return null;
}
// 增加会议的方法
public String add(HttpServletRequest req, HttpServletResponse resp) throws Exception {
int r = m.add(info);
if(r>0) {
ResponseUtil.writeJson(resp, R.ok(0, "会议数据新增成功"));
}else {
ResponseUtil.writeJson(resp, R.ok(0, "会议数据新增失败"));
}
return null;
}
}
4.4 js层
var formSelects = layui.formSelects;
var $,layer,element,form;
layui.use(['jquery','layer','element','laydate','form'],function(){
layer = layui.layer
,$ = layui.jquery,
laydate=layui.laydate
,element = layui.element,
form = layui.form;
listone();
listtwo();
date();
// 提交form表单
form.on('submit(meeting)', function(data){
//拿到表单所有的数据
var rs=data.field;
// 抓取到rs中的时间区域数据,然后分组截取
rs["startTime"]= rs.dt.split('至')[0];
rs["endTime"]= rs.dt.split('至')[1];
rs['methodName']="add";
console.log(rs)
// 向后台发请求
$.post('addmeeting.action',rs,function(res){
// 请求成功函数
if(res.success){
layer.msg(res.msg,{icon:6,
time:2000})
// 如果成功了,重置表单
$("#btn_reset").click();
}else{
layer.msg(res.msg,{icon:5,
time:2000})
}
},'json')
return false;
});
})
// 遍历参与者下拉
function listone(){
$.getJSON("addmeeting.action",{methodName:"listone"},function(rs){
console.log(rs.data)
formSelects.data('canyuze', 'local', {
arr:rs.data
});
})
}
// 遍历列席者下拉
function listtwo(){
$.getJSON("addmeeting.action",{methodName:"listtwo"},function(rs){
console.log(rs.data)
formSelects.data('liexize', 'local', {
arr:rs.data
});
})
}
//日期时间选择器
function date(){
laydate.render({
elem: '#dt'
,type: 'datetime'
,range: '至'
});
}
4.5、jsp层代码
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@include file="/common/public.jsp"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="static/js/meeting/addMeeting.js"></script>
<title>发布会议</title>
</head>
<body>
<form class="layui-form layui-form-pane">
<div class="layui-form-item">
<button id="btn_add" type="submit" class="layui-btn" lay-submit="" lay-filter="meeting">立即提交</button>
<button id="btn_reset" type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
<div class="layui-form-item">
<label class="layui-form-label">会议标题</label>
<div class="layui-input-block">
<input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入标题" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">会议内容</label>
<div class="layui-input-block">
<textarea name="content" lay-verify="required" placeholder="请输入内容" class="layui-textarea"></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">参与者</label>
<div class="layui-input-block">
<select name="canyuze" xm-select="canyuze" lay-verify="required" lay-vertype="tips">
<option value="">---请选择---</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">列席者</label>
<div class="layui-input-block">
<select name="liexize" xm-select="liexize" lay-verify="required" lay-vertype="tips">
<option value="">---请选择---</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">主持人</label>
<div class="layui-input-block">
<input type="text" readonly="readonly" name="zhuchirenname" value="${user.name }" autocomplete="off" placeholder="请输入标题" class="layui-input">
<input type="hidden" name="zhuchiren" value="${user.id }"/>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">会议地点</label>
<div class="layui-input-block">
<input type="text" lay-verify="required" name="location" autocomplete="off" placeholder="请输入会议地点" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">会议时间</label>
<div class="layui-input-block">
<input type="text" readonly="readonly" lay-verify="required" id="dt" name="dt" autocomplete="off" placeholder="请选择会议时间" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">备注</label>
<div class="layui-input-block">
<textarea name="remark" placeholder="请输入备注" class="layui-textarea"></textarea>
</div>
</div>
</form>
</body>
</html>
5、使用到的工具类
5.1、basedao
package com.zking.util;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 所有Dao层的父类 BookDao UserDao OrderDao ...
*
* @author Administrator
*
* @param <T>
*/
public class BaseDao<T> {
/**
* 适合多表联查的数据返回
* @param sql
* @param pageBean
* @return
* @throws SQLException
* @throws InstantiationException
* @throws IllegalAccessException
*/
public List<Map<String, Object>> executeQuery(String sql, PageBean pageBean)
throws SQLException, InstantiationException, IllegalAccessException {
List<Map<String, Object>> list = new ArrayList<>();
Connection con = DBAccess.getConnection();
PreparedStatement pst = null;
ResultSet rs = null;
/*
* 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
*/
if (pageBean != null && pageBean.isPagination()) {
// 必须分页(列表需求)
String countSQL = getCountSQL(sql);
pst = con.prepareStatement(countSQL);
rs = pst.executeQuery();
if (rs.next()) {
pageBean.setTotal(String.valueOf(rs.getObject(1)));
}
// 挪动到下面,是因为最后才处理返回的结果集
// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'
// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据
// -- countSql=select count(1) from (sql) t 符合条件的总记录数
String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据
pst = con.prepareStatement(pageSQL);
rs = pst.executeQuery();
} else {
// 不分页(select需求)
pst = con.prepareStatement(sql);// 符合条件的所有数据
rs = pst.executeQuery();
}
// 获取源数据
ResultSetMetaData md = rs.getMetaData();
int count = md.getColumnCount();
Map<String, Object> map = null;
while (rs.next()) {
map = new HashMap<>();
for (int i = 1; i <= count; i++) {
// map.put(md.getColumnName(i), rs.getObject(i));
map.put(md.getColumnLabel(i), rs.getObject(i));
}
list.add(map);
}
return list;
}
/**
*
* @param sql
* @param attrs
* map中的key
* @param paMap
* jsp向后台传递的参数集合
* @return
* @throws SQLException
* @throws NoSuchFieldException
* @throws SecurityException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public int executeUpdate(String sql, String[] attrs, Map<String, String[]> paMap) throws SQLException,
NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Connection con = DBAccess.getConnection();
PreparedStatement pst = con.prepareStatement(sql);
for (int i = 0; i < attrs.length; i++) {
pst.setObject(i + 1, JsonUtils.getParamVal(paMap, attrs[i]));
}
return pst.executeUpdate();
}
/**
* 批处理
* @param sqlLst
* @return
*/
public static int executeUpdateBatch(String[] sqlLst) {
Connection conn = null;
PreparedStatement stmt = null;
try {
conn = DBAccess.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 {
DBAccess.close(conn, stmt, null);
}
return 0;
}
/**
* 通用的增删改方法
*
* @param book
* @throws Exception
*/
public int executeUpdate(String sql, T t, String[] attrs) throws Exception {
// String[] attrs = new String[] {"bid", "bname", "price"};
Connection con = DBAccess.getConnection();
PreparedStatement pst = con.prepareStatement(sql);
// pst.setObject(1, book.getBid());
// pst.setObject(2, book.getBname());
// pst.setObject(3, book.getPrice());
/*
* 思路: 1.从传进来的t中读取属性值 2.往预定义对象中设置了值
*
* t->book f->bid
*/
for (int i = 0; i < attrs.length; i++) {
Field f = t.getClass().getDeclaredField(attrs[i]);
f.setAccessible(true);
pst.setObject(i + 1, f.get(t));
}
return pst.executeUpdate();
}
/**
* 通用分页查询
*
* @param sql
* @param clz
* @return
* @throws Exception
*/
public List<T> executeQuery(String sql, Class<T> clz, PageBean pageBean) throws Exception {
List<T> list = new ArrayList<T>();
Connection con = DBAccess.getConnection();
;
PreparedStatement pst = null;
ResultSet rs = null;
/*
* 是否需要分页? 无需分页(项目中的下拉框,查询条件教员下拉框,无须分页) 必须分页(项目中列表类需求、订单列表、商品列表、学生列表...)
*/
if (pageBean != null && pageBean.isPagination()) {
// 必须分页(列表需求)
String countSQL = getCountSQL(sql);
pst = con.prepareStatement(countSQL);
rs = pst.executeQuery();
if (rs.next()) {
pageBean.setTotal(String.valueOf(rs.getObject(1)));
}
// 挪动到下面,是因为最后才处理返回的结果集
// -- sql=SELECT * FROM t_mvc_book WHERE bname like '%圣墟%'
// -- pageSql=sql limit (page-1)*rows,rows 对应某一页的数据
// -- countSql=select count(1) from (sql) t 符合条件的总记录数
String pageSQL = getPageSQL(sql, pageBean);// 符合条件的某一页数据
pst = con.prepareStatement(pageSQL);
rs = pst.executeQuery();
} else {
// 不分页(select需求)
pst = con.prepareStatement(sql);// 符合条件的所有数据
rs = pst.executeQuery();
}
while (rs.next()) {
T t = clz.newInstance();
Field[] fields = clz.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
f.set(t, rs.getObject(f.getName()));
}
list.add(t);
}
return list;
}
/**
* 将原生SQL转换成符合条件的总记录数countSQL
*
* @param sql
* @return
*/
private String getCountSQL(String sql) {
// -- countSql=select count(1) from (sql) t 符合条件的总记录数
return "select count(1) from (" + sql + ") t";
}
/**
* 将原生SQL转换成pageSQL
*
* @param sql
* @param pageBean
* @return
*/
private String getPageSQL(String sql, PageBean pageBean) {
// (this.page - 1) * this.rows
// pageSql=sql limit (page-1)*rows,rows
return sql + " limit " + pageBean.getStartIndex() + "," + pageBean.getRows();
}
}
5.2、R工具类
package com.zking.util;
import java.util.HashMap;
public class R extends HashMap{
public R data(String key, Object value) {
this.put(key, value);
return this;
}
public static R ok(int code, String msg) {
R r = new R();
r.data("success", true).data("code", code).data("msg", msg);
return r;
}
public static R error(int code, String msg) {
R r = new R();
r.data("success", false).data("code", code).data("msg", msg);
return r;
}
public static R ok(int code, String msg,Object data) {
R r = new R();
r.data("success", true).data("code", code).data("msg", msg).data("data", data);
return r;
}
public static R ok(int code, String msg, long count, Object data) {
R r = new R();
r.data("success", true).data("code", code).data("msg", msg).data("count", count).data("data", data);
return r;
}
}
5.3、ResponseUtil 类
package com.zking.util;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
public class ResponseUtil {
public static void write(HttpServletResponse response,Object o)throws Exception{
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
out.println(o.toString());
out.flush();
out.close();
}
public static void writeJson(HttpServletResponse response,Object o)throws Exception{
ObjectMapper om = new ObjectMapper();
// om.writeValueAsString(o)代表了json串
write(response, om.writeValueAsString(o));
}
}
6、疑难解答
看到这里我想大家会有一些疑问
1、关于工具类的解释我都放在了专栏里了,感兴趣的同学可以看一下了
2、明明数据库中的是endtime还有starttime,但是前端的组件反馈的值为一个变量把前后的时间全部给拿到了,那么我们怎么传递添加进数据库呢?其实layui框架中为我们考虑到了这一点,我们可以改变日期选择其中的range值让其有一个分界线
//日期时间选择器 function date(){ laydate.render({ elem: '#dt' ,type: 'datetime' ,range: '至' });
然后通过截取的方法,分别将开始值和结尾的时间值进行封装
// 抓取到rs中的时间区域数据,然后分组截取 rs["startTime"]= rs.dt.split('至')[0]; rs["endTime"]= rs.dt.split('至')[1];
这样子,我们就拿到我们所需要的值了
3、此时还有一个问题,我们从前端获取的值是string类型的,但是我们的数据库中的值是date类型的,我们得进行一个转换,怎么转换呢?
Java中使用org.apache.commons.beanutils.ConvertUtils类的register()方法进行注册自定义的日期转换器。有些小伙伴可能不懂,在servlet层的这段代码中
ConvertUtils.register(new MyDateConverter(),Date.class);
将一个自定义的日期转换器(MyDateConverter)注册到ConvertUtils类中,并指定该转换器要转换的目标类型为Date类。
ConvertUtils.register(new MyDateConverter(), Date.class)
这行代码的目的是注册一个自定义的日期转换器(MyDateConverter
),并将其与Date
类相关联。在Java中,日期类型的数据通常以字符串的形式进行传递和存储。如果你希望在处理数据时将字符串转换为
Date
类型,或从Date
类型转换为字符串,就需要进行日期的转换操作。然而,默认情况下,Java的数据转换工具无法直接将字符串转换为
Date
类型,或将Date
类型转换为字符串,因为它们是不同的数据类型。这时就需要自定义一个日期转换器来告诉转换工具如何执行这样的转换。所以,代码中的注册操作就是告诉转换工具,在遇到需要转换为
Date
类型的数据时,使用MyDateConverter
这个自定义的日期转换器来执行转换。
MyDateConverter
类实现了org.apache.commons.beanutils.Converter
接口,并提供了转换逻辑。该接口要求实现一个convert()
方法来执行数据转换操作,具体转换逻辑由自定义转换器的实现决定。通过注册自定义的转换器,转换工具可以在需要转换为
Date
类型的数据时,调用MyDateConverter
中的转换逻辑来实现数据转换。这样,你就可以将字符串作为输入,通过转换器将其转换为Date
类型,或者将Date
类型转换为字符串输出。
总的来说就是,只要写了这段代码,拥有了MyDateConverter 这个类
package com.zking.util; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.commons.beanutils.Converter; public class MyDateConverter implements Converter { @Override public Object convert(Class type, Object value) { String dateStr = (String)value; SimpleDateFormat spdt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { Date date = spdt.parse(dateStr); return date; } catch (Exception e) { e.printStackTrace(); } return null; } }
那么经过web层进行后端的数据传输的时候,就会自动将符合convert方法中数据格式的数据,转成data类型