02-2 MVC

javaEE的设计模式


历史沿革:
 1. model1(jsp + javaBean)

jsp承担了给用户显示和处理内部逻辑的任务,不安全,也不利于维护

 2. model2 -> MVC(今天的主题)
    Servlet + jsp + javaBean

关于model1和model2,这篇文章博主写的很详细:https://www.cnblogs.com/wzjhoutai/p/6829457.html

MVC


   mvc是 一套设计模式, 里面主要是装饰模式

    M - Model 模型 : javabean -> 业务模型 / 数据模型
    V - View  视图 : jsp -> 负责单纯的页面显示
    C - Controller 控制器 Servlet -> 处理用户请求 / 获取数据 / 调用业务模型, 拿到数据模型 / 传递数据 / 指定用哪个视图显示

MVC和三层架构的关系?
    没啥关系

    三层架构: web层 + service层 + dao层

    MVC 发生在web层

mvc小项目实战:

实现如图所示购物网站

要求如下:

1.mvc设计模式

2.有分页效果

3.有商品详细信息页

商品详细信息页:

根据mvc设计模式思想,得出以下程序流程图

设计的分页效果流程图

分页效果的主要思想是建立一个泛型类PageBean,用于存放任何类型的商品信息以及在数据库中的记录数等

package com.wowowo.bean;

import java.util.List;

public class PageBean<T> {
	// 存放当前页数
	private int pageNum;
	// 存放每页最大记录数
	private int pageSize;
	// 存放从哪一条记录开始读取,用于查询语句limit中
	private int pageStart;
	// 存放记录总数,用于末页按钮
	private int pageMaxNum;
	// 存放最大页数,用于末页按钮
	private int pageMaxSize;
	private List<T> data;

	public PageBean(int pageNum, int pageSize, int pageMaxNum) {
		super();
		// 构造方法传三个成员属性,其余2个成员属性通过计算得出
		this.pageNum = pageNum;
		this.pageSize = pageSize;
		this.pageMaxNum = pageMaxNum;
		// 最大页数通过记录总数加上每页记录-1除以每页记录获得
		// 1.每页5条 11条:3页=(15+5-1)/5; 15条:3页=(11+5-1)/5
		pageMaxSize = (pageMaxNum + pageSize - 1) / pageSize;
		
		// 另一种计算最大页数方法
		// 先整除
		// pageMaxSize=pageMaxNum/pageSize;
		// 有余数就加1
		// if(pageMaxNum%pageSize!=0){
		// pageMaxSize++;
		// }

		/// 计算在数据库中执行查询语句时的初始位置
		pageStart = (pageNum - 1) * pageSize;

	}
//get, set,tostring方法略



}

用户访问首页,默认首页(localhost:8080/my1023hw)为index.jsp,因为只写了index.jsp(这个在web.xml配置中)

原因:

<welcome-file-list>用于指定应用的首页
里面可以指定多个文件,应用服务器会按从上到下的顺序搜索,如果找到就了进入该页面,如果都遍历完了还没找到就会返回404错误代码给浏览器。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>my1023hw</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

index.jsp(首页)

用户访问首页,它会请求转发到goodservlet(goodservlet设置了注解,和它相映射的url为/goods)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%-- 很重要:这个是jsp请求转发,给后端看的,不用加web项目名 --%>
<jsp:forward page="/goods"></jsp:forward>

</body>
</html>

goodsServlet(首页):

根据传入的当前页数和最大页数,调用service层和dao层方法查询记录并返回pagebean

package com.wowowo.web;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
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 org.eclipse.jdt.internal.compiler.parser.ParserBasicInformation;

import com.wowowo.bean.PageBean;
import com.wowowo.bean.Product;
import com.wowowo.service.ProductService;
import com.wowowo.service.impl.ProductServiceImpl;

@WebServlet("/goods")
public class GoodsServlet extends HttpServlet {

	// 依赖于业务逻辑层
	private ProductService ps = new ProductServiceImpl();

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 获取用户上传的pageNum和pageSize
		int pageNum = 1;
        //pageNum放在了url中,get方法获取
		String s_pageNum = request.getParameter("pageNum");
		if (s_pageNum != null) {
			pageNum = Integer.parseInt(s_pageNum);
		}

		int pageSize = 5;
        //pageSize放在了url中,get方法获取
		String s_pageSize = request.getParameter("pageSize");
		if (s_pageSize != null) {
			pageSize = Integer.parseInt(s_pageSize);
		}

