精华内容
下载资源
问答
  • MVC设计模式

    万次阅读 多人点赞 2019-05-27 21:03:58
    MVC设计模式的引入 在我们实际开发的最后到产品上线,供给客户使用,客户通过浏览器或者app等进行数据的操作,实现这个的有,处理发送请求,业务逻辑处理以及访问数据库,这三个功能我们是可以放到一块使用的,但是...

    MVC模式

    MVC:Model、View、Controller

    MVC设计模式的引入

    在我们实际开发的最后到产品上线,供给客户使用,客户通过浏览器或者app等进行数据的操作,实现这个的有,处理发送请求,业务逻辑处理以及访问数据库,这三个功能我们是可以放到一块使用的,但是如果放在一起,代码便会很臃肿,不利于维护,于是便出现了代码分层思想,把代码按照功能分为三层,即模型层(Model)、显示层(View)、控制层(Controller),这种代码的组织架构就叫MVC模式

    MVC分层图
    在这里插入图片描述
    模型层(Model):在模型层中又可以分为两层,即Service层和Dao层,这两层的主要功能是:

    Service层:负责一些业务处理,比如说:获取数据库连接,关闭数据库连接,事务回滚或者一些复杂的逻辑业务处理
    
    Dao层:(Database Accept Object)  负责访问数据库,对数据的操作,获取结果集,将结果集中的数据装到OV(Object Value)对象中,之后再返回给Service层
    

    Controller层:主要功能是处理用户的请求
    View层:主要负责显示数据(Html、Css、jQuery等等)

    实现分层的组织包结构图
    在这里插入图片描述
    代码的调用顺序:
    View>Controller>Service>Dao,如果上层代码对下层代码的依赖程度过高,就需要对每层的代码定义一个(标准)接口。
    定义接口之后的包结构
    在这里插入图片描述
    Model层的Dao层设计思想:
    为数据库中的emp表设计数据操作的Dao表,在实际开发过程中,Dao层需要先定义出自己的标准(接口),降低耦合度
    在这里插入图片描述
    1、新建一个项目
    2、导入相关的开发包,比如驱动包(oracle,mysql,sql server等的驱动包)
    3、构造出包的结构
    在这里插入图片描述
    4、创建emp对象,放在vo包下面,emp表中的字段名对应设置成javabean中的成员变量
    在这里插入图片描述

    package com.zhouym.mvcpro.vo;
    
    import java.io.Serializable;
    import java.util.Date;
    
    @SuppressWarnings("serial")
    public class Emp implements Serializable{
    //对应EMP表中的字段名
    	private Integer empno;
    	private String ename;
    	private String job;
    	private Integer mgr;
    	private Date hiredate;
    	private Double sal;
    	private Double comm;
    	private Integer deptno;
    	public Emp() {
    		super();
    	}
    	public Emp(Integer empno, String ename, String job, Integer mgr, Date hiredate, Double sal, Double comm,
    			Integer deptno) {
    		super();
    		this.empno = empno;
    		this.ename = ename;
    		this.job = job;
    		this.mgr = mgr;
    		this.hiredate = hiredate;
    		this.sal = sal;
    		this.comm = comm;
    		this.deptno = deptno;
    	}
    	public Integer getEmpno() {
    		return empno;
    	}
    	public void setEmpno(Integer empno) {
    		this.empno = empno;
    	}
    	public String getEname() {
    		return ename;
    	}
    	public void setEname(String ename) {
    		this.ename = ename;
    	}
    	public String getJob() {
    		return job;
    	}
    	public void setJob(String job) {
    		this.job = job;
    	}
    	public Integer getMgr() {
    		return mgr;
    	}
    	public void setMgr(Integer mgr) {
    		this.mgr = mgr;
    	}
    	public Date getHiredate() {
    		return hiredate;
    	}
    	public void setHiredate(Date hiredate) {
    		this.hiredate = hiredate;
    	}
    	public Double getSal() {
    		return sal;
    	}
    	public void setSal(Double sal) {
    		this.sal = sal;
    	}
    	public Double getComm() {
    		return comm;
    	}
    	public void setComm(Double comm) {
    		this.comm = comm;
    	}
    	public Integer getDeptno() {
    		return deptno;
    	}
    	public void setDeptno(Integer deptno) {
    		this.deptno = deptno;
    	}
    	@Override
    	public String toString() {
    		return "Emp [empno=" + empno + ", ename=" + ename + ", job=" + job + ", mgr=" + mgr + ", hiredate=" + hiredate
    				+ ", sal=" + sal + ", comm=" + comm + ", deptno=" + deptno + "]";
    	}
    	
    }
    

    注意的是:
    1、简单的java类中,最好使用基本类型对应的包装类
    2、实现Serializable接口,方便以后程序的拓展(比如说序列化该类对象就需要实现该接口)

    5、开发Dao层的接口
    定义一个父接口,定义一个适配器类,再定义子接口,让适配器类实现父接口,让一个子接口或者多个子接口继承父接口,再让一个真正的实现类去继承适配器类并且实现这些子接口,这样的好处是:可以让这个真正的实现类选择性的重写方法,根据实际需要选择要重写的方法,而不是被迫的全部重写这些方法。
    父接口

    package com.zhouym.mvcpro.dao;
    
    import java.util.List;
    import java.util.Set;
    
    /**
     * @author zhouym
     *
     * @param <K> 在对应实体类中表示数据库主键值的字段类型
     * @param <V> 表示对应的实体类的类型
     */
    public interface IBaseDAO<K,V> {
    	/**
    	 * 增加雇员数据的方法
    	 * @param emp 保存要插入数据的对象
    	 * @return
    	 * @throws Exception
    	 */
    	public int insert(V v) throws Exception;
    	
    	/**
    	 * 修改数据
    	 * @param emp 保存要插入数据的对象
    	 * @return
    	 * @throws Exception 
    	 */
    	public  int update(V v) throws Exception;
    	
    	/**
    	 * 根据编号删除数据
    	 * @param K
    	 * @return
    	 * @throws Exception
    	 */
    	public int deleteById(K k) throws Exception;
    	
    	/**
    	 * 批量删除数据
    	 * @param k
    	 * @return
    	 * @throws Exception
    	 */
    	public int deleteBatch(Set<K> ids) throws Exception;
    	
    	
    	/**
    	 * @param K 根据编号查询数据
    	 * @return
    	 * @throws Exception
    	 */
    	public V selectById(K K) throws Exception;
    	
    	/**
    	 * 模糊查询
    	 * @param kw 查询的内容
    	 * @param cp  表示当前页显示的数据量
    	 * @param ls  表示当前页
    	 * @return
    	 * @throws Exception
    	 */
    	public List<V> selectSplitAll(String kw,Integer cp,Integer ls) throws Exception;
    	
    		
    	/**
    	 * 统计数据量
    	 * @param kw 表示根据指定的参数显示统计量
    	 * @return
    	 * @throws Exception
    	 */
    	public int selectCount(String kw) throws Exception;
    	
    }
    
    

    让适配器类实现父接口,子接口继承父接口
    适配器类

    package com.zhouym.mvcpro.adapter;
    
    import java.util.List;
    import java.util.Set;
    
    import com.zhouym.mvcpro.dao.IBaseDAO;
    //适配器类实现父接口
    public class DAOAdapter<K,V> implements IBaseDAO<K, V>{
    
    	@Override
    	public int insert(V v) throws Exception {
    		return 0;
    	}
    
    	@Override
    	public int update(V v) throws Exception {
    		return 0;
    	}
    
    	@Override
    	public int deleteById(K k) throws Exception {
    		return 0;
    	}
    
    	@Override
    	public int deleteBatch(Set<K> ids) throws Exception {
    		return 0;
    	}
    
    	@Override
    	public V selectById(K K) throws Exception {
    		return null;
    	}
    
    	@Override
    	public List<V> selectSplitAll(String kw, Integer cp, Integer ls) throws Exception {
    		return null;
    	}
    
    	@Override
    	public int selectCount(String kw) throws Exception {		
    		return 0;
    	}
    
    }
    
    

    子接口
    在子接口中,可以定义本接口特有的方法,也可以不写,默认继承了父类的所有方法

    package com.zhouym.mvcpro.dao;
    
    import com.zhouym.mvcpro.vo.Emp;
    
    /**
     * 继承了父接口的所有方法(继承的是公共的方法)
     * @author zhouym
     *可以在本接口中定义特有的方法
     */
    public interface IEmpDAO extends IBaseDAO<Integer,Emp>{
    	
    }
    

    真正的实现类

    package com.zhouym.mvcpro.dao.impl;
    
    import java.sql.Connection;
    import java.util.List;
    import java.util.Set;
    import com.zhouym.mvcpro.vo.DBUtil;
    import com.zhouym.mvcpro.adapter.DAOAdapter;
    import com.zhouym.mvcpro.dao.IEmpDAO;
    import com.zhouym.mvcpro.vo.Emp;
    
    
    /**
     * 通过适配器模式,继承适配器类,实现接口,可便于在本类中选择性的继承需要用到的方法
     * @author 
     *
     */
    public class EmpDAOImpl extends DAOAdapter<Integer, Emp> implements IEmpDAO {
    	//将数据库连接对象传进来
    	private Connection conn;
    	//定义无参构造以及带参构造
    	public EmpDAOImpl() {
    		super();
    	}
    	
    	public EmpDAOImpl(Connection conn) {
    		super();
    		this.conn = conn;
    	}
    	
    	@Override
    	public int insert(Emp vo) throws Exception {
    		String sql = "insert into emp(ename,job,sal,hiredate,mgr,comm,deptno) values(?,?,?,?,?,?,?)";
    		System.out.println(sql);
    		return DBUtil.save(conn, sql, vo, false);
    	}
    
    	@Override
    	public int update(Emp vo) throws Exception {
    		String sql = "update emp set mgr=? , hiredate=? where ename=?";
    		System.out.println(sql);
    		return DBUtil.edit(conn, sql, vo);
    	}
    
    	@Override
    	public int deleteById(Integer empno) throws Exception {
    		String sql="delete from emp where empno=?";
    		return DBUtil.remove(conn, sql, empno);
    	}
    	//不需要的方法可以不用重写
    	@Override
    	public int deleteBatch(Set<Integer> ids) throws Exception {
    		StringBuilder sql = new StringBuilder("delete from emp where empno in (");
    		return DBUtil.remove(conn, sql, ids);
    	}
    
    	@Override
    	public Emp selectById(Integer id) throws Exception {
    		String sql = "select empno,ename,job,sal,hiredate,mgr,comm,deptno from emp where empno=?";
    		return DBUtil.selectOne(conn, sql, Emp.class, id);
    	}
    
    	@Override
    	public List<Emp> selectSplitAll(String kw, Integer cp, Integer ls) throws Exception {
    		
    		return DBUtil.selectSplitAll("A", 1, 3);
    	}
    
    	@Override
    	public int selectCount(String kw) throws Exception {
    		String sql = "select count(*) from emp where ename like ?";
    		return DBUtil.selectCount(conn, sql, "%"+kw+"%");
    	}
    
    }
    

    最后在这个实现类中的方法内调用工具类中的方法

    package com.zhouym.mvcpro.vo;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Set;
    
    public class DBUtil {
    	private static final int[] RETURN_GENERATED_KEYS = null;
    	private static PreparedStatement pst;
    	private static ResultSet rst;
    
    	/**
    	 * 实现数据的增加
    	 * 
    	 * @param conn
    	 *            连接对象名
    	 * @param sql
    	 *            sql语句对象
    	 * @param vo
    	 *            Volue Object
    	 * @param getAutoKey
    	 *            是否需要主动增长的主键值,如果getAutoKey为True,则需要返回自动增长的主键值
    	 * @return 返回收到影响的行数
    	 * @throws Exception
    	 */
    	public static <T> int save(Connection conn, String sql, T vo, boolean getAutoKey) throws Exception {
    		pst = conn.prepareStatement(sql,RETURN_GENERATED_KEYS);
    
    		// 为sql中的占位符“?”赋值
    		// sql = "insert into emp(ename,job,sal,hiredate,mgr,comm,deptno)
    		// values(?,?,?,?,?,?,?)"
    		// 分割后:ename,job,sal,hiredate,mgr,comm,deptno
    		String[] columns = sql.split("\\(")[1].split("\\)")[0].split(",");
    		// 取得vo类对应的class类对象 vo=emp
    		Class<?> cls = vo.getClass();
    		// 遍历字符串数组
    		for (int i = 0; i < columns.length; i++) {
    			// 获取当前字段对应在vo类中属性的值,调用对应的getter方法获取
    			Method m = cls.getDeclaredMethod("get" + upperCase(columns[i]));
    			// 调用方法取得值
    			Object fvalue = m.invoke(vo);
    
    			// 将这个值作为占位符的内容
    			pst.setObject(i + 1, fvalue);
    		}
    		// 对关键字段的自增长的判断
    		if (getAutoKey) {
    			rst = pst.getGeneratedKeys();
    			if (rst.next()) {
    				return rst.getInt(1);
    			}
    
    		} else {
    			return pst.executeUpdate();
    		}
    		return 0;
    	}
    
    	public static <T> int edit(Connection conn, String sql, T vo) throws Exception {
    		PreparedStatement pst = conn.prepareStatement(sql);
    		String[] columns = sql.split("set")[1].split("where")[0].split(",");
    		// 获取类对象
    		Class<?> cls = vo.getClass();
    
    		// 遍历数组
    		for (int i = 0; i < columns.length; i++) {
    			// 获取字段名
    			String fieldName = columns[i].split("=")[0].trim();
    
    			// 获取cls类中的字段方法
    			Method m = cls.getDeclaredMethod("get" + upperCase(fieldName));
    
    			// 获取字段值
    			Object fvalue = m.invoke(vo);
    
    			pst.setObject(i + 1, fvalue);
    
    		}
    
    		// 分割判断条件的字符,获取判断条件字段名
    		String conditionFieldName = sql.split("where")[1].split("=")[0].trim();
    
    		Object ob = cls.getDeclaredMethod("get" + upperCase(conditionFieldName)).invoke(vo);
    		pst.setObject(columns.length + 1, ob);
    
    		return pst.executeUpdate();
    	}
    
    	public static int remove(Connection conn, String sql, Object... params) throws SQLException {
    		pst = conn.prepareStatement(sql);
    		for (int i = 0; i < params.length; i++) {
    			pst.setObject(i + 1, params[i]);
    		}
    		return pst.executeUpdate();
    	}
    
    	public static int remove(Connection conn, StringBuilder sql, Set<Integer> ids) throws Exception {
    
    		Iterator<Integer> iter = ids.iterator();
    		// 遍历迭代器
    		while (iter.hasNext()) {
    			sql.append(iter.next() + ",");
    		}
    		sql.delete(sql.length() - 1, sql.length());
    
    		sql.append(")");
    		PreparedStatement pst = conn.prepareStatement(sql.toString());
    
    		return pst.executeUpdate();
    	}
    
    	public static <T> T selectOne(Connection conn, String sql, Class<T> clz, Object... params) throws Exception {
    		pst = conn.prepareStatement(sql);
    		for (int i = 0; i < params.length; i++) {
    			pst.setObject(i + 1, params[i]);
    		}
    		ResultSet rst = pst.executeQuery();
    		T t = null;
    		if (rst.next()) {
    			t = clz.newInstance();
    			// 获取所有属性
    			Field[] fs = clz.getDeclaredFields();
    			for (int i = 0; i < fs.length; i++) {
    				// 获取属性名
    				String fname = fs[i].getName();
    				// 获取属性对应的方法名
    				Method m = clz.getDeclaredMethod("get" + upperCase(fname));
    
    				// 根据属性名从结果集中获取数据
    				Object fvalue = null;
    				try {
    					fvalue = rst.getObject(fname);
    				} catch (Exception e) {
    
    				}
    				m.invoke(t, fvalue);
    			}
    		}
    		return t;
    	}
    
    	public static List<Emp> selectSplitAll(String kw, Integer cp, Integer ls) throws SQLException {
    		List<Emp> list = new ArrayList<Emp>();
    		// 对kw作空值判断
    		if (kw == null) {
    			kw = "";
    		}
    		kw = "%" + kw + "%";
    		// 创键数据路连接对象
    		Connection conn = ConnPoolUtil.getConnection();
    		// 封装sql语句
    
    		String sql = "select empno,ename,job,hiredate,sal,comm,mgr,deptno from emp" + " where ename like ? limit ?,?";
    
    		// 创建sql发送对象
    		PreparedStatement pst = conn.prepareStatement(sql);
    
    		// 为占位符设置内容
    		pst.setObject(1, kw);
    		pst.setObject(2, (cp - 1) * ls);
    		pst.setObject(3, ls);
    		// 执行sql语句,获取的数据会存在resultSet中,一种数据表的结构,存在指针,初始位置在第一行数据上面
    		ResultSet rst = pst.executeQuery();
    		// 通过循环,使用next()方法将指针下移
    		while (rst.next()) {
    			list.add(new Emp(rst.getInt("empno"), rst.getString("ename"), rst.getString("job"), rst.getInt("mgr"),
    					rst.getDate("hiredate"), rst.getDouble("sal"), rst.getDouble("comm"), rst.getInt("deptno")));
    
    		}
    
    		rst.close();
    		pst.close();
    		ConnPoolUtil.close(conn);
    
    		return list;
    	}
    
    	public static int selectCount(Connection conn, String sql, Object... params) throws Exception {
    		pst = conn.prepareStatement(sql);
    
    		for (int i = 0; i < params.length; i++) {
    			pst.setObject(i + 1, params[i]);
    		}
    
    		ResultSet rst = pst.executeQuery();
    		if (rst.next()) {
    			return rst.getInt(1);
    		}
    
    		return 0;
    	}
    
    	public static String upperCase(String column) {
    		// 方法名第一个首字母大写+后面的字母
    		return column.substring(0, 1).toUpperCase() + column.substring(1, column.length());
    	}
    }
    
    

    数据库连接池

    数据库连接池原理:
    1.当系统启动【初始化的时候】会创建5【可设置】个数据库初始连接
    2.当客户请求到来的时候【用户要获取Connection对象的时候】
    2.1连接池中有空闲连接,直接将空闲的连接中的一个赋给客户使用
    2.2如果连接池中没有空闲连接了,而且连接的数据量没有超过最大数量,
    那么连接池会向数据库申请创建新的连接【5 可设置】,然后交给客户使用
    2.3在2.2的情况下超过了最大连接数据,等待
    3.当客户数据库操作完成后,这个连接怎么处理
    3.1连接池中的空闲连接数已经超过了初始连接数,那么直接销毁
    3.2连接池中的空闲连接数没有超过初始连接数据,那么进入空闲状态
    3.3如果有等待的用户,那么这个连接直接交给等待的用户使用

    数据库连接池的概念:
    数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。

    使用数据库连接池的流程:
    在这里插入图片描述
    使用数据库连接池的步骤:
    第一次访问的时候,需要建立连接。 但是之后的访问,均会复用之前创建的连接,直接执行SQL语句。
    优点:
    较少了网络开销
    系统的性能会有一个实质的提升
    没有TIME_WAIT状态

    使用数据库连接池需配置几项参数:
    最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.
    最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作
    最大空闲时间
    获取连接超时时间
    超时重试连接次数

    常见的数据库连接池:
    BDCP
    C3P0
    Druid
    HikariCP

    这里介绍下Druid的优点:
    强大的监控特性,通过Druid提供的监控功能,可以清楚知道连接池和SQL的工作情况。
    a. 监控SQL的执行时间、ResultSet持有时间、返回行数、更新行数、错误次数、错误堆栈信息;

    b. SQL执行的耗时区间分布。什么是耗时区间分布呢?比如说,某个SQL执行了1000次,其中0-1毫秒区间50次,1-10毫秒800次,10-100毫秒100次,100-1000毫秒30次,1-10秒15次,10秒以上5次。通过耗时区间分布,能够非常清楚知道SQL的执行耗时情况;然后就可以对SQL语句进行优化

    c. 监控连接池的物理连接创建和销毁次数、逻辑连接的申请和关闭次数、非空等待次数、PSCache命中率等。

    方便扩展。Druid提供了Filter-Chain模式的扩展API,可以自己编写Filter拦截JDBC中的任何方法,可以在上面做任何事情,比如说性能监控、SQL审计、用户名密码加密、日志等等。
    Druid集合了开源和商业数据库连接池的优秀特性,并结合阿里巴巴大规模苛刻生产环境的使用经验进行优化。

    Druid的jar包下载连接:https://mvnrepository.com/artifact/com.alibaba/druid/1.0.20
    以后对数据库的连接直接可以通过连接池对数据库连接进行管理,特别方便
    举例代码如下

    package com.zhouym.mvcpro.vo;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import com.alibaba.druid.pool.DruidDataSource;
    
    public class ConnPoolUtil {
    	//创建数据库连接对象
    	private static String URL = "jdbc:mysql://localhost:3306/demo?useSSL=true&useUnicode=true&characterEncoding=UTF-8";
    	//创建驱动信息
    	private static String DRIVER="com.mysql.jdbc.Driver";
    	//创建数据库名称
    	private static String USER="root";
    	//创建数据库用户密码
    	private static String PASSWORD="123456";
    	//实例化一个数据源对象
    	private static DruidDataSource dataSource = new DruidDataSource();
    	
    	//使用静态代码块为数据源对象初始化值
    	static {
    		//配置连接地址
    		dataSource.setUrl(URL);
    		//配置数据库用户名
    		dataSource.setUsername(USER);
    		//配置数据库用户密码
    		dataSource.setPassword(PASSWORD);
    		//记载驱动信息
    		dataSource.setDriverClassName(DRIVER);
    		//设置初始化连接大小
    		dataSource.setInitialSize(10);
    		//设置最大连接数
    		dataSource.setMaxActive(20);
    		//设置连接最大等待时间
    		dataSource.setMaxWait(3000);
    	}
    	
    	/**
    	 * 和数据库建立连接
    	 * @return 
    	 */
    	public static Connection getConnection() {
    		try {
    			return dataSource.getConnection();
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    	
    	/**
    	 * 关闭连接,调用这个close方法,是将连接回收到连接池中
    	 * @param conn 连接对象
    	 */
    	public static void close(Connection conn) {
    		if (conn!=null) {
    			try {
    				//将连接回收到连接池中
    				conn.close();
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	
    }
    
    展开全文
  • MVC 设计模式

    2019-10-06 12:10:42
    MVC 设计模式:通用的软件编程思想,在MVC设计模式中人为,任何软件都可以分为:控制程序流转的控制器(Controler)、封装数据处理数据的模型(Model)、负责展示数据的试图(view)三部分组成。并且在MVC设计思想中...

      MVC 设计模式:通用的软件编程思想,在MVC设计模式中人为,任何软件都可以分为:控制程序流转的控制器(Controler)、封装数据处理数据的模型(Model)、负责展示数据的试图(view)三部分组成。并且在MVC设计思想中要求一个符合MVC设计思想的软件应该保证上面这三个部分相互独立,互不干扰,每一个部分只负责自己擅长的部分。如果某一个模块发生变化,应该尽量做到不影响其他两个模块。这样做的好处是,软件的结构会变得更加的清溪,可读性强,有利于后期的扩展和维护,并且代码可以实现服用。

    转载于:https://www.cnblogs.com/gxlaqj/p/11416487.html

    展开全文
  • mvc设计模式

    2019-05-03 12:45:25
    今天重新学习了mvc设计模式 首先是JavaBean的规范:JavaBean就是实体类,但是必须满足所有属性私有,并且必须要set 和 get 方法。 这个类常常用来充当MVC中的M,代表业务实体模型。 ...

    今天重新学习了mvc设计模式
    首先是JavaBean的规范:JavaBean就是实体类,但是必须满足所有属性私有,并且必须要set 和 get 方法,必须有无参构造函数。
    这个类常常用来充当MVC中的M,代表业务实体模型。
    V代表view ,使用JSP,负责将已有的数据展示给用户看,无论什么数据,只负责展示,不负责流程
    C代表Controller ,使用 servlet ,负责接受请求,对数据进行增删改查,核心业务计算,控制程序流程。
    这就是MVC的设计理念,各个模块拆的很碎,方便开发。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,545
精华内容 9,818
关键字:

mvc设计模式