这个项目中使用的是后台搭建的SSM框架和前端的模板,主要是bootstrap和jqgrid
关于jqgrid也是第一次使用,如果需要的话可以查看它的官方文档:jqGrid中文文档
1.关于项目中的日期格式化问题,在前端页面按照指定的格式显示时间只需要在实体类上加上两个注解即可,如下代码所示
/**
* 创建时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
* 更新时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
2.关于@ResponseBody注解
**概述:**这个注解的作用是用来将java对象转换成json格式的数据传递,前端框架将json格式的数据自动转换,呈现到前端的页面中进行展示
具体
主要是将controller层中的方法返回的对象通过适当的转换器转换为指定的格式之后,自恶如到response对象的body区域,通常用来返回json数据或者XML数据,如果不加上这个注解,通常return的时候返回的是一个字符串当然对于的是controller方法中 返回值为String类型,返回一个页面
注意
使用这个注解之后不会再走springmvc中的视图解析器,而是直接将数据写入输入流中,效果等同于通过response对象输出指定格式的数据。
使用场景
使用在方法上,使用这个注解之后,表示请求后的返回结果直接写入http response body中,通常都是通过AJAX进行异步请求获取数据时使用
注意
在使用 @RequestMapping后,返回值通常解析为跳转路径,但是加上 @ResponseBody 后返回结果 不会被解析为跳转路径,而是直接写入 HTTP response body 中。 比如异步获取 json 数据,加上 @ResponseBody 后,会直接返回 json 数据。@RequestBody 将 HTTP 请求正文插入方法中,使用适合的 HttpMessageConverter 将请求体写入某个对象。
3.评论模块的总结
我主要实现的功能是删除单个,批量删除,将数据库中的数据进行分页展示,模糊查询根据三个表中不同的字段,将数据进行excel进行导出,查看本行数据详情,通过模态框进行弹出来展示
1.首先来说的是单个删除,单个删除就是根据主键进行删除,只要sql语句写的没问题,这个就是常规操作,只要从前端获取到某一行的id传到后台就可以获取了,然后就是进行批量删除,批量删除时获取选中行的所有的id,将这个id数组传递到cotroller层,然后就是删除的不能在controller层,要在service层,如果删除过程中某一行的数据删除失败的时候,将事务进行回滚。还有就是前端通过js获取id数组的时候问题,
//批量删除的函数 获取 多行数据
function deleteBatch() {
var rowIdsOriginal=$("#jqGridId").getGridParam('selarrrow');//1
var rowIds = [];//获取的就是选中行的id 2
var idsArr=[];
$.extend(rowIds, rowIdsOriginal);//克隆 3 1,2,3这三行代码是获取选中行的ids
if(rowIds.length<1){
tipDialog2();//这是前端用的模板中封装好的弹出框
}else{
for(i in rowIds){
idsArr.push(rowIds[i]);
}
var dialog =art.dialog({
className:"g-dialog g-tip-dialog",
width: 400,
height:"auto",
padding:"0 0",
content: '<i class="icon question"></i><span class="text">确定删除?</span>',
lock: true,
ok: function () {
$.ajax({
url:"$rc.contextPath/comment/deleteBatch",
type:"post",
data:{'idsArr':idsArr},
traditional: true,//这个必须要加不然会报错的
success:function (result) {
//删除完之后重新加载表格中的数据
jQuery("#jqGridId").trigger("reloadGrid");
},
error:function () {
}
});
},
cancelVal: '取消',
cancel: true, //为true等价于function(){}
init:function(){
this._reset();
}
});
}
2.接下来就是分页展示数据了,分页展示数据主要就是使用了mybatis中封装好的PageHelper对象和PageInfo对象
@ResponseBody
@RequestMapping("selectPageAll")
public Map<String, Object> dividePage (@RequestParam(defaultValue = "1") Integer
page, @RequestParam(defaultValue = "10") Integer rows){
System.err.println("分页展示数据的方法执行了");
PageHelper.startPage(page, rows);
List<ElcComment> list = elcCommentService.queryAll();
PageInfo<ElcComment> pagers = new PageInfo<ElcComment>(list);
Map<String, Object> map = new HashMap<>();
map.put("totalCount", pagers.getTotal());
map.put("currentPage", pagers.getPageNum());
map.put("totalPage", pagers.getPages());
map.put("dataList", list);
return map;
}
这是前端ajax进行异步请求时,以及接收数据展示到页面中
$(function () {
jQuery("#jqGridId").jqGrid({//表格的id=#jqGridId
url: '$rc.contextPath/comment/selectPageAll',//请求路径
datatype: "json",
height: 500,
colNames: ['序号', '用户名', '公告标题', '评论详情', '创建时间', '修改时间','操作'],
colModel: [
{ name: 'id', index: 'id', width: 60, sorttype: "int", editable: true},
{ name: 'user.userName', index: 'userName', width: 200, sorttype: "date", editable: true},
{ name: 'notice.title', index: 'title', width: 200, editable: true },
{ name: 'detail', index: 'detail', width: 80, align: "right", sorttype: "float", editable: true },
{ name: 'createTime', index: 'createTime', width: 80, align: "right", sorttype: "float", editable: true },
{ name: 'updateTime', index: 'updateTime', width: 60, align: "right", sorttype: "float", editable: true },
{ formatter: function (cellValue, options, rowObject) {
return '<a class="gbn-min gbn-check gbn-blue" href="javascript:;" οnclick="seeComment()" data-placement="right" title="查看" data-toggle="modal" data-target="#myModal"><i></i></a>' + '<a class="gbn-min gbn-del gbn-red" title="删除" οnclick="tipDialog3(\'$rc.contextPath/comment/delete?id=' + rowObject.id + '\')" href="javascript:;"><i></i></a>';
} }
],
width: '100%',
autowidth:true,
height: '100%',
pager: 'jqGridPagerId', //分页工具栏
rowNum: 10, //每页显示记录数
viewrecords: true, //是否显示行数
rowList: [10, 20, 30], //可调整每页显示的记录数
multiselect: true,
caption: "评论信息列表",//相当于标题
jsonReader: {
root: 'dataList', // 数据
page: 'currentPage', // 当前页
total: 'totalPage', // 总页数
records: 'totalCount' // 总数据条数
}
});
});
直接使用mybatis提供的,然后就是看前端页面的传递的一页有几条数据就是请求参数 page和rows
使用时必须要先开启分页就是第一行代码 PageHelper.startPage(page, rows);
然后进行查询,将查询的结果放到list集合中,再通过PageInfo对象加上泛型放的是对象 ,通过构造new一个对象将list集合放进去,这个对象放的就是关于所有的数据信息,以及通过它的get方法获取想要的值,比如总记录数,当前页,总页数等,将这些信息放到map集合中返回响应给浏览器进行页面的展示。
3.关于模糊查询
<!-- 关联映射 -->
<resultMap id="commentMap" type="com.newcapec.ordos.entity.ElcComment">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="detail" column="detail" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
<!-- association和collection标签要用时要放在result否则就会报错 -->
<association property="user" javaType="SysUser" column="user_id">
<id property="id" column="id"/>
<result property="userName" column="user_name"/>
</association>
<association property="notice" javaType="Notice" column="notice_id">
<id property="id" column="id"/>
<result property="title" column="title"/>
</association>
</resultMap>
<!-- 模糊查询 根据多个字段进行查询 -->
<select id="dimSelect" parameterType="map" resultMap="commentMap">
SELECT elc_comment.id,elc_comment.detail,elc_comment.create_time,elc_comment.update_time,elc_notice.title,sys_user.user_name from
elc_comment,elc_notice,sys_user
-- where
-- elc_comment.notice_id=elc_notice.id
-- AND sys_user.id=elc_comment.user_id and
-- sys_user.user_name like
-- '%%' and elc_notice.title like '%%' and elc_comment.detail like '%%';
<where>
<if test="true"> elc_comment.notice_id=elc_notice.id </if>
<if test="true">AND sys_user.id=elc_comment.user_id </if>
<if test="userName!=null and userName!=''">and sys_user.user_name like #{userName}</if>
<if test="title!=null and title!=''">and elc_notice.title like #{title}</if>
<if test="detail!=null and detail!=''">and elc_comment.detail like #{detail}</if>
</where>
</select>
// 模糊查询
$("#select_comment_btn").click(function () {//搜索按钮的id
var detail=$("#details").val();//获取三个输入框中的值
var userName=$("#user_name").val();
var title=$("#notice_title").val();
$("#jqGridId").jqGrid('setGridParam',{
url: "$rc.contextPath/comment/dimSelect",
postData: {'detail':detail,'userName':userName,'title':title, selectType: 1}
}).trigger("reloadGrid");
$("#jqGridId").jqGrid('setGridParam',{
url: "$rc.contextPath/comment/dimSelect",
postData: {'detail':detail,'userName':userName,'title':title, selectType: 0}
});
});
在这里主要是对查询时的sql语句进行修改添加几个 like,在这里我走了一条麻烦路,就是将模糊查询和和分页数据展示进行分开写了,因为模糊查询时也需要将数据进行分页,分开写就多此一举,就要多写一条sql语句,多写一个controller层中的方法,而这样确实麻烦了,如果只用一个方法时,只需要通过传递一个实体类对象进行查询,where字句中的if如果为空就表示查询所有,不为空就是模糊查询,而且通过代码生成的sql语句就是传递一个对象进行查询,所以生成的代码确实有它存在的合理性,个人认为也是符合java中的面向对象的编程思想吧。如果在 添加一个模糊查询根据下拉框选中的公告类型来进行选择,这个由于我的查询所有的语句中没有传递任何参数,所以在进行添加这个功能就会很麻烦,也相当于自己给自己挖的坑吧,所以还是通过项目来进行不断的学习与熟练代码。
再有就是进行模糊查询的时候,由于是三张表进行查询,三张表对应了三个实体类对象,在进行一步请求时传递数据,就会出现问题,因为再评论对象中有两个依赖属性一个是用户user对象一个是公告notice对象,如果前端传递评论对象,controller层只能获取user对象和notice对象获取不到的是具体user对象的属性,比如通过用户名字进行模糊查询时,无法将获取的userName传递到后台,所以这时就需要再封装一个实体类用来存放请求参数,下面是我封装的
package com.newcapec.ordos.entity;
import java.io.Serializable;
import java.util.Map;
/**
* @program: ordos
* @description: 用来接收map集合
* @author: 亢超超
* @create: 2020-11-17 20:34:50
**/
public class CommentParams implements Serializable {
private String userName;
private String detail;
private String title;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
前端请求的参数是一个对象 postData: {'detail':detail,'userName':userName,'title':title, selectType: 1}
此时controller层中的方法通过封装好的对象进行接收就行了,查询时将这个对象中的值取出来放在map集合中进行查询,将查询好的数据list集合放在PageInfo中(构造方法new PageInfo<>(list))将map,然后在new一个map集合获取总数,总页数,总记录数和数据放进去即可,将第二个map集合返回响应给前端页面。下面是我写的比较麻烦的代码,就是分别写了方法(分页和模糊查询)。
4.关于导出表格数据到excel
需要引入lay的js文件
<script type="text/javascript" src="$rc.contextPath/static/layui/layui.js"></script>
<script type="text/javascript" src="$rc.contextPath/static/layui_exts/excel.js"></script>
controller层中的方法
@ResponseBody
@RequestMapping("outPut")
public Map outPut(){
List<OutPutComment> list=elcCommentService.outPut();
Map<String, Object> map=new HashMap<>();
map.put("code",0);
map.put("count",list.size());
map.put("msg","");
map.put("data",list);
return map;
}
js
// 数据导出方法
function outputExcel() {
layui.use(['jquery', 'excel', 'layer'], function() {
var $ = layui.jquery;
var layer = layui.layer;
var excel = layui.excel;
// 模拟从后端接口读取需要导出的数据
$.ajax({
url: 'outPut'
,dataType: 'json'
,success(res) {
var data = res.data;
// 重点!!!如果后端给的数据顺序和映射关系不对,请执行梳理函数后导出
data = excel.filterExportData(data, [
'id',
'userName',
'detail',
'title',
'createTime',
'updateTime',
]);
// 重点2!!!一般都需要加一个表头,表头的键名顺序需要与最终导出的数据一致
data.unshift({id: 'id',userName:'用户名',detail:'评论内容',title:'公告标题',createTime: '创建时间', updateTime: '修改时间'});
var timestart = Date.now();
excel.exportExcel(data, '评论信息数据.xlsx', 'xlsx');
var timeend = Date.now();
var spent = (timeend - timestart) / 1000;
layer.alert('简单的数据导出耗时 '+spent+' s');
}
,error() {
layer.alert('获取数据失败,请检查是否部署在本地服务器环境下');
}
});
});
}
这是通过lay导出,按照指定的格式进行修改即可,就是表格中对应的字段是三张表中的数据,而lay在请求数据时只能返回一个对象并没有包含id,所以需要在进行封装一个对象,将表格的列名对应的属性封装到一个类中,前端请求的对象里边的key就是类中的属性
data.unshift({id: 'id',userName:'用户名',detail:'评论内容',title:'公告标题',createTime: '创建时间', updateTime: '修改时间'});
封装的类如下
package com.newcapec.ordos.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @program: ordos
* @description: 评论数据导出excel
* @author: 亢超超
* @create: 2020-11-18 19:50:27
**/
public class OutPutComment {
private Integer id;
private String userName;
private String title;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateTime;
private String detail;
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
5.查看表格中某行数据的详情,弹出模态框设置只读属性,可以直接通过jqgrid封装好的获取行对象,这个行对象就包含了里边的所有的属性信息,只需要获取模态框中的输入框和文本域的id即可设置它们的value值,
js代码如下
// 查看评论详情
function seeComment() {
var ids=$("#jqGridId").jqGrid("getGridParam","selarrrow");
if (ids.length==1){
var rowId=$("#jqGridId").jqGrid("getGridParam","selrow");
var rowData = $("#jqGridId").jqGrid('getRowData',rowId);
$("#name").val(rowData['user.userName']);
$("#tit").val(rowData['notice.title']);
$("#dea").html(rowData.detail);
}
}
模态框展示
<a class="gbn-min gbn-check gbn-blue" href="javascript:;" onclick="seeComment()" data-placement="right" title="查看" data-toggle="modal" data-target="#myModal"><i></i></a>
<!--评论详情 模态框(Modal) -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
×
</button>
<h4 class="modal-title" id="myModalLabel">
评论详情展示
</h4>
</div>
<div class="modal-body">
<form class="bs-example bs-example-form" role="form">
<div class="input-group">
<span class="input-group-addon"> 用 户 名</span>
<input type="text" class="form-control" readonly id="name">
</div>
<br>
<div class="input-group">
<span class="input-group-addon">公告标题</span>
<input type="text" class="form-control" readonly id="tit">
</div>
<br>
<div class="input-group">
<span class="input-group-addon">评论内容</span>
<textarea type="text" class="form-control" readonly style="resize: none;" id="dea"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal -->
</div>
设置文本域不可拉伸改变大小的样式,行内添加 style="resize:none"即可