		// 调用业务模型 获取数据模型
		PageBean<Product> pageBean = ps.queryAll(pageNum, pageSize);

		// 放到request域中
		request.setAttribute("pageBean", pageBean);

		// 转发到jsp页面
		request.getRequestDispatcher("/main.jsp").forward(request, response);
	}

}

service层(参考架构基础):

package com.wowowo.service.impl;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.wowowo.bean.PageBean;
import com.wowowo.bean.Product;
import com.wowowo.dao.ProductDao;
import com.wowowo.dao.impl.ProductDaoImpl;
import com.wowowo.database.ConnectionFactory;
import com.wowowo.service.ProductService;

public class ProductServiceImpl implements ProductService {

	private ProductDao pd = new ProductDaoImpl();

	@Override
	public PageBean<Product> queryAll(int pageNum, int pageSize) {
		Connection conn = null;
		List<Product> list = new ArrayList<>();
		try {
			conn = ConnectionFactory.getConnection();
			// 查询获得记录数
			int count = pd.queryCount(conn);
			// 构造pageBean对象
			PageBean<Product> pageBean = new PageBean<Product>(pageNum, pageSize, count);
			//调用dao层方法查询相关记录,不返回值,在方法里面对pageBean修改
			//传引用赋值和传值赋值的区别建议再看看
			pd.queryAll(conn, pageBean);
			return pageBean;
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {

				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

		}
		return null;
	}

	// 这个方法用于商品详情页面
	@Override
	public Product queryById(int uid) {

		Connection conn = null;
		List<Product> list = new ArrayList<>();
		try {
			conn = ConnectionFactory.getConnection();
			return pd.queryById(conn, uid);
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			if (conn != null) {

				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

		}
		return null;
	}

}

dao层用于和数据库交互(参考架构基础);

package com.wowowo.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.wowowo.bean.PageBean;
import com.wowowo.bean.Product;
import com.wowowo.dao.ProductDao;
import com.wowowo.database.ConnectionFactory;

public class ProductDaoImpl implements ProductDao {

	// 查记录总数
	@Override
	public int queryCount(Connection conn) throws SQLException {

		String sql = "select count(*)from product";
		PreparedStatement ps = conn.prepareStatement(sql);
		ResultSet rs = ps.executeQuery();
		if (rs.next()) {

			return rs.getInt(1);
		}
		return 0;

	}

	// 根据这一页的的初始记录位置,和每页显示数量查找相关记录并组装成list赋值给pageBean,不用返回
	@Override
	public void queryAll(Connection conn, PageBean<Product> pageBean) throws SQLException {

		List<Product> list = new ArrayList<>();
		String sql = "select *from product limit ?,?";
		PreparedStatement ps = conn.prepareStatement(sql);
		ps.setInt(1, pageBean.getPageStart());
		ps.setInt(2, pageBean.getPageSize());

		ResultSet rs = ps.executeQuery();
		while (rs.next()) {
			Product product = new Product();
			product.setProdId(rs.getInt("prodId"));
			product.setProdName(rs.getString("prodName"));
			product.setProdImage(rs.getString("prodImage"));
			product.setProdPrice(rs.getDouble("prodPrice"));
			product.setProdAmount(rs.getInt("prodAmount"));
			list.add(product);
		}
		pageBean.setData(list);
	}

	// 通过id查找商品,用于显示商品详情
	@Override
	public Product queryById(Connection conn, int uid) throws SQLException {

		String sql = "select *from product where prodid =?";
		PreparedStatement ps = conn.prepareStatement(sql);
		ps.setInt(1, uid);

		ResultSet rs = ps.executeQuery();
		if (rs.next()) {
			Product product = new Product();
			product.setProdId(rs.getInt("prodId"));
			product.setProdName(rs.getString("prodName"));
			product.setProdImage(rs.getString("prodImage"));
			product.setProdPrice(rs.getDouble("prodPrice"));
			product.setProdAmount(rs.getInt("prodAmount"));
			return product;
		}
		return null;

	}
}

对我而言,难点在于jsp页面,毕竟刚学

首页(main)的jsp(view层)

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@page import="com.wowowo.bean.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link
	href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
	rel="stylesheet">
<script
	src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<script
	src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<style type="text/css">
.prod {
	border: 1px solid black;
	width: 230px;
}

.prod_price {
	float: right;
}
</style>
</head>
<body>

	<h1 class="text-center">欢迎访问服装商城</h1>
	<div class="container">

		<%
			//request域对象里拿到servlet传过来的数据模型,强转,拿出记录list 
			PageBean<Product> pageBean = (PageBean<Product>) request.getAttribute("pageBean");
			//拿出商品list,遍历输出每一条记录 
			List<Product> list = pageBean.getData();

			for (int i = 0; i < list.size(); i++) {
		%>
		<div class="prod col-md-3">
			<div>
<%-- a标签的属性href属性用于指定超链接目标的URL,在url尾部添加?uid=商品id跳转到详细信息servlet --%>
				<a href="/my1023hw/single?uid=<%=list.get(i).getProdId()%>"><img
<%-- 图片路径通过jsp脚本实现拼接 --%>
					src="images/<%=list.get(i).getProdImage()%>" /></a>
			</div>
			<div>
				<%
					//商品名,也可以用脚本表达式 <%==list.get(i).getProdName()%》
						out.write(list.get(i).getProdName());
				%>
				<span class="prod_price">价格:<%
					//商品价格,也可以用脚本表达式 <%==list.get(i).getProdName()%》
				
					out.write(String.valueOf(list.get(i).getProdPrice())); %>
				</span>
			</div>
		</div>

		<%
			}
		%>
		<%--  循环结束 --%>
	</div>
	<div style="text-align: center;">
		<%--a标签的 href属性用于指定超链接目标的 URL,通过在后面添加?k-v&k-v在servlet的get方式能获取到参数--%>
		<%--  首页为第一页,url里输入首页和点击首页的效果一致,每页5条记录 --%>
		<a href="goods?pageNum=1&pageSize=5" class="btn btn-danger">首页</a>
		<%--  上一页为当前页-1,前提是当前页不是第一页,采用三目运算符实现,每页5条记录 --%>
		<a
			href="goods?pageNum=<%=pageBean.getPageNum() <= 1 ? 1 : pageBean.getPageNum() - 1%>&pageSize=5"
			class="btn btn-danger">上一页</a>
		<%--  下一页为当前页+1,前提是当前页不是末页,采用三目运算符实现,每页5条记录 --%>
		<a
			href="goods?pageNum=<%=pageBean.getPageNum() >= pageBean.getPageMaxSize() ? pageBean.getPageNum()
					: pageBean.getPageNum() + 1%>&pageSize=5"
			class="btn btn-danger">下一页</a>
		<%--  末页为在pagebean的构造方法中有计算,只需取出即可,每页5条记录 --%>
		<a href="goods?pageNum=<%=pageBean.getPageMaxSize()%>&pageSize=5"
			class="btn btn-danger">末页</a>
	</div>

</body>
</html>

详细信息页面的设计:

在首页的商品图片设置a标签(商品id放在url中)跳转到singleservlet(get方式获取url中的参数商品id并做业务处理,返回一个数据模型放到request)转发到jsp显示

singleservlet(controller层)

package com.wowowo.web;

import java.io.IOException;

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.wowowo.bean.Product;
import com.wowowo.service.ProductService;
import com.wowowo.service.impl.ProductServiceImpl;

/**
 * Servlet implementation class SingleServlet
 */
@WebServlet("/single")
public class SingleServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private ProductService ps=new ProductServiceImpl();

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //get方式获取的商品id
	int uid = Integer.parseInt(request.getParameter("uid"));
//传入逻辑模型
	Product p=ps.queryById(uid);
	//request添加数据模型
	request.setAttribute("product", p);
//跳转到single.jsp(view层)
	request.getRequestDispatcher("/single.jsp").forward(request, response);;
	
	}

}

singleservlet跳转到的jsp(view层)

显示单一商品信息

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@page import="com.wowowo.bean.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style type="text/css">
.single {
	width: 500px;
	text-align: center;
	margin: auto;
}

.detail {
	height: 195px;
	float: left;
}
</style>

</head>
<body>
	<%
		Product p = (Product) request.getAttribute("product");
	%>

	<div class="single">
		<div class="detail">
			<img src="/my1023hw/images/<%=p.getProdImage()%>" />
		</div>
		<div class="detail">
			商品名称:<%=p.getProdName()%><br /> 商品单价:<%=p.getProdPrice()%><br />
			商品库存:<%=p.getProdAmount()%><br /> <input type="text" value="1">
			<br /> <input type="button" value="添加到购物车"> <input
				type="button" value="立即购买">
		</div>

	</div>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_36194262/article/details/83351692
MVC
今日推荐