搭建 MVC 架构,实现数据的增删改查
1.前言2.搭建MVC架构MVC概念JavaBean数据库相关配置lib中的jar包project目录
3.各JSP页面、URI、Servlet的关系4.前后端如何实现数据传递后端传给前端前端传给后端
5.代码JSPmainPage.jspshowAllBestsellers.jspadd.jspdelete.jspupdate.jsp
beandaoservicewebFilterSelectServletAddServletDeleteServletUpdateServlet
6.测试
1.前言
之前学习了MVC 设计模式、HTML、JSP(EL表达式、JSTL)、JDBC、MySql、Servlet、Filter等,在这个例子中加以巩固练习一下。虽然是一个简单的demo,但由于是初学Java web,写完了代码之后,觉得有必要整理一下思路并记录下来。值得记录的有两个方面:1.如何搭建MVC架构 2.各JSP页面是怎么通过URI、Servlet关联起来的 3.前后端怎么进行数据传递?后端查询得到的数据是怎么传给前端的,用户在前端提交的表单信息怎么传给后端。
该例子实现了数据库中表的增删改查,具体的效果请见测试一节。
2.搭建MVC架构
MVC概念
MVC:Model模型,View视图,Controller控制器
Model模型:负责操作数据库(dao包,bean包) View视图:给用户呈现的页面,html、JSP页面 Controller控制器:负责前后端的交互(web包,service包)
JavaBean
分为2类(bean和dao), 封装业务逻辑的JavaBean(即dao) 封装数据的JavaBean(即bean,又叫:实体类):对应于数据库中的一张表,即数据库中有个Student表,项目中就有个Student.java类。
表名=类名,列名=属性名public修饰的类,提供public 无参构造方法所有属性 都是private提供getter和setter方法
数据库相关配置
为了能够正常使用JDBC操作数据,以及使用Druid连接池,需要做以下工作: 1.创建lib文件夹,在idea里配置其为project library(过程略) 2.在lib里放有关数据库的jar包(Druid的jar包,JDBC的jar包) 3. src文件夹里放druid.properties文件,别放错地方了,里边的配置要改一下(数据库的名字) 4. 创建util包,util里放DruidUtil.java文件,这是一个工具类,方便使用连接池 5. dao的impl实现类要继承DruidUtil类
lib中的jar包
从上到下,各Jar包的作用依次为:
DruidDruidJSTLJDBCJSTL
project目录
创建bean包、dao包、service包、web包,这4个包必须创建。util包放工具类,可要可不要。 对于dao和service而言,都采用接口+实现类的模式,impl包里放实现类。
src文件夹:
3.各JSP页面、URI、Servlet的关系
将JSP页面、URI、Servlet的关系绘制成下图,清晰明了。在写该例子的代码时,有时候会感到思维混乱,页面被各URI和、Servlet关联着,跳过来跳过去的,在写代码的同时,画出下图可能有助于理清思路。
蓝色方框:JSP页面 绿色框:Servlet 红色字:URI 白色框:form表单 下划线:html中的a标签(链接)
注意:本图省略了Filter,每个URI都会先经过Filter。Filter的作用:1.设置编码方式 2.判断用户填写的form是否合乎规范。
4.前后端如何实现数据传递
后端传给前端
后端从数据库里查询出来的数据需要传给前端。
后端: 在SelectServlet.java中,调用Service方法进行数据查询,查询出来的所有产品信息存储在List中,将List存入request域。
req
.setAttribute("bestsellers",bsList
);
前端: 在showAllBestsellers.jsp中,通过EL表达式,将存在request域里的数据取出来。
<c
:forEach items
="${bestsellers}" var
="bs">
前端传给后端
用户在前端填写的form表单里的信息,需要传递给后端,后端利用这些信息来做增、删、改。
前端: 用户点击表单的提交按钮,表单中的元素就会自动存储在request域,以键值对的形式,键:元素的name属性,值:用户填写的内容。
后端: 从request域里取数据,通过request对象的getParameter方法,传入参数:键。
String name
= req
.getParameter("name");
5.代码
JSP
mainPage.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页
</title>
</head>
<body>
<h1 style="color: coral">Nana Cosmetics Bestsellers
</h1>
<h2>Menu:
</h2>
<h2><a href="/toSelect">查看所有热销产品
</a></h2>
<h2><a href="add.jsp">添加产品信息
</a></h2>
<h2><a href="delete.jsp">删除产品信息
</a></h2>
<h2><a href="update.jsp">修改产品信息
</a></h2>
</body>
</html>
showAllBestsellers.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>所有热销产品
</title>
</head>
<body>
<h1 style="color: coral">所有热销产品:
</h1>
<table border="1" cellspacing="0" width="500px">
<tr>
<td>产品名称
</td>
<td>价格
</td>
</tr>
<%--使用JSTL和EL表达式来获取存入request域里的数据,是个List,存有所有产品的信息--%>
<%--bs就是获取的单个的Bestseller对象,通过对象.属性名获取属性值--%>
<c:forEach items="${bestsellers}" var="bs">
<tr>
<%--
<td>${bs.id}
</td>--%>
<td>${bs.brand}${bs.name}
</td><%--牌子和产品名连在一起,作为产品名称--%>
<td>${bs.price}
</td>
</tr>
</c:forEach>
</table>
<br><h4><a href="mainPage.jsp">点击返回主页
</a></h4>
</body>
</html>
add.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>添加产品信息
</title>
</head>
<body>
<h2>请输入需要添加的产品信息:
</h2>
<form action="/toAdd" method="get">
产品名:
<input type="text" name="name"><br><br>
品牌:
<input type="text" name="brand"><br><br>
价格:
<input type="text" name="price"><br><br>
<input type="submit" value="提交">
</form>
<br><h4><a href="mainPage.jsp">点击返回主页
</a></h4>
</body>
</html>
delete.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>删除产品信息
</title>
</head>
<body>
<h2>请输入需要删除的产品信息:
</h2>
<form action="/toDelete" method="get">
产品名:
<input type="text" name="name"><br><br>
品牌:
<input type="text" name="brand"><br><br>
价格:
<input type="text" name="price"><br><br>
<input type="submit" value="提交">
</form>
<br><h4><a href="mainPage.jsp">点击返回主页
</a></h4>
</body>
</html>
update.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改产品信息
</title>
</head>
<body>
<form action="/toUpdate" method="get">
<h2>请输入修改前的产品信息,用于检索:
</h2>
产品名:
<input type="text" name="oldName"><br><br>
品牌:
<input type="text" name="oldBrand"><br><br>
价格:
<input type="text" name="oldPrice"><br><br>
<h2>请输入新的产品信息:
</h2>
产品名:
<input type="text" name="newName"><br><br>
品牌:
<input type="text" name="newBrand"><br><br>
价格:
<input type="text" name="newPrice"><br><br>
<input type="submit" value="提交">
</form>
<br><h4><a href="mainPage.jsp">点击返回主页
</a></h4>
</body>
</html>
bean
package com
.czn
.bean
;
public class Bestseller {
private Integer id
= null
;
private String name
;
private String brand
;
private Integer price
;
public Bestseller() {
}
public Bestseller(String name
, String brand
, int price
) {
this.name
= name
;
this.brand
= brand
;
this.price
= price
;
}
public String
getName() {
return name
;
}
public void setName(String name
) {
this.name
= name
;
}
public String
getBrand() {
return brand
;
}
public void setBrand(String brand
) {
this.brand
= brand
;
}
public Integer
getPrice() {
return price
;
}
public void setPrice(Integer price
) {
this.price
= price
;
}
public Integer
getId() {
return id
;
}
public void setId(Integer id
) {
this.id
= id
;
}
}
dao
接口和实现类
package com
.czn
.dao
;
import com
.czn
.bean
.Bestseller
;
import java
.util
.List
;
public interface BestsellerDao {
public List
<Bestseller> selectAll();
public boolean add(Bestseller bs
);
public boolean update(Bestseller oldBS
,Bestseller newBS
);
public boolean delete(Bestseller bs
);
}
package com
.czn
.dao
.impl
;
import com
.czn
.bean
.Bestseller
;
import com
.czn
.dao
.BestsellerDao
;
import com
.czn
.util
.DruidUtil
;
import java
.sql
.Connection
;
import java
.sql
.PreparedStatement
;
import java
.sql
.ResultSet
;
import java
.sql
.SQLException
;
import java
.util
.ArrayList
;
import java
.util
.List
;
public class BestsellerDaoImpl extends DruidUtil implements BestsellerDao {
@Override
public List
<Bestseller> selectAll() {
List list
= new ArrayList();
Connection conn
= null
;
PreparedStatement state
= null
;
ResultSet rs
= null
;
try{
conn
= getConnection();
String sql
= "select * from bestsellers";
state
= conn
.prepareStatement(sql
);
rs
= state
.executeQuery();
while(rs
.next()){
Bestseller bs
= new Bestseller();
bs
.setId(rs
.getInt("id"));
bs
.setBrand(rs
.getString("brand"));
bs
.setName(rs
.getString("name"));
bs
.setPrice(rs
.getInt("price"));
list
.add(bs
);
}
}catch (SQLException e
){
System
.out
.println("从数据库中取数据时出错。");
e
.printStackTrace();
}finally {
close(conn
,state
,rs
);
}
return list
;
}
@Override
public boolean add(Bestseller bs
) {
Connection conn
= null
;
PreparedStatement state
= null
;
int rowNumAffected
= 0;
try{
conn
= getConnection();
String sql
= "insert into bestsellers(name,brand,price) value(?,?,?)";
state
= conn
.prepareStatement(sql
);
state
.setString(1,bs
.getName());
state
.setString(2,bs
.getBrand());
state
.setInt(3,bs
.getPrice());
rowNumAffected
= state
.executeUpdate();
}catch (SQLException e
){
System
.out
.println("从数据库中取数据时出错。");
e
.printStackTrace();
}finally {
close(conn
,state
,null
);
}
if(rowNumAffected
> 0){
return true;
}
return false;
}
@Override
public boolean update(Bestseller oldBS
,Bestseller newBS
) {
Connection conn
= null
;
PreparedStatement state
= null
;
int rowNumAffected
= 0;
try{
conn
= getConnection();
String sql
= "update bestsellers set name=?,brand=?,price=? where name=? and brand=? and price=?";
state
= conn
.prepareStatement(sql
);
state
.setString(1,newBS
.getName());
state
.setString(2,newBS
.getBrand());
state
.setInt(3,newBS
.getPrice());
state
.setString(4,oldBS
.getName());
state
.setString(5,oldBS
.getBrand());
state
.setInt(6,oldBS
.getPrice());
rowNumAffected
= state
.executeUpdate();
System
.out
.println("更新数据库的数据时,影响表的行数:"+rowNumAffected
);
}catch (SQLException e
){
System
.out
.println("在数据库中更新数据时出错。");
e
.printStackTrace();
}finally {
close(conn
,state
,null
);
}
if(rowNumAffected
> 0){
return true;
}
return false;
}
@Override
public boolean delete(Bestseller bs
) {
Connection conn
= null
;
PreparedStatement state
= null
;
int rowNumAffected
= 0;
try{
conn
= getConnection();
String sql
= "delete from bestsellers where name=? and brand=? and price=?";
state
= conn
.prepareStatement(sql
);
state
.setString(1,bs
.getName());
state
.setString(2,bs
.getBrand());
state
.setInt(3,bs
.getPrice());
rowNumAffected
= state
.executeUpdate();
System
.out
.println("删除数据库的数据时,影响表的行数:"+rowNumAffected
);
}catch (SQLException e
){
System
.out
.println("在数据库中删除数据时出错。");
e
.printStackTrace();
}finally {
close(conn
,state
,null
);
}
if(rowNumAffected
> 0){
return true;
}
return false;
}
}
service
接口和实现类
package com
.czn
.service
;
import com
.czn
.bean
.Bestseller
;
import java
.util
.List
;
public interface BestsellerService {
public List
<Bestseller> selectAll();
public boolean add(Bestseller bs
);
public boolean update(Bestseller oldBS
,Bestseller newBS
);
public boolean delete(Bestseller bs
);
}
import com
.czn
.service
.BestsellerService
;
import java
.util
.List
;
public class BestsellerServiceImpl implements BestsellerService {
private BestsellerDao dao
= new BestsellerDaoImpl();
@Override
public List
<Bestseller> selectAll() {
return dao
.selectAll();
}
@Override
public boolean add(Bestseller bs
) {
return dao
.add(bs
);
}
@Override
public boolean update(Bestseller oldBS
,Bestseller newBS
) {
return dao
.update(oldBS
,newBS
);
}
@Override
public boolean delete(Bestseller bs
) {
return dao
.delete(bs
);
}
}
web
Filter
package com
.czn
.web
.filters
;
import javax
.servlet
.*
;
import javax
.servlet
.http
.HttpServletRequest
;
import javax
.servlet
.http
.HttpServletResponse
;
import java
.io
.IOException
;
import java
.io
.PrintWriter
;
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig
) throws ServletException
{
System
.out
.println("初始化过滤器EncodingFilter");
}
@Override
public void destroy() {
System
.out
.println("销毁过滤器EncodingFilter");
}
@Override
public void doFilter(ServletRequest servletRequest
, ServletResponse servletResponse
, FilterChain filterChain
) throws IOException
, ServletException
{
System
.out
.println("开始执行过滤器EncodingFilter");
HttpServletRequest req
= (HttpServletRequest
)servletRequest
;
HttpServletResponse resp
= (HttpServletResponse
)servletResponse
;
req
.setCharacterEncoding("utf-8");
resp
.setCharacterEncoding("utf-8");
resp
.setContentType("text/html;charset=utf-8");
String requestURI
= req
.getRequestURI();
System
.out
.println("requestURI="+requestURI
);
if(requestURI
.endsWith("/toDelete")||requestURI
.endsWith("/toAdd")){
String price
= req
.getParameter("price");
String name
= req
.getParameter("name");
String brand
= req
.getParameter("brand");
try {
Integer
.parseInt(price
);
}catch (NumberFormatException e
){
System
.out
.println("用户输入的价格不规范。");
PrintWriter out
= resp
.getWriter();
out
.print("<script language='javascript'>alert('您的输入不规范。');" +
"window.location.href='mainPage.jsp';</script>");
}
if(Integer
.parseInt(price
)<0||name
== null
||brand
== null
||price
== null
||name
.length()==0||brand
.length()==0||price
.length()==0){
System
.out
.println("用户输入不规范。");
PrintWriter out
= resp
.getWriter();
out
.print("<script language='javascript'>alert('您的输入不规范。');" +
"window.location.href='mainPage.jsp';</script>");
}else{
filterChain
.doFilter(req
,resp
);
}
}else if (requestURI
.endsWith("/toUpdate")){
String oldPrice
= req
.getParameter("oldPrice");
String newPrice
= req
.getParameter("newPrice");
String oldName
= req
.getParameter("oldName");
String newName
= req
.getParameter("newName");
String oldBrand
=req
.getParameter("oldBrand");
String newBrand
= req
.getParameter("newBrand");
try {
Integer
.parseInt(oldPrice
);
Integer
.parseInt(newPrice
);
}catch (NumberFormatException e
){
System
.out
.println("用户输入的价格不规范。");
PrintWriter out
= resp
.getWriter();
out
.print("<script language='javascript'>alert('您的输入不规范。');" +
"window.location.href='mainPage.jsp';</script>");
}
if(oldPrice
== null
||Integer
.parseInt(oldPrice
)<0||oldName
== null
||oldBrand
== null
||newPrice
== null
||Integer
.parseInt(newPrice
)<0||newName
== null
||newBrand
== null
||oldPrice
.length()==0||oldName
.length()==0||oldBrand
.length()==0
||newPrice
.length()==0||newName
.length()==0|| newBrand
.length()==0){
System
.out
.println("用户输入不规范。");
PrintWriter out
= resp
.getWriter();
out
.print("<script language='javascript'>alert('您的输入不规范。');" +
"window.location.href='mainPage.jsp';</script>");
}else{
filterChain
.doFilter(req
,resp
);
}
}else {
filterChain
.doFilter(req
,resp
);
}
System
.out
.println("结束执行过滤器EncodingFilter");
}
}
SelectServlet
package com
.czn
.web
.servlets
;
import com
.czn
.bean
.Bestseller
;
import com
.czn
.service
.BestsellerService
;
import com
.czn
.service
.impl
.BestsellerServiceImpl
;
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 java
.io
.IOException
;
import java
.util
.List
;
@WebServlet(value
= "/toSelect")
public class SelectServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
BestsellerService bsService
= new BestsellerServiceImpl();
List
<Bestseller> bsList
= bsService
.selectAll();
req
.setAttribute("bestsellers",bsList
);
req
.getRequestDispatcher("showAllBestsellers.jsp").forward(req
,resp
);
}
}
AddServlet
package com
.czn
.web
.servlets
;
import com
.czn
.bean
.Bestseller
;
import com
.czn
.service
.BestsellerService
;
import com
.czn
.service
.impl
.BestsellerServiceImpl
;
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 java
.io
.IOException
;
@WebServlet(value
= "/toAdd")
public class AddServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
String name
= req
.getParameter("name");
String brand
= req
.getParameter("brand");
String price
= req
.getParameter("price");
Bestseller bs
= new Bestseller();
bs
.setName(name
);
bs
.setBrand(brand
);
bs
.setPrice(Integer
.parseInt(price
));
BestsellerService bsService
= new BestsellerServiceImpl();
boolean result
= bsService
.add(bs
);
req
.getRequestDispatcher("/toSelect").forward(req
,resp
);
}
}
DeleteServlet
package com
.czn
.web
.servlets
;
import com
.czn
.bean
.Bestseller
;
import com
.czn
.service
.BestsellerService
;
import com
.czn
.service
.impl
.BestsellerServiceImpl
;
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 java
.io
.IOException
;
import java
.io
.PrintWriter
;
@WebServlet(value
= "/toDelete")
public class DeleteServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
String name
= req
.getParameter("name");
String brand
= req
.getParameter("brand");
String price
= req
.getParameter("price");
Bestseller bs
= new Bestseller();
bs
.setName(name
);
bs
.setBrand(brand
);
bs
.setPrice(Integer
.parseInt(price
));
BestsellerService bsService
= new BestsellerServiceImpl();
boolean result
= bsService
.delete(bs
);
System
.out
.println("result:"+result
);
if(result
== false){
PrintWriter out
= resp
.getWriter();
out
.print("<script language='javascript'>alert('删除产品信息失败。可能的原因:数据库中不存在该产品。');" +
"window.location.href='delete.jsp';</script>");
}else{
req
.getRequestDispatcher("/toSelect").forward(req
,resp
);
}
}
}
UpdateServlet
package com
.czn
.web
.servlets
;
import com
.czn
.bean
.Bestseller
;
import com
.czn
.service
.BestsellerService
;
import com
.czn
.service
.impl
.BestsellerServiceImpl
;
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 java
.io
.IOException
;
import java
.io
.PrintWriter
;
@WebServlet(value
= "/toUpdate")
public class UpdateServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req
, HttpServletResponse resp
) throws ServletException
, IOException
{
String oldName
= req
.getParameter("oldName");
String oldBrand
= req
.getParameter("oldBrand");
String oldPrice
= req
.getParameter("oldPrice");
String newName
= req
.getParameter("newName");
String newBrand
= req
.getParameter("newBrand");
String newPrice
= req
.getParameter("newPrice");
Bestseller oldBS
= new Bestseller();
oldBS
.setName(oldName
);
oldBS
.setBrand(oldBrand
);
oldBS
.setPrice(Integer
.parseInt(oldPrice
));
Bestseller newBS
= new Bestseller();
newBS
.setName(newName
);
newBS
.setBrand(newBrand
);
newBS
.setPrice(Integer
.parseInt(newPrice
));
BestsellerService bsService
= new BestsellerServiceImpl();
boolean result
= bsService
.update(oldBS
,newBS
);
System
.out
.println("result:"+result
);
if(result
== false){
PrintWriter out
= resp
.getWriter();
out
.print("<script language='javascript'>alert('修改产品信息失败。可能的原因:数据库中不存在该产品。');" +
"window.location.href='update.jsp';</script>");
}else{
req
.getRequestDispatcher("/toSelect").forward(req
,resp
);
}
}
}
6.测试
测试1:正常流程的增删改查
测试2:filter过滤掉用户不规范的输入
测试3:删除或更新时,数据库中不存在该数据