后台页面基于AdminLTE
AdminLTE是基于bootstrap和jquery的,主要是用于创建后台网站。
ADminLTE官网:https://github.com/ColorlibHQ/AdminLTE
ADminLTE汉化:https://github.com/itheima2017/adminlte2-itheima
表结构介绍
多对多关系的有:订单表与旅客表、用户表与角色表、角色表与资源权限表。
环境搭建
创建一个没有骨架的父工程,然后将pom.xml复制到父工程的pom.xml文件就可以了,从<properties>开始直到</build>,不要把<modules>也复制了。
web这个子工程记得配置一个tomcat7插件,
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8080</port>
</configuration>
<version>2.2</version>
</plugin>
</plugins>
制作product-list.jsp页面
1、ctrl+F把../替换成${pageContext.request.contextPath}/,换成绝对路径。
2、讲之前的页面头和导航侧栏抽取到两个jsp文件中并include进来。
3、在相应位置修改成我们修改的表头
4、讲<tbody>标签里的<tr>标签改写成动态遍历的,并在jsp页面引入jstl才能使用forEach。
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:forEach items="${productList}" var="product">
<tr>
<td><input name="ids" type="checkbox"></td>
<td>${product.id}</td>
<td>${product.productNum}</td>
<td>${product.productName}</td>
<td>${product.cityName}</td>
<td>${product.departureTimeStr}</td>
<td class="text-center">${product.productPrice}</td>
<td class="text-center">${product.productDesc}</td>
<td class="text-center">${product.productStatusStr}</td>
<td class="text-center">
<button type="button" class="btn bg-olive btn-xs">订单</button>
<button type="button" class="btn bg-olive btn-xs">详情</button>
<button type="button" class="btn bg-olive btn-xs">编辑</button>
</td>
</tr>
</c:forEach>
添加日志配置文件以及它的作用
在我们编写好,添加产品的前端和后端代码之后(逻辑没问题),点击保存之后出现400错误,,但是在我们服务器端(Tomcat7)后台却看不到任何操作以及错误的提示信息。
后台不报错的原因,我们没加日志,加上即可。
这也是下面这些jar包(依赖)的作用,
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency> <!-- log end -->
加上日志文件后,能看到服务器端报的错误如下:
原因:springmvc框架类型转换问题。
解决方案:
1.类型转换器Converter,这是一个最优解决方式,因为它是一种全局类型转换方式。
2.实体类中加日期格式化注解。优点,使用简单。缺陷,是局部的这对当前加上这个注解的类字段属性有效,如果其他bean也需要转换又得手动去添加,没有第一种好。
3.属性编辑器。这是一种spring3.1之前可以使用的一种方式,用法比较复杂且不推荐使用。
这里我们选用方式2,因为简单:
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm")
private Date departureTime; //出发时间
订单分页查询
PageHelper介绍
PageHelper是国内非常优秀的一款开源的mybatis分页插件(它只是mybatis的一个插件),它支持基本主流与常用的数据库,例如mysql、 oracle、mariaDB、DB2、SQLite、Hsqldb等。
本项目在 github 的项目地址:https://github.com/pagehelper/Mybatis-PageHelper
本项目在 gitosc 的项目地址:http://git.oschina.net/free/Mybatis_PageHelper
可以自己去上面的中文官网地址,自行学习,全是中文学习成本很低。
PageHelper使用
1、加入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
2、在spring.xml配置文件中
注意:如果使用的不是mysql数据库,而是oracle数据库,直接在helperDialect属性写成oracle即可。
部分参数说明,其他参数作用看文档:
reasonable:分页合理化参数,默认值为 false 。当该参数设置为 true 时,pageNum<=0 时会查询第一 页,pageNum>pages (超过总数时),会查询最后一页。默认 false 时,直接根据参数进行查询。
配置了这个,当你一直按上一页或者下一页就不会出错了。
<!-- 把交给IOC管理 SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 传入PageHelper的插件 -->
<property name="plugins">
<array>
<!-- 传入插件的对象 -->
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="helperDialect">mysql</prop>
<prop key="reasonable">true</prop>
</props>
</property>
</bean>
</array>
</property>
</bean>
3、在真正执行sql前,使用PageHelper来完成分页
在service的实现类中添加,
@Override
public List<Orders> findAll() {
//参数pageNum是页码值 参数pageSize是每页显示条数
PageHelper.startPage(1, 5);
return ordersDao.findAll();
}
原理:return ordersDao.findAll();之前加上PageHelper.startPage(1, 5);这条语句,它在真正查询时,在最后去拼一个分页条件。这两条语句必须紧挨着,中间不能有其他代码,不然就不起效果了,就拼不起来了。
4、其他细节地方修改
前端代码修改,菜单那块:
修改Controller类:
@RequestMapping("findAll.do")
public ModelAndView findAll(@RequestParam(name = "page", defaultValue = "1") int page, @RequestParam(name = "size", defaultValue = "5") int size) {
ModelAndView mv = new ModelAndView();
List<Orders> ordersList = ordersService.findAll(page,size);
// PageInfo就是一个分页bean 通过其构造方法最后得到的结果集是PageInfo对象中的一个list字段属性
PageInfo pageInfo=new PageInfo(ordersList);
mv.addObject("pageInfo",pageInfo);
mv.setViewName("orders-page-list");
return mv;
}
修改相应的service接口以及实现类,加入page与size参数。
接口:
public List<Orders> findAll(int page ,int size);
service实现类:
public List<Orders> findAll(int page, int size) {
//参数pageNum是页码值 参数pageSize是每页显示条数
PageHelper.startPage(page, size);
return ordersDao.findAll();
}
最后修改展示页面的代码:
说明,传到页面的参数是pageInfo然后还得取到里面的结果集为list,看看PgaeInfo对象的源码就知道list字段的含义了。
完善下一页上一页第几页功能
<div class="box-tools pull-right">
<ul class="pagination">
<li>
<a href="${pageContext.request.contextPath}/orders/findAll.do?page=1&size=${pageInfo.pageSize}"
aria-label="Previous">首页</a>
</li>
<li>
<a href="${pageContext.request.contextPath}/orders/findAll.do?page=${pageInfo.pageNum-1}&size=${pageInfo.pageSize}">上一页</a>
</li>
<c:forEach begin="1" end="${pageInfo.pages}" var="pageNum">
<li>
<a href="${pageContext.request.contextPath}/orders/findAll.do?page=${pageNum}&size=${pageInfo.pageSize}">${pageNum}</a>
</li>
</c:forEach>
<li>
<a href="${pageContext.request.contextPath}/orders/findAll.do?page=${pageInfo.pageNum+1}&size=${pageInfo.pageSize}">下一页</a>
</li>
<li>
<a href="${pageContext.request.contextPath}/orders/findAll.do?page=${pageInfo.pages}&size=${pageInfo.pageSize}"
aria-label="Next">尾页</a>
</li>
</ul>
</div>
完成每页显示几条数据功能
页面:
<div class="pull-left">
<div class="form-group form-inline">
总共${pageInfo.pages} 页,共${pageInfo.total} 条数据。 每页
<select class="form-control" id="changePageSize" onchange="changePageSize()">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select> 条
</div>
</div>
js函数:
<script>
function changePageSize() {
//获取下拉框的值
var pageSize = $("#changePageSize").val();
//向服务器发送请求,改变没页显示条数
location.href = "${pageContext.request.contextPath}/orders/findAll.do?page=1&size="
+ pageSize;
}
</script>
订单详情功能
涉及到多表操作。不仅查询订单信息,还有产品信息、会员信息、旅客信息(多对多)。
流程图:
具体操作此处,略。详情可以直接看本博客提供的github工程里的相应部分dao层的处理,如何实现多表查询操作。