一、项目需求
1、数据库需求
- 需要一个名为springdb数据库
- 需要一个账户表,字段如下:
- 创建数据库
create database if not exists springdb;
- 创建表
create table if not exists account(
a_id int auto_increment comment '账户编号',
a_name varchar(32) comment '账户姓名',
a_money double comment '账户金额',
a_createdate date comment '开户日期',
constraint pk_account_aid primary key(a_id)
)engine=innodb default charset='utf8';
- 为了查询更方便 将字段重命名为实体类对应的字段
create view jdbcview
as
select a_id aid,a_name aname,a_money money,a_createdate createDate
from account;
2、页面需求
- 需要完成账户的新增、修改、删除以及查询功能
- 效果如下:
二、开发思路及步骤
1、需要用到的技术
- Spring 用于创建对象,对象的动态整合
- SpringMVC 用于WEB层控制页面
- dbutils DAO层数据的增删改查
- Bootstrap 提供页面的CSS支持
- jQuery 提供页面的JS支持
2、整合jar包
pom.xml的编写
- 初始化maven项目
<properties>
<!-- maven项目整体编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 项目编译的时候,源码(.java)使用哪个版本JDK -->
<maven.compiler.source>1.7</maven.compiler.source>
<!-- 项目编译的时候,可执行文件(.class)使用哪个版本JDK -->
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
- Spring相关:spring-context 5.0.2、spring-webmvc、spring-test
- 数据库相关:mysql-connector-java 5.1.6、commons-dbutils 1.6、druid 1.1.9
- 单元测试:junit 4.12、与spring-test一起配合
- ServletAPI相关:jsp-api 2.0、servlet-api 2.5,设置provided
- 页面表达式:jstl 1.2、standard 1.1.2
- pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gaj</groupId>
<artifactId>springmvc_tp2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<!-- maven项目整体编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 项目编译的时候,源码(.java)使用哪个版本JDK -->
<maven.compiler.source>1.7</maven.compiler.source>
<!-- 项目编译的时候,可执行文件(.class)使用哪个版本JDK -->
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<!-- spring容器,依赖了其他jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- 用于springMVC 可以暂时理解为servlet的升级版 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!-- dbutilsJDBC的API自动释放资源 -->
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
<!-- druid数据源以及druid数据监控 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<!-- mysql数据库连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- jsp api 编译器有效 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- servlet api 编译器有效 因为Tomcat自带这两个jar -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- jstl核心包 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- jstl标准标签库 -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- spring的Test的jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
</project>
3、实体类
package com.gaj.pojo;
import java.util.Date;
/**
* Account实体类
* JavaBean
* 对应springdb数据库的account表
* 数据库字段:a_id,a_name,a_money,a_createdate
* @author Jan
*
*/
public class Account {
private Integer aid; // 账户ID
private String aname; // 账户姓名
private Double money; // 账户余额
private Date createDate; // 开户日期
public Integer getAid() {
return aid;
}
public void setAid(Integer aid) {
this.aid = aid;
}
public String getAname() {
return aname;
}
public void setAname(String aname) {
this.aname = aname;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
@Override
public String toString() {
return "Account [aid=" + aid + ", aname=" + aname + ", money=" + money + ", createDate=" + createDate + "]";
}
}
4、DAO层
- 接口
package com.gaj.dao;
import java.sql.SQLException;
import java.util.List;
import com.gaj.pojo.Account;
/**
* Account数据操作层接口
* @author Jan
*
*/
public interface AccountDAO {
public int insertAccount(Account account) throws SQLException;
public int updateAccount(Account account) throws SQLException;
public int deleteAccount(Account account) throws SQLException;
public Account findAccountById(Integer aid) throws SQLException;
public List<Account> findAccountsByPage(Integer start, Integer size) throws SQLException;
public int accountTotalCount() throws SQLException;
}
- 实现类
package com.gaj.dao.impl;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.gaj.dao.AccountDAO;
import com.gaj.pojo.Account;
/**
* Account数据操作层实现类
* @author Jan
*
*/
@Repository
public class AccountDAOImpl implements AccountDAO {
@Autowired
private QueryRunner qr;
@Override
public int insertAccount(Account account) throws SQLException {
// 设置返回值
int count = 0;
// 编写sql语句
String sql = "insert into account values(null,?,?,?)";
// 占位符赋值
Object[] params = {account.getAname(), account.getMoney(), account.getCreateDate()};
// 执行sql
count = qr.update(sql, params);
// 返回
return count;
}
@Override
public int updateAccount(Account account) throws SQLException {
// 设置返回值
int count = 0;
// 编写sql语句
String sql = "update account set a_name=?,a_money=?,a_createdate=? where a_id=?";
// 占位符赋值
Object[] params = {account.getAname(), account.getMoney(), account.getCreateDate(), account.getAid()};
// 执行sql
count = qr.update(sql, params);
// 返回
return count;
}
@Override
public int deleteAccount(Account account) throws SQLException {
// 设置返回值
int count;
// 编写sql语句
String sql = "delete from account where a_id=?";
// 占位符赋值
Object param = account.getAid();
// 执行sql
count = qr.update(sql, param);
// 返回
return count;
}
@Override
public Account findAccountById(Integer aid) throws SQLException {
// 设置返回值
Account account = null;
// 编写sql语句
String sql = "select * from jdbcview where aid=?";
// 占位符赋值
Object param = aid;
// 执行sql
account = qr.query(sql, new BeanHandler<Account>(Account.class), param);
// 返回
return account;
}
@Override
public List<Account> findAccountsByPage(Integer start, Integer size) throws SQLException {
// 设置返回值
List<Account> list = null;
// 编写sql语句
String sql = "select * from jdbcview limit ?,?";
// 占位符赋值
Object[] params = {start, size};
// 执行sql
list = qr.query(sql, new BeanListHandler<Account>(Account.class), params);
// 返回
return list;
}
@Override
public int accountTotalCount() throws SQLException {
// 设置返回值
int totalCount = 0;
// 编写sql语句
String sql = "select count(a_id) from account";
// 执行sql
Number num = qr.query(sql, new ScalarHandler<Number>(1));
// 转换
totalCount = num.intValue();
// 返回
return totalCount;
}
}
5、Service层
- 接口
package com.gaj.service;
import java.sql.SQLException;
import java.util.List;
import com.gaj.pojo.Account;
/**
* Account逻辑业务层接口
* @author Jan
*
*/
public interface AccountService {
public int insertAccount(Account account) throws SQLException;
public int updateAccount(Account account) throws SQLException;
public int deleteAccount(Account account) throws SQLException;
public Account findAccountById(Integer aid) throws SQLException;
public List<Account> findAccountsByPage(Integer pageIndex, Integer pageSize) throws SQLException;
public int accountTotalCount() throws SQLException;
}
- 实现类
package com.gaj.service.impl;
import java.sql.SQLException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.gaj.dao.AccountDAO;
import com.gaj.pojo.Account;
import com.gaj.service.AccountService;
/**
* Account业务逻辑层实现类
* @author Jan
*
*/
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDAO accountDAO;
@Override
public int insertAccount(Account account) throws SQLException {
return accountDAO.insertAccount(account);
}
@Override
public int updateAccount(Account account) throws SQLException {
return accountDAO.updateAccount(account);
}
@Override
public int deleteAccount(Account account) throws SQLException {
return accountDAO.deleteAccount(account);
}
@Override
public Account findAccountById(Integer aid) throws SQLException {
return accountDAO.findAccountById(aid);
}
@Override
public List<Account> findAccountsByPage(Integer pageIndex, Integer pageSize) throws SQLException {
// 设置返回值
List<Account> list = null;
// 边界判断
if(pageIndex != null && pageSize != null){
if(pageIndex > 0 && pageSize > 0){
// 计算起始页
int start = (pageIndex - 1) * pageSize;
int size = pageSize;
list = accountDAO.findAccountsByPage(start, size);
}
}
// 返回
return list;
}
@Override
public int accountTotalCount() throws SQLException {
return accountDAO.accountTotalCount();
}
}
6、Spring配置文件的编写
- applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置注解Bean的包扫描器 -->
<context:component-scan base-package="com.gaj.dao" />
<context:component-scan base-package="com.gaj.service" />
<!-- 创建druid数据源并绑定属性 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/springdb?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
<!-- 配置web监控统计拦截的filters -->
<!-- 源码:String property = properties.getProperty("druid.filters"); -->
<property name="filters" value="stat" />
</bean>
<!-- 创建QueryRunner并注入数据源 -->
<bean id="qr" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource" />
</bean>
</beans>
7、测试类
- 查看DAO层和Service层能否进行CURD
package com.gaj.test;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gaj.pojo.Account;
import com.gaj.service.AccountService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext.xml"})
public class AccountTest {
@Autowired
private AccountService service;
Random random = new Random();
Scanner scanner = new Scanner(System.in);
@Test
public void addBatchTest() throws SQLException{
Account account = null;
System.out.println("请输入需要添加的记录数:");
int num = scanner.nextInt();
System.out.println("开始批量添加数据...");
for(int i = 1; i <= num; i++){
account = new Account();
account.setAname("测试数据" + i);
account.setMoney(random.nextInt(10000) + 0D);
account.setCreateDate(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * random.nextInt(366)));
int count = service.insertAccount(account);
System.out.println(count > 0 ? i +" Insert OK!" : i + " Insert Failed!");
}
System.out.println("批量添加完成!");
}
@Test
public void addTest() throws SQLException, ParseException{
System.out.println("开始添加数据...");
Account account = new Account();
System.out.println("请输入账户姓名:");
account.setAname(scanner.next());
System.out.println("请输入账户金额:");
account.setMoney(scanner.nextDouble());
System.out.println("请输入开户日期:");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
account.setCreateDate(df.parse(scanner.next()));
int count = service.insertAccount(account);
System.out.println(count > 0 ? "Insert OK!" : "Insert Failed!");
}
@Test
public void updateTest() throws SQLException, ParseException{
System.out.println("请输入需要更新的账户编号:");
int aid = scanner.nextInt();
Account account = service.findAccountById(aid);
if(account != null){
System.out.println("开始更新账户信息...");
System.out.println("请输入账户姓名:");
account.setAname(scanner.next());
System.out.println("请输入账户金额:");
account.setMoney(scanner.nextDouble());
System.out.println("请输入开户日期:");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
account.setCreateDate(df.parse(scanner.next()));
int count = service.updateAccount(account);
System.out.println(count > 0 ? "Update OK!" : "Update Failed!");
}else{
System.out.println("抱歉,没有找到这个编号的账户...");
}
}
@Test
public void deleteTest() throws SQLException{
System.out.println("请输入需要删除的账户编号:");
int aid = scanner.nextInt();
Account account = service.findAccountById(aid);
if(account != null){
System.out.println("开始删除账户...");
int count = service.deleteAccount(account);
System.out.println(count > 0 ? "Delete OK!" : "Delete Failed!");
}else{
System.out.println("抱歉,没有找到这个编号的账户...");
}
}
@Test
public void query() throws SQLException{
int pageSize = 10; // 页容量
int totalCount = 0; // 总记录数
int totalPage = 0; // 总页数
int pageIndex = 0; // 页码
totalCount = service.accountTotalCount();
totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
for(int i = 1; i <= totalPage; i++){
pageIndex = i;
System.out.println("总记录数:" + totalCount + "\t\t总页数:" + totalPage + "\t\t页容量:" + pageSize + "\t\t当前页:" + pageIndex);
List<Account> accounts = service.findAccountsByPage(pageIndex, pageSize);
for (Account account : accounts) {
System.out.println(account);
}
}
}
}
8、jsp文件的编写
- index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>账户信息管理系统-首页</title>
<link rel="stylesheet" type="text/css"
href="${pageContext.request.contextPath }/css/bootstrap.min.css" />
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/jquery-1.9.1.js"></script>
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/bootstrap.min.js"></script>
</head>
<body>
<div class="jumbotron">
<div class="container">
<h1>欢迎使用账户信息管理系统!</h1>
<p>请选择一些功能吧...</p>
<p>
<a class="btn btn-primary btn-lg" role="button" href="showAccountsAction?pi=1">显示账户信息</a>
 
