1.MVC设计模式

1.1.分层架构模式

随着软件工程的规模越来越大,复杂度越来越高,工程中的组件也越来越多。而组件与组件之间的关联过于紧密,导致整个工程变得异常复杂,进而导致开发人员越来越难以掌控整个工程,造成工程开发失败。 这就是组件之间的 “紧耦合” 问题。为了解决这个问题,提出了 “高内聚低耦合” 的思想。也就是 “解耦”。

  1. 高内聚:每个模块尽可能独立完成自己的功能,不依赖于模块外部的代码。
  2. 低耦合:模块与模块之间使用接口尽量降低耦合度。

高内聚、低耦合目的:使得软件工程实现 “可重用、可扩展、可维护、灵活性好” 的目的。
分层架构也是解决 “解耦” 问题的一种设计模式。

1.1.1.model1 两层架构

在早期开发中,通常采用的都是model1。Model1就是两层架构:视图层和数据层。
05.MVC设计模式 - 图1

实际上,在我们的第一个JDBC项目中,使用的就是两层架构。

1.1.2.model2 三层架构

model1两层架构只适用于比较简单的软件工程,后来出现了model2三层架构。
05.MVC设计模式 - 图2

所谓三层体系结构,是在视图层与数据层之间加入了一个“中间层”。 三层架构使得视图层不在直接与数据层进行交互,而是经由中间层与数据层进行交互。

1.2.MVC设计模式

model2三层架构提供了一种思想,为了实现这种思想,人们提出了一些具体的设计模式。 MVC就三层架构思想的一种具体实现。
05.MVC设计模式 - 图3

  • MVC是 “Model-View-Controller” 的缩写。也就是 “模型-视图-控制器”。
  • MVC把工程的组成分解成模型、视图、控制器三种部件。
  • MVC架构的目的:用控制器将业务模型和视图分离,这就是MVC架构的目的。

1.3.在javaWeb工程中的MVC

05.MVC设计模式 - 图4

具体来说: 在javaWeb工程中,MVC部件与javaWeb工程中的组件的对应关系为:

  • View:前端html
  • Controller:Servlet
  • Model:javaBean(Service组件)

1.4.在前后端分离架构工程中的MVC

05.MVC设计模式 - 图5

在前后端分离的开发模式中,V层已经独立出来,成为一个独立的工程。

2.MVC实例:分页

下面使用MVC架构实现一个分页。工程目录结构为:

2.1.服务器端代码

2.1.1.使用过滤器解决跨域和字符集问题

  1. package com.neusoft.emp.filter;
  2. import javax.servlet.*;
  3. import javax.servlet.annotation.WebFilter;
  4. import javax.servlet.http.HttpServletResponse;
  5. import java.io.IOException;
  6. @WebFilter("/*")
  7. public class SetCharFilter implements Filter{
  8. @Override
  9. public void init(FilterConfig filterConfig) throws ServletException { }
  10. @Override
  11. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
  12. FilterChain filterChain) throws IOException, ServletException {
  13. servletRequest.setCharacterEncoding("utf-8");
  14. servletResponse.setContentType("text/html;charset=utf-8");
  15. servletResponse.setCharacterEncoding("utf-8");
  16. filterChain.doFilter(servletRequest, servletResponse);
  17. }
  18. @Override
  19. public void destroy() { }
  20. }
  1. package filter;
  2. import java.io.IOException;
  3. import javax.servlet.Filter;
  4. import javax.servlet.FilterChain;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.ServletRequest;
  8. import javax.servlet.ServletResponse;
  9. import javax.servlet.annotation.WebFilter;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. @WebFilter("/*")
  13. public class CorsFilter implements Filter {
  14. @Override
  15. public void init(FilterConfig filterConfig) throws ServletException {}
  16. @Override
  17. public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
  18. throws IOException, ServletException {
  19. HttpServletRequest request = (HttpServletRequest)req;
  20. HttpServletResponse response = (HttpServletResponse)resp;
  21. //设置允许跨域
  22. response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
  23. //设置开启Cookie
  24. response.setHeader("Access-Control-Allow-Credentials", "true");
  25. chain.doFilter(req, resp);
  26. }
  27. @Override
  28. public void destroy() {}
  29. }

2.1.2.po代码

  1. package com.neusoft.emp.po;
  2. public class Emp {
  3. private Integer empno;
  4. private String ename;
  5. private String job;
  6. private Integer mgr;
  7. private String hiredate;
  8. private Double sal;
  9. private Double comm;
  10. private Integer deptno;
  11. //get/set方法...
  12. }

2.1.3.dto代码

DTO:数据传输对象(Data Transfer Object); 这里专用于响应分页后的业务数据。

  1. package com.neusoft.emp.dto;
  2. import java.util.List;
  3. public class PageDto {
  4. private int totalRow; //总行数
  5. private int totalPageNum; //总页数
  6. private int preNum; //上一页
  7. private int nextNum; //下一页
  8. private int pageNum; //当前页
  9. private int maxPageNum; //每页显示最大行数
  10. private int beginNum; //开始记录数
  11. private List list; //查询返回数据
  12. //get/set方法...
  13. }

