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实例:分页
下面使用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{@Overridepublic void init(FilterConfig filterConfig) throws ServletException { }@Overridepublic 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);}@Overridepublic 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 {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic 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"));//设置开启Cookieresponse.setHeader("Access-Control-Allow-Credentials", "true");chain.doFilter(req, resp);}@Overridepublic 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;@Overridepublic 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;}@Overridepublic 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{@Overridepublic PageDto listEmp(int pageNum,int maxPageNum) {int totalRow = 0; //初始化总行数int totalPageNum = 0; //初始化总页数int preNum = 0; //初始化上一页int nextNum = 0; //初始化下一页int beginNum = 0; //初始化开始记录数//创建DAOEmpDao 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 {@Overrideprotected 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();}@Overrideprotected 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>第页</li><li>总页</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>
[