<a class="btn btn-success btn-lg" role="button" href="account_add.jsp">添加新账户</a>
</p>
</div>
</div>
</body>
</html>
- account_list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="f" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>账户信息管理系统-展示</title>
<link rel="stylesheet" type="text/css"
href="${pageContext.request.contextPath }/css/bootstrap.min.css" />
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/jquery-1.9.1.js"></script>
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/bootstrap.min.js"></script>
<style type="text/css">
h1,th,tr {
text-align: center;
}
</style>
<script type="text/javascript">
function goIndex(pi){
window.location.href="showAccountsAction?pi=" + pi;
}
</script>
</head>
<body>
<div>
<h1 onclick="javascript:location.href='index.jsp'">展示账户信息</h1>
<table class="table table-hover">
<tr class="active">
<th colspan="5">
总条数:<span style="color: red; font-size: 20px;">${totalCount }</span>   
总页数:<span style="color: red; font-size: 20px;">${totalPage }</span>   
页容量:<span style="color: red; font-size: 20px;">${pageSize }</span>   
当前页:<span style="color: red; font-size: 20px;">${pageIndex }</span>
</th>
</tr>
<tr class="info">
<th>账户编号</th>
<th>账户姓名</th>
<th>账户金额</th>
<th>开户日期</th>
<th>操作</th>
</tr>
<c:forEach var="account" items="${accounts }">
<tr class="warning">
<td>${account.aid }</td>
<td>${account.aname }</td>
<td>
<f:formatNumber type="currency" value="${account.money }" />
</td>
<td>
<f:formatDate pattern="yyyy年MM月dd日" value="${account.createDate }"/>
</td>
<td>
<button class="btn btn-warning" type="button" onclick="javascript:location.href='findAccountAction?pi=${account.aid}'">更新</button>
<button class="btn btn-danger" type="button" onclick="javascript:location.href='deleteAccountAction?pi=${account.aid}'">删除</button>
</td>
</tr>
</c:forEach>
<tr>
<th colspan="5">
<button class="btn btn-default" type="button" onclick="goIndex(1);">首页</button>
<c:choose>
<c:when test="${pageIndex > 1 }">
<button class="btn btn-default" type="button" onclick="goIndex(${pageIndex - 1});">上一页</button>
</c:when>
<c:otherwise>
<button class="btn btn-default" type="button" disabled="disabled" onclick="goIndex(${pageIndex - 1});">上一页</button>
</c:otherwise>
</c:choose> <c:choose>
<c:when test="${totalPage > pageIndex }">
<button class="btn btn-default" type="button" onclick="goIndex(${pageIndex + 1})">下一页</button>
</c:when>
<c:otherwise>
<button class="btn btn-default" type="button" disabled="disabled" onclick="goIndex(${pageIndex + 1})">下一页</button>
</c:otherwise>
</c:choose>
<button class="btn btn-default" type="button" onclick="goIndex(${totalPage});">尾页</button>
</th>
</tr>
</table>
</div>
</body>
</html>
- account_add.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>账户信息管理系统-添加</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/css/bootstrap.min.css" />
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery.1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/bootstrap.min.js"></script>
<style type="text/css">
th{
font-size: large;
color: fuchsia;
}
</style>
</head>
<body>
<div>
<h1 style="text-align: center; color:purple;" onclick="javascript:location.href='index.jsp'" >添加账户信息</h1>
<form action="insertAccountAction" method="post">
<table class="table table-hover">
<tr class="info">
<th>账户姓名:</th>
<td>
<input class="form-control" type="text" name="aname" required="required" placeholder="请输入账户姓名..." />
</td>
</tr>
<tr class="danger">
<th>账户金额</th>
<td>
<input class="form-control" type="number" name="money" min="0.0" max="9999999.99" step="0.1" required="required" placeholder="请输入账户金额..." />
</td>
</tr>
<tr class="warning">
<th>开户日期</th>
<td>
<input class="form-control" type="date" name="createDate" required="required" />
</td>
</tr>
<tr class="active">
<th colspan="2" style="text-align:center;">
<button class="btn btn-success" type="submit">添加</button>
  