2.1.4.dao层代码

  1. package com.neusoft.emp.dao;
  2. import java.util.List;
  3. import com.neusoft.emp.po.Emp;
  4. public interface EmpDao {
  5. public int getEmpCount();
  6. public List<Emp> listEmp(int beginNum,int maxPageNum);
  7. }
  1. package com.neusoft.emp.dao.impl;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. import com.neusoft.emp.dao.EmpDao;
  9. import com.neusoft.emp.po.Emp;
  10. import com.neusoft.emp.util.DBUtil;
  11. public class EmpDaoImpl implements EmpDao{
  12. private Connection con = null;
  13. private PreparedStatement pst = null;
  14. private ResultSet rs = null;
  15. @Override
  16. public int getEmpCount() {
  17. int count = 0;
  18. String sql = "select count(*) from emp";
  19. try {
  20. con = DBUtil.getConnection();
  21. pst = con.prepareStatement(sql);
  22. rs = pst.executeQuery();
  23. if(rs.next()) {
  24. count = rs.getInt(1);
  25. }
  26. } catch (SQLException e) {
  27. e.printStackTrace();
  28. } finally {
  29. DBUtil.close(rs, pst, con);
  30. }
  31. return count;
  32. }
  33. @Override
  34. public List<Emp> listEmp(int beginNum,int maxPageNum) {
  35. List<Emp> list = new ArrayList();
  36. String sql = "select * from emp order by empno desc limit ?,?";
  37. try {
  38. con = DBUtil.getConnection();
  39. pst = con.prepareStatement(sql);
  40. pst.setInt(1, beginNum);
  41. pst.setInt(2, maxPageNum);
  42. rs = pst.executeQuery();
  43. while(rs.next()) {
  44. Emp e = new Emp();
  45. e.setEmpno(rs.getInt("empno"));
  46. e.setEname(rs.getString("ename"));
  47. e.setJob(rs.getString("job"));
  48. e.setMgr(rs.getInt("mgr"));
  49. e.setHiredate(rs.getString("hiredate"));
  50. e.setSal(rs.getDouble("sal"));
  51. e.setComm(rs.getDouble("comm"));
  52. e.setDeptno(rs.getInt("deptno"));
  53. list.add(e);
  54. }
  55. } catch (SQLException e) {
  56. e.printStackTrace();
  57. } finally {
  58. DBUtil.close(rs, pst, con);
  59. }
  60. return list;
  61. }
  62. }

2.1.5.service层代码

  1. package com.neusoft.emp.service;
  2. import com.neusoft.emp.dto.PageDto;
  3. public interface EmpService {
  4. public PageDto listEmp(int pageNum,int maxPageNum);
  5. }
  1. package com.neusoft.emp.service.impl;
  2. import java.util.List;
  3. import com.neusoft.emp.dao.EmpDao;
  4. import com.neusoft.emp.dao.impl.EmpDaoImpl;
  5. import com.neusoft.emp.dto.PageDto;
  6. import com.neusoft.emp.po.Emp;
  7. import com.neusoft.emp.service.EmpService;
  8. public class EmpServiceImpl implements EmpService{
  9. @Override
  10. public PageDto listEmp(int pageNum,int maxPageNum) {
  11. int totalRow = 0; //初始化总行数
  12. int totalPageNum = 0; //初始化总页数
  13. int preNum = 0; //初始化上一页
  14. int nextNum = 0; //初始化下一页
  15. int beginNum = 0; //初始化开始记录数
  16. //创建DAO
  17. EmpDao dao = new EmpDaoImpl();
  18. //创建返回值
  19. PageDto pageDto = new PageDto();
  20. //获取总行数
  21. totalRow = dao.getEmpCount();
  22. //如果查询行数为0,那么直接结束。
  23. if(totalRow == 0) {
  24. return pageDto;
  25. }
  26. //计算总页数
  27. //totalPageNum = totalRow/maxPageNum+1;
  28. if(totalRow%maxPageNum==0) {
  29. totalPageNum = totalRow/maxPageNum;
  30. }else {
  31. totalPageNum = totalRow/maxPageNum+1;
  32. }
  33. //当前页数验证
  34. if(pageNum<=0){
  35. pageNum = 1;
  36. }
  37. if(pageNum>totalPageNum){
  38. pageNum = totalPageNum;
  39. }
  40. //设置上一页和下一页
  41. preNum = pageNum;
  42. nextNum = pageNum;
  43. if(pageNum > 1) {
  44. preNum--;
  45. }
  46. if(pageNum < totalPageNum) {
  47. nextNum++;
  48. }
  49. //计算开始查询记录数
  50. beginNum = (pageNum - 1) * maxPageNum;
  51. //开始查询业务数据
  52. List<Emp> list = dao.listEmp(beginNum, maxPageNum);
  53. //封装返回数据
  54. pageDto.setTotalRow(totalRow);
  55. pageDto.setTotalPageNum(totalPageNum);
  56. pageDto.setPreNum(preNum);
  57. pageDto.setNextNum(nextNum);
  58. pageDto.setPageNum(pageNum);
  59. pageDto.setMaxPageNum(maxPageNum);
  60. pageDto.setBeginNum(beginNum);
  61. pageDto.setList(list);
  62. return pageDto;
  63. }
  64. }

