1.MVC设计模式
1.1.分层架构模式
随着软件工程的规模越来越大,复杂度越来越高,工程中的组件也越来越多。而组件与组件之间的关联过于紧密,导致整个工程变得异常复杂,进而导致开发人员越来越难以掌控整个工程,造成工程开发失败。 这就是组件之间的 “紧耦合” 问题。为了解决这个问题,提出了 “高内聚低耦合” 的思想。也就是 “解耦”。
- 高内聚:每个模块尽可能独立完成自己的功能,不依赖于模块外部的代码。
- 低耦合:模块与模块之间使用接口尽量降低耦合度。
高内聚、低耦合目的:使得软件工程实现 “可重用、可扩展、可维护、灵活性好” 的目的。
分层架构也是解决 “解耦” 问题的一种设计模式。
1.1.1.model1 两层架构
在早期开发中,通常采用的都是model1。Model1就是两层架构:视图层和数据层。
实际上,在我们的第一个JDBC项目中,使用的就是两层架构。
1.1.2.model2 三层架构
model1两层架构只适用于比较简单的软件工程,后来出现了model2三层架构。
所谓三层体系结构,是在视图层与数据层之间加入了一个“中间层”。 三层架构使得视图层不在直接与数据层进行交互,而是经由中间层与数据层进行交互。
1.2.MVC设计模式
model2三层架构提供了一种思想,为了实现这种思想,人们提出了一些具体的设计模式。 MVC就三层架构思想的一种具体实现。
- MVC是 “Model-View-Controller” 的缩写。也就是 “模型-视图-控制器”。
- MVC把工程的组成分解成模型、视图、控制器三种部件。
- MVC架构的目的:用控制器将业务模型和视图分离,这就是MVC架构的目的。
1.3.在javaWeb工程中的MVC
具体来说: 在javaWeb工程中,MVC部件与javaWeb工程中的组件的对应关系为:
- View:前端html
- Controller:Servlet
- Model:javaBean(Service组件)
1.4.在前后端分离架构工程中的MVC
在前后端分离的开发模式中,V层已经独立出来,成为一个独立的工程。
2.MVC实例:分页
2.1.服务器端代码
2.1.1.使用过滤器解决跨域和字符集问题
package com.neusoft.emp.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter("/*")
public class SetCharFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
servletResponse.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() { }
}
package filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebFilter("/*")
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
//设置允许跨域
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
//设置开启Cookie
response.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(req, resp);
}
@Override
public void destroy() {}
}
2.1.2.po代码
package com.neusoft.emp.po;
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer mgr;
private String hiredate;
private Double sal;
private Double comm;
private Integer deptno;
//get/set方法...
}
2.1.3.dto代码
DTO:数据传输对象(Data Transfer Object); 这里专用于响应分页后的业务数据。
package com.neusoft.emp.dto;
import java.util.List;
public class PageDto {
private int totalRow; //总行数
private int totalPageNum; //总页数
private int preNum; //上一页
private int nextNum; //下一页
private int pageNum; //当前页
private int maxPageNum; //每页显示最大行数
private int beginNum; //开始记录数
private List list; //查询返回数据
//get/set方法...
}
2.1.4.dao层代码
package com.neusoft.emp.dao;
import java.util.List;
import com.neusoft.emp.po.Emp;
public interface EmpDao {
public int getEmpCount();
public List<Emp> listEmp(int beginNum,int maxPageNum);
}
package com.neusoft.emp.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.neusoft.emp.dao.EmpDao;
import com.neusoft.emp.po.Emp;
import com.neusoft.emp.util.DBUtil;
public class EmpDaoImpl implements EmpDao{
private Connection con = null;
private PreparedStatement pst = null;
private ResultSet rs = null;
@Override
public int getEmpCount() {
int count = 0;
String sql = "select count(*) from emp";
try {
con = DBUtil.getConnection();
pst = con.prepareStatement(sql);
rs = pst.executeQuery();
if(rs.next()) {
count = rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(rs, pst, con);
}
return count;
}
@Override
public List<Emp> listEmp(int beginNum,int maxPageNum) {
List<Emp> list = new ArrayList();
String sql = "select * from emp order by empno desc limit ?,?";
try {
con = DBUtil.getConnection();
pst = con.prepareStatement(sql);
pst.setInt(1, beginNum);
pst.setInt(2, maxPageNum);
rs = pst.executeQuery();
while(rs.next()) {
Emp e = new Emp();
e.setEmpno(rs.getInt("empno"));
e.setEname(rs.getString("ename"));
e.setJob(rs.getString("job"));
e.setMgr(rs.getInt("mgr"));
e.setHiredate(rs.getString("hiredate"));
e.setSal(rs.getDouble("sal"));
e.setComm(rs.getDouble("comm"));
e.setDeptno(rs.getInt("deptno"));
list.add(e);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(rs, pst, con);
}
return list;
}
}
2.1.5.service层代码
package com.neusoft.emp.service;
import com.neusoft.emp.dto.PageDto;
public interface EmpService {
public PageDto listEmp(int pageNum,int maxPageNum);
}
package com.neusoft.emp.service.impl;
import java.util.List;
import com.neusoft.emp.dao.EmpDao;
import com.neusoft.emp.dao.impl.EmpDaoImpl;
import com.neusoft.emp.dto.PageDto;
import com.neusoft.emp.po.Emp;
import com.neusoft.emp.service.EmpService;
public class EmpServiceImpl implements EmpService{
@Override
public PageDto listEmp(int pageNum,int maxPageNum) {
int totalRow = 0; //初始化总行数
int totalPageNum = 0; //初始化总页数
int preNum = 0; //初始化上一页
int nextNum = 0; //初始化下一页
int beginNum = 0; //初始化开始记录数
//创建DAO
EmpDao dao = new EmpDaoImpl();
//创建返回值
PageDto pageDto = new PageDto();
//获取总行数
totalRow = dao.getEmpCount();
//如果查询行数为0,那么直接结束。
if(totalRow == 0) {
return pageDto;
}
//计算总页数
//totalPageNum = totalRow/maxPageNum+1;
if(totalRow%maxPageNum==0) {
totalPageNum = totalRow/maxPageNum;
}else {
totalPageNum = totalRow/maxPageNum+1;
}
//当前页数验证
if(pageNum<=0){
pageNum = 1;
}
if(pageNum>totalPageNum){
pageNum = totalPageNum;
}
//设置上一页和下一页
preNum = pageNum;
nextNum = pageNum;
if(pageNum > 1) {
preNum--;
}
if(pageNum < totalPageNum) {
nextNum++;
}
//计算开始查询记录数
beginNum = (pageNum - 1) * maxPageNum;
//开始查询业务数据
List<Emp> list = dao.listEmp(beginNum, maxPageNum);
//封装返回数据
pageDto.setTotalRow(totalRow);
pageDto.setTotalPageNum(totalPageNum);
pageDto.setPreNum(preNum);
pageDto.setNextNum(nextNum);
pageDto.setPageNum(pageNum);
pageDto.setMaxPageNum(maxPageNum);
pageDto.setBeginNum(beginNum);
pageDto.setList(list);
return pageDto;
}
}
2.1.6.controller层代码
package com.neusoft.emp.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.neusoft.emp.dto.PageDto;
import com.neusoft.emp.po.Emp;
import com.neusoft.emp.service.EmpService;
import com.neusoft.emp.service.impl.EmpServiceImpl;
@WebServlet("/listEmp")
public class ListEmpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Integer pageNum = Integer.valueOf(request.getParameter("pageNum"));
Integer maxPageNum = Integer.valueOf(request.getParameter("maxPageNum"));
EmpService service = new EmpServiceImpl();
PageDto pageDto = service.listEmp(pageNum, maxPageNum);
PrintWriter out = response.getWriter();
ObjectMapper om = new ObjectMapper();
out.print(om.writeValueAsString(pageDto));
out.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2.2.前端代码
<template>
<div class="home">
<table>
<tr>
<th>员工编号</th>
<th>员工姓名</th>
<th>员工职位</th>
<th>入职日期</th>
<th>员工工资</th>
<th>所属部门</th>
</tr>
<tr v-for="emp in pageInfo.list">
<td>{{emp.empno}}</td>
<td>{{emp.ename}}</td>
<td>{{emp.job}}</td>
<td>{{emp.hiredate}}</td>
<td>{{emp.sal}}</td>
<td>{{emp.deptno}}</td>
</tr>
</table>
<ul>
<li><a @click="fenye(1)">首页</a></li>
<li><a @click="fenye(pageInfo.preNum)">上一页</a></li>
<li>第{{pageInfo.pageNum}}页</li>
<li>总{{pageInfo.totalPageNum}}页</li>
<li><a @click="fenye(pageInfo.nextNum)">下一页</a></li>
<li><a @click="fenye(pageInfo.totalPageNum)">尾页</a></li>
<li>
<input type="text" v-model="toPage"><a @click="fenye(toPage)">GO</a>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Home',
data(){
return {
pageInfo:{},
maxPageNum:10,
toPage:1
}
},
created() {
this.fenye(1);
},
methods:{
fenye(pageNum){
this.$axios.post('http://localhost:8080/emp/listEmp',this.$qs.stringify({
pageNum:pageNum,
maxPageNum:this.maxPageNum
}))
.then(response=> {
this.pageInfo = response.data
})
.catch(error=> {
console.log(error);
});
}
}
}
</script>
<style scoped>
table{
width: 100%;
border-collapse: collapse;
}
table tr,table td,table th{
height: 36px;
border-bottom: solid 1px #AAA;
}
ul{
width: 100%;
display: flex;
justify-content: center;
}
ul li{
width: 60px;
display: flex;
justify-content: center;
}
ul li input{
width: 25px;
margin-right: 4px;
}
ul li a{
user-select: none;
cursor: pointer;
}
</style>