<button class="btn btn-danger" type="reset">取消</button>
</th>
</tr>
</table>
</form>
</div>
</body>
</html>
- account_update.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>账户信息管理系统-更新</title>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/css/bootstrap.min.css" />
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery.1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/bootstrap.min.js"></script>
<style type="text/css">
th{
font-size: large;
color: fuchsia;
}
</style>
</head>
<body>
<div>
<h1 style="text-align: center; color:purple;" onclick="javascript:location.href='index.jsp'" >更新账户信息</h1>
<form action="updateAccountAction" method="post">
<input type="hidden" name="aid" value="${account.aid }" />
<table class="table table-hover">
<tr class="info">
<th>账户姓名:</th>
<td>
<input class="form-control" type="text" name="aname" value="${account.aname }" required="required" placeholder="请输入账户姓名..." />
</td>
</tr>
<tr class="danger">
<th>账户金额</th>
<td>
<input class="form-control" type="number" name="money" value="${account.money }" min="0.0" max="9999999.99" step="0.1" required="required" placeholder="请输入账户金额..." />
</td>
</tr>
<tr class="warning">
<th>开户日期</th>
<td>
<input class="form-control" type="date" name="createDate" value="${account.createDate }" required="required" />
</td>
</tr>
<tr class="active">
<th colspan="2" style="text-align:center;">
<button class="btn btn-success" type="submit">更新</button>
  