2.1.6.controller层代码

  1. package com.neusoft.emp.servlet;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import java.util.List;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.annotation.WebServlet;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import com.fasterxml.jackson.databind.ObjectMapper;
  11. import com.neusoft.emp.dto.PageDto;
  12. import com.neusoft.emp.po.Emp;
  13. import com.neusoft.emp.service.EmpService;
  14. import com.neusoft.emp.service.impl.EmpServiceImpl;
  15. @WebServlet("/listEmp")
  16. public class ListEmpServlet extends HttpServlet {
  17. @Override
  18. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  19. throws ServletException, IOException {
  20. Integer pageNum = Integer.valueOf(request.getParameter("pageNum"));
  21. Integer maxPageNum = Integer.valueOf(request.getParameter("maxPageNum"));
  22. EmpService service = new EmpServiceImpl();
  23. PageDto pageDto = service.listEmp(pageNum, maxPageNum);
  24. PrintWriter out = response.getWriter();
  25. ObjectMapper om = new ObjectMapper();
  26. out.print(om.writeValueAsString(pageDto));
  27. out.close();
  28. }
  29. @Override
  30. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  31. throws ServletException, IOException {
  32. doGet(request, response);
  33. }
  34. }

2.2.前端代码

  1. <template>
  2. <div class="home">
  3. <table>
  4. <tr>
  5. <th>员工编号</th>
  6. <th>员工姓名</th>
  7. <th>员工职位</th>
  8. <th>入职日期</th>
  9. <th>员工工资</th>
  10. <th>所属部门</th>
  11. </tr>
  12. <tr v-for="emp in pageInfo.list">
  13. <td>{{emp.empno}}</td>
  14. <td>{{emp.ename}}</td>
  15. <td>{{emp.job}}</td>
  16. <td>{{emp.hiredate}}</td>
  17. <td>{{emp.sal}}</td>
  18. <td>{{emp.deptno}}</td>
  19. </tr>
  20. </table>
  21. <ul>
  22. <li><a @click="fenye(1)">首页</a></li>
  23. <li><a @click="fenye(pageInfo.preNum)">上一页</a></li>
  24. <li>第页</li>
  25. <li>总页</li>
  26. <li><a @click="fenye(pageInfo.nextNum)">下一页</a></li>
  27. <li><a @click="fenye(pageInfo.totalPageNum)">尾页</a></li>
  28. <li>
  29. <input type="text" v-model="toPage"><a @click="fenye(toPage)">GO</a>
  30. </li>
  31. </ul>
  32. </div>
  33. </template>
  34. <script>
  35. export default {
  36. name: 'Home',
  37. data(){
  38. return {
  39. pageInfo:{},
  40. maxPageNum:10,
  41. toPage:1
  42. }
  43. },
  44. created() {
  45. this.fenye(1);
  46. },
  47. methods:{
  48. fenye(pageNum){
  49. this.$axios.post('http://localhost:8080/emp/listEmp',this.$qs.stringify({
  50. pageNum:pageNum,
  51. maxPageNum:this.maxPageNum
  52. }))
  53. .then(response=> {
  54. this.pageInfo = response.data
  55. })
  56. .catch(error=> {
  57. console.log(error);
  58. });
  59. }
  60. }
  61. }
  62. </script>
  63. <style scoped>
  64. table{
  65. width: 100%;
  66. border-collapse: collapse;
  67. }
  68. table tr,table td,table th{
  69. height: 36px;
  70. border-bottom: solid 1px #AAA;
  71. }
  72. ul{
  73. width: 100%;
  74. display: flex;
  75. justify-content: center;
  76. }
  77. ul li{
  78. width: 60px;
  79. display: flex;
  80. justify-content: center;
  81. }
  82. ul li input{
  83. width: 25px;
  84. margin-right: 4px;
  85. }
  86. ul li a{
  87. user-select: none;
  88. cursor: pointer;
  89. }
  90. </style>

[

](https://null_688_6639.gitee.io/javase/JavaWeb%E7%BC%96%E7%A8%8B/04.%E7%AC%AC%E5%9B%9B%E7%AB%A0%E8%BF%87%E6%BB%A4%E5%99%A8%E4%B8%8E%E7%9B%91%E5%90%AC%E5%99%A8.html)