分页与项目准备
一、EL与JSTL应用
在项目展示中使用EL+JSTL的应用:
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:forEach items="${emps}" var="emp">
<tr>
<td>${emp.id}</td>
<td>${emp.name}</td>
<td>${emp.salary}</td>
<td>${emp.age}</td>
<td><a href='${pageContext.request.contextPath}/manage/safe/remove?id=${emp.id}'>删除</a></td>
<td><a href='<%=request.getContextPath()%>/manage/safe/showEmp?id=${emp.id}'>修改</a></td>
</tr>
</c:forEach>
在显示单个对象时,使用EL表达式:
<form action="<%=request.getContextPath()%>/manage/safe/update">
<%-- 编号不可变更,要么设置为只读,要么隐藏该控件 --%>
编号:<input type="text" name="id" value="${emp.id}" readonly><br>
姓名:<input type="text" name="name" value="${emp.name}"><br>
工资:<input type="text" name="salary" value="${emp.salary}"><br>
年龄:<input type="text" name="age" value="${emp.age}"><br>
<input type="submit" value="修改">
</form>
二、MVC框架
概述
三个单词的组合:Model,View,Controller
M–Model:模型层,包含了业务模型,数据模型,实体模型
V–View: 视图层,用于展示后端数据,使用JSP/HTML展示视图
C–Controller:控制层,Servlet控制,用于和模型层打交道
应用场景:在java的很多框架中使用了MVC架构,例如:Struts2,SpringMVC
MVC与三层架构
MVC:将三层架构中的表示层分离了;抽取出了视图层,侧重点在于前后端的交互,封装了业务层与DAO层。
三层架构:重点在于模型层,在于后端数据的处理;将业务层和DAO分离,封装了控制层与视图层。
三、分页
分析:关于分页功能,我们可以先进行后端的处理,将SQL语句完成,并测试DAO,如果没问题,再进行前后端交互即可,需要考虑数据的封装。
后端操作
完成SQL语句:
第一页: select * from emp limit 0,5
第二页: select * from emp limit 5,5
以此类推…
员工DAO层的分页测试:
@Override
public List<Emp> selectEmpsPage(int startIndex, int pageSize) throws SQLException {
String sql = "select * from emp limit ?,?";
return runner.query(sql,new BeanListHandler<>(Emp.class),startIndex,pageSize);
}
public static void main(String[] args) throws SQLException {
List<Emp> emps = new EmpDaoImpl().selectEmpsPage(0,5);
System.out.println(emps);
}
封装Page
从后端回传到前端的数据有很多,例如:内容,当前页,页数量等,所以需要封装成Page实体类,将这些数据装起来。
创建Page实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Page <T>{ //分页的实体类
private int currentPage; //当前页
private int pageSize; //页大小(每页条数)
private long totalCount; //总条数
private long pageCount; //总页数
private List<T> list; //存内容
public Page(int currentPage,int pageSize){
this.currentPage = currentPage;
this.pageSize = pageSize;
}
}
在业务层进行Page数据的封装与逻辑判断
public class EmpServiceImpl implements EmpService {
private EmpDao empDao = new EmpDaoImpl();
@Override
public Page<Emp> getPage(String current) {
try {
//分页数据的封装:
int currentPage = 1; //初始数据:当前页默认为1
int pageSize = 5; //页大小默认5条
if(current!=null){ //为null则默认为第一页;不为null,则赋值
currentPage=Integer.parseInt(current);
}
Page page = new Page<>(currentPage,pageSize);
long totalCount = empDao.getEmpCounts();
page.setTotalCount(totalCount); //设置总条数
long pageCount = (long) Math.ceil ((double)totalCount/pageSize);
page.setPageCount(pageCount); //设置总页数
int startIndex = (currentPage-1)*pageSize; //求起始页
page.setList(empDao.selectEmpsPage(startIndex,pageSize));
return page;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
控制层只需传一个封装的Page数据
@WebServlet("/manage/safe/show")
public class EmpShowController extends HttpServlet {
private EmpService empService = new EmpServiceImpl(); //员工业务层
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String current = req.getParameter("currentPage");
//传入currentPage,表示根据选择的当前页,返回分页数据
Page<Emp> page = empService.getPage(current); //获取封装后的Page实体
req.setAttribute("p",page); //存储page实体
req.getRequestDispatcher("/showEmps.jsp").forward(req,resp);
}
}
前端测试:http://localhost:8080/manage/safe/show?currentPage=2,根据传入的当前页,显示不同页数的内容。
分页展示
<a href="<%=request.getContextPath()%>/manage/safe/show?currentPage=1">首页</a>
<c:if test="${p.currentPage!=1}"><%--如果不是第一页,则显示上一页--%>
<a href="<%=request.getContextPath()%>/manage/safe/show?currentPage=${p.currentPage-1}">上一页</a>
</c:if>
<c:if test="${p.currentPage!=p.pageCount}"> <%-- 如果不是尾页,则显示下一页 --%>
<a href="<%=request.getContextPath()%>/manage/safe/show?currentPage=${p.currentPage+1}">下一页</a>
</c:if>
<a href="<%=request.getContextPath()%>/manage/safe/show?currentPage=${p.pageCount}">尾页</a>
共${p.currentPage}/${p.pageCount}
四、项目准备
电商项目目前虽然不是最主流,但是应用场景还是非常广;所以,以电商项目作为web项目,熟悉里面的项目流程是非常合适的。
商城类别
B2B: 商家对商家—阿里巴巴,中国制造
B2C: 商家对客户—京东
C2C: 客户对客户—淘宝(引入第三方售卖)
O2O:线上线下结合—京东,淘宝等都有线下实体店
商城模块
商城模块主要分为前端和后端的模块,通过用户的角色来设计前后端模块(这里的前后端模块都是动态web资源)
前端模块:(普通会员访问的模块)
会员用户模块管理、商品模块、类别模块、购物车模块、订单模块、订单详情模块,发货地址模块等。
后端模块:(管理员访问的模块)
后端登录模块、商品模块、类别模块、订单模块等(权限会更大,设置DML等功能)
开发流程
一个正规的公司,基本上会具备以下开发流程:
需求分析:产品经理与客户谈需求-项目需求,工期,收费
概要设计:技术总监完成需求文档,模块划分
详细设计:主管或架构师进行架构设计,从业务需求转为技术实现;需要的框架,数据结构,算法等
编码:前端和后端工程师进行编程开发
测试:黑盒测试(功能体验角度测试)与白盒测试(写代码及案例进行测试)
项目交付:程序员编写操作手册交付给客户,以及操作培训
验收:产品经理与客户洽谈功能是否合格,收款(90%~95%)
维护:程序员后期维护
五、项目设计
设计细节
考虑开发环境、开发工具、操作系统、数据库等等
主要业务功能:前端模块需要有那些设计以及后端模块要求
项目完成效果:根据普通会员,游客及管理员身份的登录进行流程化的设计
数据库设计
设计工具为PD,通过该工具创建表后,可以直观的看成这些表之间的关系;图形化效果较好。
PD生成SQL文件的步骤:
1.先创建CDM(概念数据模型):也就是创建了实体,实体中包含多个属性
2.再创建PDM(物理数据模型):将实体转为表设计,CDM中的属性转为PDM中的字段
3.最后生成SQL文件,该SQL文件即可导入到数据建库
表的关系
表的关系指的是多张表之间的关联关系,有以下几种:
一对一:从当前表的一条记录可查询到另一张表的一条记录;例如:一个人对应一个身份证
一对多:从当前表的一条记录可查询到另一张表的多条记录;例如:一个用户对应多个地址
多对多:双方都是一对多关系 例如:一个老师教多门课程;一门课程可以被多个老师教
六、项目搭建
导入素材
导入数据库的SQL文件
导入前端页面
导入项目中需要的依赖包
导入Utils工具类
BaseServlet设计
在前面的员工管理综合案例中,一个员工模块,在Controller层写了多个Controller,针对于功能进行编写的Controller(从功能角度设计);因为在之前的设计中,无法将这些功能整合到一个Controller中。
现在的商城项目中,有多个模块,我们可以从模块的角度出发,根据模块去整合多个应用功能;此处再使用功能去设计Controller则无法进行管理。
设计案例:有一个用户模块,里面整合登录和注册功能;另一个产品模块里面整合展示和搜索功能
思路1:创建BaseServlet,将每个模块的service方法处理都统一到BaseServlet,提升了复用性;
处理方案:BaseServlet继承HttpServlet;模块Servlet则继承BaseServlet
思路2:判断BaseServlet中的功能调用,找到对应模块中的方法调用,如何提升判断的维护性?
处理方案:使用反射机制,得到模块Servlet的类对象,再通过反射调用模块对应功能
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
//反射应用:
try{
Class clazz = this.getClass(); //获取反射对象 哪个模块访问的service,则反射对象代表谁
Method method = clazz.getMethod(action,HttpServletRequest.class,HttpServletResponse.class);
Object o = method.invoke(this,req,resp); //调用指定功能
}catch (Exception e){
e.printStackTrace();
}
}
}
@WebServlet("/user") //http://localhost:8080/user?action=login
public class UserController extends BaseServlet {
public void login(HttpServletRequest request,HttpServletResponse response){
System.out.println("登录功能");
}
public void register(HttpServletRequest request,HttpServletResponse response){
System.out.println("注册功能..");
}
}
@WebServlet("/product")
public class ProductController extends BaseServlet {
public void show(HttpServletRequest request,HttpServletResponse response){
System.out.println("产品展示");
}
public void search(HttpServletRequest request,HttpServletResponse response){
System.out.println("产品搜索");
}
}
访问规则:http://localhost:8080/user?action=login
七、总结与作业
总结
1.EL与JSTL应用
EL+JSTL完成if及for循环操作
2.MVC框架(重点)
概述、MVC与三层架构的区别
3.分页
后端操作-DAO测试SQL、封装Page-在业务层完成封装数据、分页展示
4.项目准备
商城类别、商城模块-前端会员、后端管理员模块、开发流程
5.项目设计
设计细节-环境准备、数据库设计-PD、表的关系(重点)
6.项目搭建
导入素材,BaseServlet设计(重点)
作业
1.BaseServlet设计的优势是什么?为什么调用方法需要传request和response参数
2.完成Servlet模块中统一返回String类型,并在BaseServlet中完成转发与重定向及字符串的判断;并说明这样设计的好处
晨考
1. MVC与三层架构区别
2. 分页中为什么需要Page实体类?
3. 为什么需要按模块划分控制层?为什么需要BaseServlet? 为什么用到了反射处理?
答: