15.mvc和分页

MVC和分页

第一节 MVC模式简介
1.1 MVC概念

​ 首先我们需要知道MVC模式并不是javaweb项目中独有的,MVC是一种软件工程中的一种设计模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),即为MVC。它是一种软件设计的典范,最早为Trygve Reenskaug提出,为施乐帕罗奥多研究中心(Xerox PARC)的Smalltalk语言发明的一种软件设计模式。

1.2 MVC模式详解

虽然MVC并不是Java当中独有的,但是现在几乎所有的B/S的架构都采用了MVC框架模式。

  • 控制器Controller:控制器即是控制请求的处理逻辑,对请求进行处理,负责请 求转发和重定向;
  • 视图View:视图即是用户看到并与之交互的界面,比如HTML(静态资源),JSP(动态资源)等等。
  • 模型Model:模型代表着一种企业规范,就是业务流程/状态的处理以及业务规则的规定。业务流程的处理过程对其他层来说是不透明的,模型接受的请求,并返回最终的处理结果。业务模型的设计可以说是MVC的核心。
1.3 MVC高级框架应用

​ MVC模式被广泛用于Java的各种框架中,比如Struts2、spring MVC等等都用到了这种思想。

Struts2是基于MVC的轻量级的web应用框架。基于MVC,说明基于Struts2开发的Web应用自然就能实现MVC,也说明Struts2着力于在MVC的各个部分为我们的开发提供相应帮助。

第二节 JSP开发模型
2.1 JavaWeb经历两个时期
2.1.1 JSP Model1

JSP Model1是JavaWeb早期的模型,它适合小型Web项目,开发成本低!Model1第一代时期,服务器端只有JSP页面,所有的操作都在JSP页面中,连访问数据库的API也在JSP页面中完成。也就是说,所有的东西都耦合在一起,对后期的维护和扩展极为不利。

在这里插入图片描述

JSP Model1的优化(Model1第二代)

JSP Model1优化后有所改进,把业务逻辑和数据访问的内容放到了JavaBean(狭义JavaBean:实体类,广义JavaBean:实体类,dao,service,工具类)中,而JSP页面负责显示以及请求调度的工作。虽然第二代比第一代好了些,但还让JSP做了过多的工作,JSP中把视图工作和请求调度(控制器)的工作耦合在一起了。

在这里插入图片描述

2.1.2 JSP Model2

JSP Model2模式已经可以清晰的看到MVC完整的结构了。

JSP:视图层,用来与用户打交道。负责接收数据,以及显示数据给用户;

Servlet:控制层,负责找到合适的模型对象来处理业务逻辑,转发到合适的视图;

JavaBean:模型层,完成具体的业务工作,例如:开启事务、转账等。

在这里插入图片描述

小结:这就是javaweb经历的两个时期,JSP Model2适合多人合作开发大型的Web项目,各司其职,互不干涉,有利于开发中的分工,有利于组件的重用。但是,Web项目的开发难度加大,同时对开发人员的技术要求也提高了。

2.2基于MVC的三层架构的实现

虽然MVC把程序分成三部分,每个部分负责不同的功能,但是这只是逻辑的分离,实际代码并没有真正分离,特别是Model(包括业务、数据访问和实体类、工具类等)部分的代码,为了增强代码的维护性和降低代码耦合性,需要把代码分层管理,于是就有了三层架构:

分别是:web层(表示|界面层)、service层(业务逻辑层)、dao层(数据访问层、持久层)

在这里插入图片描述

web层对应MVC中的Servlet和JSP

其他层都属于MVC中的Model

在这里插入图片描述

第三节 MVC结合事务练习

通过结合事务和MVC知识,练习一个转账demo

ThreadLocal:线程局部变量:作用实现把数据绑定到线程中,从而实现线程安全。

3.1 项目准备
  • 创建web项目

  • 导入需要jar包

    mysql驱动

​ druid.jar

​ commons-beanutils-1.8.3.jar

​ commons-collections.jar

​ commons-dbutils-1.4.jar

​ commons-logging-1.1.1.jar

  • 添加数据库配置文件

    db.properties

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/myschool
username=root
password=root
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=5000
3.2 编写前端页面
  • 转账页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'transfer.jsp' starting page</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  
  <body>
      
      <form action="${pageContext.request.contextPath }/servlet/AccountServlet" method="post" >
         
             转出方:<input type="text"  name="outaccount"/><br/>
             转入方:<input type="text"  name="intaccount"/><br/>        
             金额<input type="text"  name="money"/><br/>
     <input type="submit"  value="转账"/><br/>    
      </form>
  </body>
</html>
3.3 准备编写java代码

因为要使用到mvc模式,要对项目代码进行分包

3.3.1 项目分包

​ com.qf.dao

​ com.qf.dao.impl

​ com.qf.service

​ com.qf.service.impl

​ com.qf.web.servlet

​ com.qf.utils

​ com.qf.domain

3.3.2 编写DataSourceUtils工具类

DatasoutceUtils工具类,优化获取连接,优化事务操作

ThreadLocal的实例代表了一个线程局部的变量,每条线程都只能看到自己的值,并不会意识到其它的线程中也存在该变量。它采用采用空间来换取时间的方式,解决多线程中相同变量的访问冲突问题。

package com.itqf.utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.qf.utils.DruidUtils;

public class DataSourceUtils {
   
	private static DruidDataSource ds=null;
	
	private static ThreadLocal<Connection> tl=new ThreadLocal<Connection>();
   //静态代码块
    static {
   
        InputStream is = DruidUtils.class.getClassLoader().getResourceAsStream("db.properties");
        Properties properties=new Properties();
        try {
   
            properties.load(is);
            dataSource= (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
   
            e.printStackTrace();
        }

    }
	/**
	 * 获取数据源
	 * @return 连接池
	 */
	public static DataSource getDataSource(){
   
		return ds;
	}
	
	/**
	 * 从当前线程上获取连接
	 * @return 连接
	 * @throws SQLException
	 */
	public static Connection getConnection() throws SQLException{
   
		//-- 从线程获取链接
		Connection conn = tl.get();
		if(conn==null){
   
			//第一次获取 创建一个连接 和当前的线程绑定
			 conn=ds.getConnection();
			 
			 //----绑定
			 tl.set(conn);
		}
		return conn;
	}
	
	/**
	 * ---释放资源
	 * 
	 * @param conn
	 *            连接
	 * @param st
	 *            语句执行者
	 * @param rs
	 *            结果集
	 */
	public static void closeResource(Connection conn, Statement st, ResultSet rs) {
   
		closeResource(st, rs);
		closeConn(conn);
	}
	
	 
	public static void closeResource(Statement st, ResultSet rs) {
   
			closeResultSet(rs);
			closeStatement(st);
	}

	/**
	 * 释放连接
	 * 
	 * @param conn
	 *            连接
	 */
	public static void closeConn(Connection conn) {
   
		if (conn != null) {
   
			try {
   
              	//----和当前的线程解绑
				tl.remove();
				conn.close();
			} catch (SQLException e) {
   
				e.printStackTrace();
			}
			conn = null;
		}

	}

	/**
	 * 释放语句执行者
	 * 
	 * @param st
	 *            语句执行者
	 */
	public static void closeStatement(Statement st) {
   
		if (st != null) {
   
			try {
   
				st.close();
			} catch (SQLException e) {
   
				e.printStackTrace();
			}
			st = null;
		}

	}

	/**
	 * 释放结果集
	 * 
	 * @param rs
	 *            结果集
	 */
	public static void closeResultSet(ResultSet rs) {
   
		if (rs != null) {
   
			try {
   
				rs.close();
			} catch (SQLException e) {
   
				e.printStackTrace();
			}
			rs = null;
		}

	}
	
	/**
	 *---- 开启事务
	 * @throws SQLException
	 */
	public static void startTransaction() throws SQLException{
   
		//获取连接//开启事务
		getConnection().setAutoCommit(false);;
	}
	
	/**
	 *--- 事务提交
	 */
	public static void commitAndClose(){
   
		try {
   
			//获取连接
			Connection conn = getConnection();
			//提交事务
			conn.commit();
			//释放资源
			conn.close();
			//解除绑定
			tl.remove();
		} catch (SQLException e) {
   
			e.printStackTrace();
		}
	}
	
	/**
	 * ----事务回滚
	 */
	public static void rollbackAndClose(){
   
		try {
   
			//获取连接
			Connection conn = getConnection();
			//事务回滚
			conn.rollback();
			//释放资源
			conn.close();
			//解除绑定
			tl.remove();
		} catch (SQLException e) {
   
			e.printStackTrace();
		}
	}
}
3.3.3 编写Dao层代码

dao层进行具体数据库操作

package com.itqf.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.commons.dbutils.DbUtils;
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值