<button class="btn btn-danger" type="reset">取消</button>
</th>
</tr>
</table>
</form>
</div>
</body>
</html>
- error.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>账户信息管理系统-错误</title>
<link rel="stylesheet" type="text/css"
href="${pageContext.request.contextPath }/css/bootstrap.min.css" />
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/jquery-1.9.1.js"></script>
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/bootstrap.min.js"></script>
</head>
<body>
<div class="jumbotron">
<div class="container">
<h1>ERROR</h1>
<p style="color: red; font-size: 30px;">
${msg }
</p>
<p>
<a class="btn btn-info btn-lg" role="button" href="index.jsp">返回首页</a>
</p>
</div>
</div>
</body>
</html>
9、后端控制器的编写
- 分页查询
package com.gaj.web;
import java.sql.SQLException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.gaj.pojo.Account;
import com.gaj.service.AccountService;
@Controller
public class AccountViewAction {
@Autowired
private AccountService service;
@RequestMapping("/showAccountsAction")
public ModelAndView showAccountsAction(
@RequestParam(value = "pi", required = false, defaultValue = "1") Integer pageIndex) throws SQLException {
// 创建方法的返回值
ModelAndView mv = new ModelAndView();
// 定义页容量大小
int pageSize = 10;
// 计算记录总条数
int totalCount = service.accountTotalCount();
// 计算总页数
int totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;
// 判断索引边界值
if(pageIndex < 1){
pageIndex = 1;
}
if(pageIndex > totalPage){
pageIndex = totalPage;
}
// 获取分页数据
List<Account> accounts = service.findAccountsByPage(pageIndex, pageSize);
// 保存数据
mv.addObject("pageSize", pageSize);
mv.addObject("totalCount", totalCount);
mv.addObject("totalPage", totalPage);
mv.addObject("pageIndex", pageIndex);
mv.addObject("accounts", accounts);
// 转发到下一页
mv.setViewName("forward:/account_list.jsp");
// 返回
return mv;
}
}
- 增删改操作
package com.gaj.web;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.gaj.pojo.Account;
import com.gaj.service.AccountService;
@Controller
public class AccountOperationAction {
@Autowired
private AccountService service;
// 时间类型需要进行转换
@InitBinder
public void dateBinder(WebDataBinder binder){
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
@RequestMapping("/insertAccountAction")
public ModelAndView insertAccountAction(Account account) throws SQLException{
// 设置返回值
ModelAndView mv = new ModelAndView();
// 执行 需保证表单name与实体bean的属性一致
int count = service.insertAccount(account);
// 判断
if (count > 0) {
// 添加成功,重定向到showAccountsAction
mv.setViewName("redirect:/showAccountsAction");
} else {
// 添加失败,将错误信息转发到error.jsp
mv.addObject("msg", "很遗憾,添加失败了...");
mv.setViewName("forward:/error.jsp");
}
// 返回
return mv;
}
@RequestMapping("/deleteAccountAction")
public ModelAndView deleteAccountAction(@RequestParam(value = "pi", required = true) Integer pageIndex)
throws SQLException {
// 设置返回值
ModelAndView mv = new ModelAndView();
// 查询是否有该数据
Account account = service.findAccountById(pageIndex);
// 判断
if (account != null) {
// 找到了该记录
int count = service.deleteAccount(account);
if (count > 0) {
// 删除成功,重定向到showAccountsAction
mv.setViewName("redirect:/showAccountsAction");
} else {
// 删除失败,将错误信息转发到error.jsp
mv.addObject("msg", "很遗憾,删除失败了...");
mv.setViewName("forward:/error.jsp");
}
} else {
// 没找到记录
// 删除失败,将错误信息转发到error.jsp
mv.addObject("msg", "很遗憾,没有找到aid为" + pageIndex + "的记录...");
mv.setViewName("forward:/error.jsp");
}
// 返回
return mv;
}
@RequestMapping("/findAccountAction")
public ModelAndView findAccountAction(
@RequestParam(value = "pi", required = true)Integer pageIndex) throws SQLException{
// 设置返回值
ModelAndView mv = new ModelAndView();
// 定位到这条数据
Account account = service.findAccountById(pageIndex);
// 判断
if(account != null){
// 保存对象
mv.addObject("account", account);
// 跳转到更新页面
mv.setViewName("forward:/account_update.jsp");
}else{
// 没找到记录
// 更新失败,将错误信息转发到error.jsp
mv.addObject("msg", "很遗憾,没有找到aid为" + pageIndex + "的记录...");
mv.setViewName("forward:/error.jsp");
}
// 返回
return mv;
}
@RequestMapping("/updateAccountAction")
public ModelAndView updateAccountAction(Account account) throws SQLException{
// 设置返回值
ModelAndView mv = new ModelAndView();
// 执行
int count = service.updateAccount(account);
// 判断
if(count > 0){
// 更新成功
mv.setViewName("redirect:/showAccountsAction");
}else{
// 更新失败
mv.addObject("msg","很遗憾,更新失败了...");
mv.setViewName("forward:/error.jsp");
}
// 返回
return mv;
}
}
10、前端控制器的编写
- spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 扫描注解bean配置的controller层 -->
<context:component-scan base-package="com.gaj.web" />
<!-- 加载springmvc的预置功能 -->
<mvc:annotation-driven />
<!-- 设置哪些请求是在请求静态文件不需要后端控制器处理 -->
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/fonts/" mapping="/fonts/**" />
<mvc:resources location="/css/" mapping="/css/**" />
</beans>
11、web.xml的配置
<?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_2_5.xsd"
version="2.5">
<!-- 项目名 -->
<display-name>springmvc_tp2</display-name>
<!-- 默认首页 欢迎页面 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 加载spring配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 配置Spring web监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring MVC核心servlet -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 加载spring-mvc配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<!-- 拦截规则 / -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 中文乱码过滤器 -->
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- druid过滤器 -->
<filter>
<filter-name>DruidWebStatFilter</filter-name>
<filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>DruidWebStatFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置druid连接池的web监控 -->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
<!-- StatViewServlet的父类ResourceServlet配置了druid web监控相关资源 -->
<init-param>
<!-- 设置登录用户名 -->
<param-name>loginUsername</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<!-- 设置登录密码 -->
<param-name>loginPassword</param-name>
<param-value>admin</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
</web-app>
三、知识点及总结
1、实体类包名的表示方式
com.xxx.domain:域;定义域
com.xxx.pojo:(Plain Ordinary Java Object)简单的java对象
com.xxx.entity:实体
2、监听器的配置
监听器是一个专门用于对其他对象身上发生的事件或状态的改变进行监听和相应处理的对象,当被监视的对象发生改变时就立即采取相应的行动。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- 监听器专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行。
- ContextLoaderListener的作用:在启动Web容器时,自动装配Spring applicationContext.xml的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
- 在ContextLoderListenner中关联了ContextLoader类,因此整个加载配置过程由ContextLoader来完成。
3、开启druid web监控
- web.xml
<!-- 配置 Druid 监控信息显示页面 -->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
<init-param>
<!-- 用户名 -->
<param-name>loginUsername</param-name>
<param-value>admin</param-value>
</init-param>
<init-param>
<!-- 密码 -->
<param-name>loginPassword</param-name>
<param-value>admin</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
- application.xml
需要设置filters属性的值为stat
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/springdb?characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="filters" value="stat" />
</bean>
4、引用Bootstrap样式没有显示
- 原因:SpringMVC将请求CSS和JS的URL当成了request请求,这时没有能够处理这些个请求的后端控制器。
- 解决:在SpringMVC配置静态文件,无需后端控制器处理
配置作用:DispatcherServlet不会拦截以/static开头的所有请求路径,并当作静态资源交由Servlet处理
<!-- 设置哪些请求是在请求静态文件不需要后端控制器处理 -->
<mvc:resources location="/js/" mapping="/js/**" />
<mvc:resources location="/fonts/" mapping="/fonts/**" />
<mvc:resources location="/css/" mapping="/css/**" />
location元素表示webapp目录下的static包下的所有文件
mapping元素表示以/static开头的所有请求路径,如/static/a或/static/b
5、时间处理
jsp中date类型 -> http中string类型 -> java中date类型
需要在后端控制器中绑定自定义的格式
@InitBinder
public void dateBinder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); //true:允许输入空值,false:不能为空值
}
6、属性对应
后端控制器中使用对象时,对象的属性需要与jsp中表单name一致,否则拿不到数据。