JavaWeb:基于MVC设计模式的一个小案例(一)
(未经允许,请勿转载,谢谢。)
本案例的处理过程:
客户端发送一个请求给服务器,服务器把这个请求给Servlet,Servlet 获取请求信息,根据请求信息的情况去调用 model (在这里是一个普通的 Java 类),然后把返回结果给 Servlet ,然后Servlet 根据返回结果 转向一个 JSP,JSP是用来呈现数据的 (这里用的是Java 代码),生成一个HTML 页面显给客户。
使用到的技术:
MVC 设计模式:JSP、Servlet、POJO
数据库:MySQL
连接数据库使用 c3p0 数据库连接池
JDBC 工具使用 DBUtils
页面上的提示操作使用 jQuery
具体实现步骤:
1、建立数据表
代码:
Create table customer(
id int(10) primary key auto_increment,
name varchar(30) not null unique,
address varchar(30),
phone varchar(30)
);
为 name 字段添加唯一约束:
alter table customers add constraint name_uk unique(name);
2、底层实现
①、加入c3p0 数据源:导入两个 jar 包(c3p0 和 数据库驱动),在 src 下新建配置文件:c3p0-config.xml ,修改一下要有连接数据库的基本信息(driverClass、jdbcUrl、user、password)。
c3p0-config.xml 代码:
<?xml version="1.0" encoding="UTF-8" ?>
<c3p0-config> <named-config name="mvcapp"> <!--指定连接数据源的基本信息 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///javawebdb</property>
<property name="user">root</property>
<property name="password">root</property> <!-- 若数据库中连接不足时,一次性向数据库服务器申请多少个连接-->
<property name="acquireIncrement">5</property>
<!-- 初始化数据库连接池时连接的数量-->
<property name="initialPoolSize">10</property>
<!-- 数据库连接池中的最小的数据库连接数-->
<property name="minPoolSize">10</property>
<!-- 数据库连接池中的最大的数据库连接数-->
<property name="maxPoolSize">50</property> <!-- c3p0 数据库连接池可以维护的 Statement 的个数-->
<property name="maxStatements">20</property>
<!-- 每个连接同时可以使用的Statement 对象的个数-->
<property name="maxStatementsPerConnection">5</property> </named-config>
</c3p0-config>
②、编写DAO 工具类、JdbcUtils 工具类和 CustomerDao 接口(以下有具体说明和代码)
DAO 工具类:封装了基本的增删改查的方法,以供子类继承使用。当前DAO 没有事务,直接在方法中获取数据库连接。导入了DBUtils 的 jar 包,整个 DAO 采取 DBUtils 的解决方案。
实现方法:
update(封装了insert、delete、update)操作:public void update(String sql, Object...args){ }
查询 返回 T 对应的实体类的对象:public T get(String sql, Object...args){ }
查询 返回 T 对应的List :public List<T> getForList(String sql, Object...args){ }
查询 返回一个字段的值: public <E> E getForValue(String sql, Object...args){ }
DAO.java 代码:
package com.hnust.mvcapp.dao; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler; import com.hnust.mvcapp.utils.JdbcUtils; /**
* 封装了基本的增删改查的方法,以供子类继承使用。
* 当前DAO 直接在方法中获取数据库连接。
* 整个DAO 采取DBUtils 解决方案。
* @author User
*
* @param <T> 当前 DAO 处理的实体类的类型是什么
*/
public class Dao<T> { private QueryRunner queryRunner = new QueryRunner(); private Class<T> clazz; /**
* 需要确定 clazz
*/
public Dao(){
//由得到子类的 Class得到父类 带泛型的那个类型。
Type superClass = getClass().getGenericSuperclass();
//先判断是不是那个类型
if(superClass instanceof ParameterizedType){
//是的话,强转一下
ParameterizedType parameterizedType = (ParameterizedType) superClass;
//获取真正的泛型的参数
Type[] typeArgs = parameterizedType.getActualTypeArguments();
if(typeArgs != null && typeArgs.length >0){
if(typeArgs[0] instanceof Class){
clazz = (Class<T>) typeArgs[0];
}
}
}
} /**
* 查询,返回某一个字段的值
*/
public <E> E getForValue(String sql, Object...args){
Connection connection = null;
try {
connection = JdbcUtils.getConnection();
return (E) queryRunner.query(connection, sql, new ScalarHandler(), args);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}
return null;
} /**
* 查询,返回T 所对应的 List
*/
public List<T> getForList(String sql, Object...args){
Connection connection = null;
try {
connection = JdbcUtils.getConnection();
return queryRunner.query(connection, sql, new BeanListHandler<>(clazz), args);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}
return null;
} /**
* 查询,返回一个T 的实体类对象
*/
public T get(String sql, Object...args){
Connection connection = null; try {
connection = JdbcUtils.getConnection();
return queryRunner.query(connection, sql, new BeanHandler<>(clazz), args);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}
return null;
} /**
* 通用的 insert 、delete、update 方法
*/
public void update(String sql, Object...args){
Connection connection = null;
try {
connection = JdbcUtils.getConnection();
queryRunner.update(connection, sql, args);
} catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.releaseConnection(connection);
}
}
}
JdbcUtils 工具类:JDBC 操作的工具类。
实现方法:
返回数据源的一个 Connection 对象:public static Connection getConnection(){ }
释放 Connection 的连接:public static void releaseConnection(Connection connection){ }
注意:数据源的初始化一定要放在静态代码块中,数据源被创建一次就够了。写完一个可以用单元测试检验以下。
JdbcUtils.java 代码:
package com.hnust.mvcapp.utils; import java.sql.Connection;
import java.sql.SQLException; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; /**
* JDBC 操作的工具类
* @author User
*
*/
public class JdbcUtils { /**
* 释放连接
*/
public static void releaseConnection(Connection connection){ try {
if(connection != null){
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} private static DataSource dataSource = null;
static{
dataSource = new ComboPooledDataSource("mvcapp"); //传入的是 configName
}
/**
* 获取连接
* @throws SQLException
*/
public static Connection getConnection() throws SQLException{ return dataSource.getConnection();
}
}
CustomerDao 接口:
实现的方法:
模糊查询 返回满足条件的List :public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc);
查询 返回List:public List<Customer> getAll();
添加:poublic void save(Customer customer);
修改时要根据id 的查询显示:public Customer get(Inreger id);
删除(根据 id):public void delete(Integer id);
查询 和这个名字一样的 记录数(根据 name):public long getCountWithName(String name);
CustomerDao.java 代码:
package com.hnust.mvcapp.dao; import java.util.List; import com.hnuct.mvcapp.entity.Customer; public interface CustomerDao { /**
* 模糊查询 返回满足条件的List
* @param cc :封装了查询条件
* @return
*/
public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc); /**
* 查询 返回 List
*/
public List<Customer> getAll(); /**
* 增加
*/
public void save(Customer customer); /**
* 修改 更新时候的查询(根据id)显示
*/
public Customer get(Integer id); /**
* 删除
*/
public void delete(Integer id); /**
* 返回和name 相同的记录数
*/
public long getCountWithName(String name);
}
实体类 Customer:
Customer.java 代码:
package com.hnuct.mvcapp.entity; public class Customer { private Integer id;
private String name;
private String address;
private String phone;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Customer(Integer id, String name, String address, String phone) {
super();
this.id = id;
this.name = name;
this.address = address;
this.phone = phone;
}
public Customer() {
super();
} @Override
public String toString() {
return "Customers [id=" + id + ", name=" + name + ", address="
+ address + ", phone=" + phone + "]";
} }
Dao 接口的实现:
CustomerDaoJdbcImpl.java 代码:
package com.hnuct.mvcapp.dao.impl; import java.util.List; import com.hnuct.mvcapp.entity.Customer;
import com.hnust.mvcapp.dao.CriteriaCustomer;
import com.hnust.mvcapp.dao.CustomerDao;
import com.hnust.mvcapp.dao.Dao; public class CustomerDaoJdbcImpl extends Dao<Customer> implements CustomerDao{ @Override
public List<Customer> getAll() {
String sql = "select * from customer";
return getForList(sql);
} @Override
public void save(Customer customer) {
String sql = "insert into customer(name,address,phone) values (?,?,?)";
update(sql, customer.getName(), customer.getAddress(), customer.getPhone());
} @Override
public Customer get(Integer id) {
String sql = "select * from customer where id = ?";
return get(sql, id);
} @Override
public void delete(Integer id) {
String sql = "delete from customer where id = ? ";
update(sql, id);
} @Override
public long getCountWithName(String name) {
String sql = "select count(id) from customer where name = ?";
return getForValue(sql, name);
} @Override
public List<Customer> getForListWithCriteriaCustomer(CriteriaCustomer cc) {
String sql = "SELECT id,name,address,phone FROM customer WHERE name LIKE ? AND "
+ "address LIKE ? AND phone LIKE ?";
//注意:修改了 CriteriaCustomer 的 getter 方法,使其返回的字符串中有 "%%",
//若返回值为 null 则返回 "%%" ,若不为 null, 则返回 "% " + 字段本身的值 + " %"
return getForList(sql, cc.getName(), cc.getAddress(), cc.getPhone());
} }
ps:注意因为查询条件很多时候 和 实体类 并不相同,所以要做成一个单独的类,这里是 CriteriaCustomer 类,其中里面的getter 方法做了修改,是为了正确的填充占位符。
CriteriaCustomer.java 代码:
package com.hnust.mvcapp.dao; public class CriteriaCustomer { private String name;
private String address;
private String phone;
public String getName() {
if(name == null)
name = "%%";
else
name = "%" + name + "%";
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
if(address == null)
address = "%%";
else
address = "%" + address + "%";
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
if(phone == null)
phone = "%%";
else
phone = "%" + phone + "%";
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
} public CriteriaCustomer() {
super();
}
public CriteriaCustomer(String name, String address, String phone) {
super();
this.name = name;
this.address = address;
this.phone = phone;
} }
3、Servlet 的实现:获取请求信息的参数,根据请求信息调用 DAO 的对应的方法。
先写了一个 test.jsp 页面 放了三个超链接。
test.jsp 代码:
<%@ 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>
<%--
<a href="customerServlet?method=add">add</a>
<br><br>
<a href="customerServlet?method=query">query</a>
<br><br>
<a href="customerServlet?method=delete">delete</a>
--%> <a href="addCustomer.do">add</a>
<br><br>
<a href="query.do">query</a>
<br><br>
<a href="delete.do">delete</a>
<br><br> </body>
</html>
注意你的 web.xml 里的 url-pattern:<url-pattern>*.do</url-pattern>
然后 创建了CustomerServlet :去响应服务器的请求,调用对应的model,返回结果(我这里暂时实现了 模糊查询和 删除的功能)。
CustomerServlet.java 代码:
package com.hnust.mvcapp.servlet; import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.hnuct.mvcapp.dao.impl.CustomerDaoJdbcImpl;
import com.hnuct.mvcapp.entity.Customer;
import com.hnust.mvcapp.dao.CriteriaCustomer;
import com.hnust.mvcapp.dao.CustomerDao; public class CustomerServlet extends HttpServlet {
private static final long serialVersionUID = 1L; private CustomerDao customerDao = new CustomerDaoJdbcImpl(); protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { this.doPost(request, response);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException { //1、获取servletPath
String servletPath = req.getServletPath();
//System.out.println(servletPath); //得到的是 /addCustomer.do //2、去除 / 和 .do ,得到 addCustomer 这样的字符串
String methodName = servletPath.substring(1);
methodName = methodName.substring(0, methodName.length() - 3);
//System.out.println(methodName); // 得到的是 addCustomer try {
//3、利用反射,根据获取的 方法名,获取对应的方法。
Method method = getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
HttpServletResponse.class);
//4、利用反射调用对应的方法
method.invoke(this, req, resp); } catch (Exception e) {
e.printStackTrace();
//可以有一些响应
resp.sendRedirect("error.jsp");
} } private void delete(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1、获取 id
String idStr = request.getParameter("id");
int id = 0;
//为了避免输入的 id 是不 合法的。 idStr 不能转为 int 类型。若不能转,则 id 为0,无法执行任何的操作。
try {
id = Integer.parseInt(idStr);
//2、调用 CustomerDAO 的 delete 方法
customerDao.delete(id);
//3、页面的重定向
response.sendRedirect("query.do");
} catch (Exception e) {
e.printStackTrace();
}
} private void query(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1、获取模糊查询的请求参数
String name = request.getParameter("name");
String address = request.getParameter("address");
String phone = request.getParameter("phone"); //2、把请求参数封装为 CriteriaCustomer 对象
CriteriaCustomer cc = new CriteriaCustomer(name, address, phone); //3、再调用CustomerDao 的 getForListWithCriteriaCustomer() 方法
List<Customer> customers = customerDao.getForListWithCriteriaCustomer(cc); //调用CustomerDao 的 getAll() 方法 查询。
//List<Customer> customers = customerDao.getAll(); //4、把查询到的结果集放入 request 中
request.setAttribute("customers", customers);
//5、请求的转发
request.getRequestDispatcher("/index.jsp").forward(request, response); } private void addCustomer(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { System.out.println("add");
} }
4、返回结果 的 JSP 页面:获取返回结果,遍历显示。
index.jsp 代码:
<%@page import="com.hnuct.mvcapp.entity.Customer"%>
<%@page import="java.util.List"%>
<%@ 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>
<script type="text/javascript" src="Scripts/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function(){
$(".delete").click(function(){
var content = $(this).parent().parent().find("td:eq(1)").text();
var flag = confirm("确定要删除 " + content + " 的信息吗?");
return flag;
});
})
</script>
</head>
<body>
<form action="query.do" method="post">
<table>
<tr>
<td>name:</td>
<td><input type="text" name="name"/></td>
</tr>
<tr>
<td>address:</td>
<td><input type="text" name="address"/></td>
</tr>
<tr>
<td>phone:</td>
<td><input type="text" name="phone"/></td> <tr>
<td><input type="submit" value="Query"/></td>
<td><a href="">Add new Customer</a></td>
</tr>
</table>
</form>
<br><br> <%
List<Customer> customers = (List<Customer>) request.getAttribute("customers");
if(customers != null && customers.size() > 0){
%>
<hr>
<br><br>
<table border="1" cellpadding="10" cellspacing="0">
<tr>
<th>ID</th>
<th>NAME</th>
<th>ADDRESS</th>
<th>PHONE</th>
<th>UPDATE/DELETE</th>
</tr>
<% for(Customer cust : customers){ %>
<tr>
<td><%= cust.getId() %></td>
<td><%= cust.getName() %></td>
<td><%= cust.getAddress() %></td>
<td><%= cust.getPhone() %></td>
<td>
<a href="">Update</a>
<a href="delete.do?id=<%=cust.getId() %>" class="delete">Delete</a>
</td>
</tr>
<%
}
%>
</table>
<%
}
%>
</body>
</html>
最后结果:
点击query
可以实现模糊查询,和删除的功能。
这是今天的学习内容。
JavaWeb:基于MVC设计模式的一个小案例(一)的更多相关文章
- Struts2是一个基于MVC设计模式的Web应用框架
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互. Struts ...
- 基于MVC设计模式的Web应用框架:struts2的简单搭建(一)
Struts2的初步介绍 Struts2是apache项目下的一个web 框架,普遍应用于阿里巴巴.京东等互联网.政府.企业门户网站.虽然之前存在了很大的安全漏洞,在2013年让苹果.中国移动.中国联 ...
- iOS 基于MVC设计模式的基类设计
iOS 基于MVC设计模式的基类设计 https://www.jianshu.com/p/3b580ffdae00
- Python:通过一个小案例深入理解IO多路复用
通过一个小案例深入理解IO多路复用 假如我们现在有这样一个普通的需求,写一个简单的爬虫来爬取校花网的主页 import requests import time start = time.time() ...
- IT兄弟连 JavaWeb教程 MVC设计模式
MVC是Model-View-Controller的简称,即模型-视图-控制器.MVC是一种设计模式,它强制性地把应用程序的数据展示.数据处理和流程控制分开.MVC把应用程序分成3个核心模块:模型.视 ...
- 【JAVA】基于MVC架构Java技术荟萃案例演练
基于JAVA-MVC技术的顾客管理项目案例总结 作者 白宁超 2016年6月9日22:47:08 阅读前瞻:本文源于对javaweb相关技术和资料汇总,涉及大量javaweb基础技术诸如:Servle ...
- JavaWeb笔记——MVC设计模式和JavaWeb经典三层架
1 MVC设计模式 MVC设计模式 MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(C ...
- javaweb之MVC设计模式
1.MVC简介 MVC是Model-View-Controller的简称,即模型-视图-控制器.MVC是一种设计模式,它把应用程序分成三个核心模块:模型,视图,控制器,它们各自处理自己的任务. 模型( ...
- iOS开发--Swift 基于MVC设计模式的简单的tableViewDemo
如果说MVC是最好的设计模式, 可能很多人并不赞同, 但是如果说MVC是最主流, 应用面最广的设计模式, 我想这是毫无争议的. 不说废话, 直接演示在Swift中如何使用MVC新建工程(我并没有新建文 ...
随机推荐
- Linux驱动开发cdev驱动分层设计
#ifndef MYDEV_H #define MYDEV_H #define DYNAMIC_MINOR 256 struct mydev{ const char *name; const stru ...
- 最全的C#图片处理帮助类ImageHelper
最全的C#图片处理帮助类ImageHelper.cs 方法介绍: 生成缩略图 图片水印处理方法 图片水印位置处理方法 文字水印处理方法 文字水印位置的方法 调整光暗 反色处理 浮雕处理 拉伸图片 滤色 ...
- .NET注册页面代码
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI ...
- linux批量执行工具omnitty使用方法
一.omnitty概述 在生产环境中,可能会有多台linux主机.运维人员可能会对多台主机进行同样的操作,例:同时在多台主机上添加一个user或查看所有主机的硬件信息,如果没有批量操作工具,设备少于2 ...
- JavaScript中几个可以转化为false的值
1.[0,NaN,“”,null,undefined]都可以直接转化为false,但这几个值不是完全相等的 var arr = [0,"",false,null,undefined ...
- MySQL性能调优与架构设计读书笔记
可扩展性设计之数据切分 14.2 数据的垂直切分 如何切分,切分到什么样的程度,是一个比较考验人的难题.只能在实际的应用场景中通过平衡各方面的成本和利益,才能分析出一个真正适合自己的拆分方案. 14. ...
- new Option()——实现时间联动
//1.动态创建select function createSelect(){ var mySelect = document.createElement("select"); m ...
- mysql数据库编码
MySQL数据库默认的编码是: character set :latin1 collation : latin1_swedish_ci 查看MySQL支持的编码: mysql> show cha ...
- 解决Cacti监控图像断断续续问题
最近cacti的图像全都是断断续续.新加的设备,图像也是这样,查看cacti 的log发现大量下面类似的错误信息:04/12/2011 03:54:37 PM - SPINE: Poller[0] H ...
- C# LINQ 基本操作实例
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...