前言
学Java Web有一段时日了,这篇文章来做个中场休息,了解一下Java项目的三层架构以及实现一个简单的小案例。
三层架构:软件设计架构
三层架构
- 界面层(表示层):用户看得到的界面。用户可以通过界面上的组件和服务器进行交互。
- 业务逻辑层:处理业务逻辑。
- 数据访问层:操作数据存储文件。
dao的意思是Data Access objects:数据存取对象
著名的SSM框架其实就是对三层架构各个层的一个简化:
- 界面层==》Spring MVC 框架
- 数据访问层==》MyBatis框架
- 业务逻辑层==》Spring框架
三层架构与MVC的关系
三层架构架构模式与MVC设计模式的关系
案例
项目流程
案例及需求
我们的案例是用户的信息的查询
需求:用户信息的增删改查操作
设计
- 技术选型:Servlet+JSP+MySQL+JDBC Template+Druid+BeanUtils+tomcat
- 数据库设计:
-
CREATE DATABASE sometest; -- 创建数据库 USE sometest; -- 使用数据库 CREATE TABLE user( -- 创建表 id int primary key auto_increment, -- id name varchar(20) not null, -- 姓名 gender varchar(5), -- 性别 age int, -- 年龄 address varchar(20), -- 地址 qq varchar(20), -- qq email varchar(50) -- 邮箱 );
-
USE sometest; CREATE TABLE administrator( -- 创建表 id INT PRIMARY KEY AUTO_INCREMENT, -- id username VARCHAR(32) NOT NULL, -- 用户名 password VARCHAR(32) NOT NULL -- 密码 ); INSERT INTO administrator(username,password) VALUE("金庸","123456");
-
开发
- 环境搭建
- 数据库创建
- 创建项目,导入需要的jar包
- 编码
测试
部署运维
编码之前
环境搭建
数据库下
上面已经写好SQL语句了,复制过去执行即可。
创建好sometest库下的user表、administrator表(暂定管理员——金庸,123456)。
IDEA下
创建一个项目,导入需要的jar包:
- druid
- BeanUtils
- jstl
- mysql驱动
- spring-jdbc
这里我分享一波:
链接:https://pan.baidu.com/s/1AAHCgcB6td5OuBxsaW4Nlw
提取码:r5q8
另外,为了方便我们的前端美化,我们使用bootstrap这一框架,故请在web目录下导入bootstrap需要的js、css等目录文件。
分析项目
分析项目:
开始编码
1.大体框架
好,接下来我们来具体写代码:
先在web项目的src下创建五个包(前面都是 域名.公司.项目.):
- dao
- impl
- service
- impl
- web
- servlet
- util
- domain
好,接下来在domain包下创建一个JavaBean——User.java,这个JavaBean的变量就是数据库User表下的字段,然后生成getter/setter即可:
public class User {
private Integer id;
private String name;
private String gender;
private Integer age;
private String address;
private String qq;
private String email;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", address='" + address + '\'' +
", qq='" + qq + '\'' +
", email='" + email + '\'' +
'}';
}
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 getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getQq() {
return qq;
}
public void setQq(String qq) {
this.qq = qq;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
上面这个JavaBean中的变量全部是引用类型,因为我们后面会用Spring JDBC去通过字节码文件直接映射封装它,故变量类型最好是引用类型,引用类型才能有null值,这样数据库的某个字段为null的时候映射过来就不会报错了!
在web目录下的index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>首页</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
</script>
</head>
<body>
<div align="center">
<!--EL表达式动态拿到虚拟目录,总目录指向userListServlet接口-->
<a href="${pageContext.request.contextPath}/userListServlet"
style="text-decoration:none;font-size:33px">
查询所有用户信息
</a>
</div>
</body>
</html>
如代码,我们将一个超链接转给userListServlet接口,故我们接下来在web.servlet包下创建一个Servlet——UserListServlet.java:
@WebServlet("/userListServlet")
public class UserListServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.调用UserService完成查询
UserService service=new UserServiceImpl();
List<User> users=service.findAll();
//2.将list存入request域
request.setAttribute("users",users);
//3.转发到list.jsp
request.getRequestDispatcher("/list.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
如这个Servlet,我们调用UserServiceImpl类去实现查询,然后保存到了request域,然后请求转发给了list.jsp
list.jsp我们先不着急实现,我们先来写业务逻辑层的UserService
service包下的UserService.java:
public interface UserService {
List<User> findAll();
}
service.impl包下的UserServiceImpl.java:
public class UserServiceImpl implements UserService {
private UserDao dao=new UserDaoImpl();
@Override
public List<User> findAll(){
//使用Dao完成查询
return dao.findAll();
}
}
我们调用了Dao层的UserDaoImpl类的对象的方法去完成查询:
dao包下的UserDao.java:
public interface UserDao {
List<User> findAll();
}
dao.impl包下的UserDaoImpl.java:
public class UserDaoImpl implements UserDao {
@Override
public List<User> findAll() {
//使用JDBC操作数据库
return null;
}
}
这里的具体功能我们先不实现。
数据库登场
除了druid这些以外,有一点记得注意:MySQL的版本超过8.0需要使用高版本的驱动包,以及不同的连接方式,详情请看我以前的MySQL驱与Java的文章,这里提供下载 8.0+ 的驱动包的官网。
在src目录下创建druid.properties:
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/sometest?useSSL=false&serverTimezone=UTC
username=root
password=964939451
#初始化连接数
initialSize=5
#最大连接数
maxActive=10
#等待时间
maxWait=3000
# 验证连接是否可用,使用的SQL语句
validationQuery:SELECT 1
#指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.
testWhileIdle:true
#借出连接时不要测试,否则很影响性能
testOnBorrow:false
具体连接的参数要根据你自己的情况来
接下来,我们在utils包下写一个JDBCUtils.java:
public class JDBCUtils {
private static DataSource ds;
static{
try{
//1.加载配置文件
Properties pro=new Properties();
pro.load(JDBCUtils.class
.getClassLoader()
.getResourceAsStream("druid.properties"));
//2.获取DataSource
ds= DruidDataSourceFactory.createDataSource(pro);
}catch(Exception e){
e.printStackTrace();
}
}
/**
* @Description 获取连接
**/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
/**
* @Description 获取连接池的方法
**/
public static DataSource getDateSource(){
return ds;
}
/**
* @Description 释放资源
**/
public static void close(Statement stmt,Connection conn){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet rs, Statement stmt, Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
close(stmt,conn);
}
}
写了这个工具类,就方便多了,我们回到UserDaoImpl来实现具体的findAll方法
dao.impl包下UserDaoImpl.java:
public class UserDaoImpl implements UserDao {
private JdbcTemplate template=new JdbcTemplate(JDBCUtils.getDateSource());
@Override
List<User> findAll() {
//1.定义sql
String sql="SELECT * FROM user ";
List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class));
return users;
}
}
这样数据库的搜索需求就实现了,另外就是展示结果的问题了。
还记得UserListServlet中查询到数据库的结果后将请求转发到了list.jsp吗?我们下面来实现list.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="C" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>用户信息管理系统</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<style type="text/css">
td, th {
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h3 style="text-align: center">用户信息列表</h3>
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<C:forEach items="${requestScope.users}" var="user" varStatus="s">
<tr>
<td>${s.count}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${user.age}</td>
<td>${user.address}</td>
<td>${user.qq}</td>
<td>${user.email}</td>
<td><a class="btn btn-default btn-sm" href="update.html">
修改</a>
<a class="btn btn-default btn-sm" href="">
删除</a></td>
</tr>
</C:forEach>
<tr>
<td colspan="8" align="center"><a class="btn btn-primary" href="add.html">
添加联系人</a></td>
</tr>
</table>
</div>
</body>
</html>
做完这里你就可以测试一下了,尝试手动给数据库添加几条记录,然后来访问一下测试一下看看数据是否能正确的显示出来。
列表查询的美化
对于list.jsp页面,我们还希望丰富其功能,可以查询、有分页组件、统一添加或删除等,具体方法我们先不着急实现,我们先来将一个“摆样子”的list.jsp写出来,同时,我们将预留的访问对象、方法绑定什么的都写好:
<body>
<div class="container">
<h3 style="text-align: center">用户信息列表</h3>
<!--内联表单,实现查询-->
<div style="float:left">
<form class="form-inline">
<div class="form-group">
<label for="exampleInputName2">姓名</label>
<input type="text" class="form-control" id="exampleInputName2">
</div>
<div class="form-group">
<label for="exampleInputName3">籍贯</label>
<input type="text" class="form-control" id="exampleInputName3">
</div>
<div class="form-group">
<label for="exampleInputEmail2">邮箱</label>
<input type="email" class="form-control" id="exampleInputEmail2">
</div>
<button type="submit" class="btn btn-default">查询</button>
</form>
</div>
<div style="float:right;margin:5px">
<a class="btn btn-success"
href="${pageContext.request.contextPath}/add.jsp">添加联系人</a>
<a class="btn btn-primary" href="add.html">删除选中</a>
</div>
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th><input type="checkbox"></th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<C:forEach items="${requestScope.users}" var="user" varStatus="s">
<tr>
<td><input type="checkbox"></td>
<td>${s.count}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${user.age}</td>
<td>${user.address}</td>
<td>${user.qq}</td>
<td>${user.email}</td>
<td><a class="btn btn-default btn-sm" href="update.html">
修改</a>
<a class="btn btn-default btn-sm"
href="javascript:deleteUser(${user.id});">
删除</a>
</td>
</tr>
</C:forEach>
</table>
<!--分页组件-->
<div>
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
<span style="font-size: 25px;margin: 5px">
共16条记录,共4页
</span>
</ul>
</nav>
</div>
</div>
</body>
bootstrap这个前端框架真是牛逼,轻轻松松帮助我们完成了页面的美化!
登录页面
list.jsp这边先放着,我们接下来来完成这个项目的登录页面及其功能。
步骤:
- 创建login.jsp
- 调整页面,加入验证码功能
- 处理登录逻辑
首先是我们的login.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>管理员登录</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
//切换验证码
function refreshCode(){
//1.获取验证码的图片对象
var vcode=document.getElementById("vcode");
//2.设置其src属性,加时间戳(避免浏览器访问缓存)
//注意:EL表达式在js中依然有用
vcode.src="${pageContext.request.contextPath}/checkCodeServlet?time="
+new Date().getTime();
}
</script>
</head>
<body>
<div class="container" style="width: 400px;">
<h3 style="text-align: center;">管理员登录</h3>
<form action="${pageContext.request.contextPath}/loginServlet" method="post">
<div class="form-group">
<label for="user">用户名:</label>
<input type="text" name="username" class="form-control"
id="user" placeholder="请输入用户名"/>
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" name="password" class="form-control"
id="password" placeholder="请输入密码"/>
</div>
<div class="form-inline">
<label for="verifycode">验证码:</label>
<input type="text" name="verifycode" class="form-control"
id="verifycode" placeholder="请输入验证码" style="width: 120px;"/>
<a href="javascript:refreshCode()">
<img src="${pageContext.request.contextPath}/checkCodeServlet"
title="看不清点击刷新" id="vcode"/>
</a>
</div>
<hr/>
<div class="form-group" style="text-align: center;">
<input class="btn btn btn-primary" type="submit" value="登录">
</div>
</form>
<!-- 出错显示的信息框 -->
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" >
<span>×</span>
</button>
<strong>${requestScope.login_msg}</strong>
</div>
</div>
</body>
</html>
这是登录界面的展示,我们看到这个jsp会向checkCodeServlet接口请求验证码,向loginServlet发出登录请求。
我们先来做验证码的,这个比较好实现,在包web.servlet中,有CheckCodeServlet.java:
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
int width=100;
int height=50;
//1.创建一个对象,在内存中的图片(验证码图片对象)
BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//2.美化图片
//2.1 填充背景色
Graphics g=image.getGraphics(); //画笔对象
g.setColor(Color.green); //设置画笔颜色
g.fillRect(0,0,width,height); //给内存中的图片填充背景
//2.2画边框
g.setColor(Color.yellow);
g.drawRect(1,1,width - 1,height - 1);
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
//生成随机角标
Random ran = new Random();
StringBuffer sb=new StringBuffer();
for(int i=1;i<=4;i++){
//得到随机下标
int index=ran.nextInt(str.length());
//获取字符
char ch=str.charAt(index); //随机字符
//将验证码值存到StringBuffer中
sb.append(ch);
//将验证码写入图片
g.setColor(Color.black);
g.drawString(ch+" ",width/5*i,height/2);
}
String checkCode=sb.toString();
//将验证码存入session域
req.getSession().setAttribute("checkCode",checkCode);
//画干扰线
g.setColor(Color.white);
for (int i = 0; i < 10; i++) {
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}
//3.将图片输出到页面展示
ImageIO.write(image,"jpg",resp.getOutputStream());
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req,resp);
}
}
请求此接口可直接得到图片,其中我们将当前正确验证码放到session域中,一会会在loginServlet下用到。
登录逻辑
接下来就是来写登录逻辑了,还记得之前我们创建的administrator表吗?这里要派上用场了。
首先在domain包下创建一个JavaBean:
public class Administrator {
private String username;
private String password;
@Override
public String toString() {
return "Administrator{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
然后我们来写web.servlet包下的LoginServlet.java:
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.设置编码(调整请求体内容编码)
request.setCharacterEncoding("utf-8");
//2.获取数据
//2.1 获取用户填写的验证码
String verifycode=request.getParameter("verifycode");
Map<String, String[]> maps = request.getParameterMap();
//3.检验验证码
String vCode=(String)request.getSession().getAttribute("checkCode");
request.getSession().removeAttribute("checkCode");
if(!vCode.equalsIgnoreCase(verifycode)){
//验证码不正确
//提示信息
request.setAttribute("login_msg","验证码错误!");
//跳转登录页面(请求转发)
request.getRequestDispatcher("/login.jsp").forward(request,response);
return;
}
//4.封装Administrator对象
Administrator admin=new Administrator();
try {
BeanUtils.populate(admin,maps);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//5.调用Service查询
AdministratorService service=new AdministratorServiceImpl();
Administrator loginAdmin = service.login(admin);
//6.判断是否登录成功
if(loginAdmin!=null){
//登录成功
//将用户存入session
request.getSession().setAttribute("user",admin);
//跳转页面
response.sendRedirect(request.getContextPath()+"/index.jsp");
}else{
//登录失败
//提示信息
request.setAttribute("login_msg","用户名或密码错误!");
//跳转登录页面(请求转发)
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
如上,我们需要创建AdministratorService 来处理登录,故service.impl包下有(对应接口就不写了):
public class AdministratorServiceImpl implements AdministratorService {
private AdministratorDao ad=new AdministratorDaoImpl();
@Override
public Administrator login(Administrator admin) {
return ad.findAdminByNameAndPass(admin.getUsername(),admin.getPassword());
}
}
再往下走就是dao里需要AdministratorDaoImpl,故dao.impl包下(对应接口就不写了):
public class AdministratorDaoImpl implements AdministratorDao {
private JdbcTemplate template=new JdbcTemplate(JDBCUtils.getDateSource());
@Override
public Administrator findAdminByNameAndPass(String username, String password) {
try {
String sql = "SELECT * FROM administrator WHERE username=? and password=?";
Administrator admin = template.queryForObject(sql,
new BeanPropertyRowMapper<Administrator>(Administrator.class),
username, password);
return admin;
}catch(Exception e){
e.printStackTrace();
return null;
}
}
}
OK,到这里为止,登录功能就实现了,如果你想,可以在index.jsp页面下添加一个“欢迎用户”的提示:
<h2>${sessionScope.login_admin.username},欢迎您!</h2>
添加用户信息
完成了登录功能后,我们回到list.jsp页面上的功能实现,我们先来完成添加用户的功能吧。
对于添加用户信息的功能,我们来做成一个add.jsp页面,用来添加用户信息。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>添加用户</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
$(function(){
//如下是前端拦截代码
$("#name").change(function(){
if(!testName()){
//不符合正则表达式
if(!$("#name + span")[0]) {
//没有span提示,则添加span提示
var text = $("<span style='color:red'>" +
"汉字/字母/数字/下划线,3至16位" +
"</span>");
$("#name").parent().append(text);
}
}else {
//符合正则表达式
$("#name + span").remove();
}
});
$("#age").change(function(){
if(!testAge()){
//不符合正则表达式
if(!$("#age + span")[0]) {
//没有span提示,则添加span提示
var text = $("<span style='color:red'>" +
"请输入数字" +
"</span>");
$("#age").parent().append(text);
}
}else {
//符合正则表达式
$("#age + span").remove();
}
});
$("#qq").change(function(){
if(!testQq()){
//不符合正则表达式
if(!$("#qq + span")[0]) {
//没有span提示,则添加span提示
var text = $("<span style='color:red'>" +
"请输入QQ账号" +
"</span>");
$("#qq").parent().append(text);
}
}else {
//符合正则表达式
$("#qq + span").remove();
}
});
$("#email").change(function(){
if(!testEmail()){
//不符合正则表达式
if(!$("#email + span")[0]) {
//没有span提示,则添加span提示
var text = $("<span style='color:red'>" +
"请输入正确的邮箱地址" +
"</span>");
$("#email").parent().append(text);
}
}else {
//符合正则表达式
$("#email + span").remove();
}
});
var testName=function(){
var regexp=/^[\u4e00-\u9fa5_A-Za-z0-9]{3,16}$/;
var name=$("#name").val();
return regexp.test(name);
}
var testAge=function(){
var regexp=/^[0-9]{1,3}$/;
var age=$("#age").val();
return regexp.test(age);
}
var testQq=function(){
var regexp=/^[0-9]{8,11}$/;
var qq=$("#qq").val();
return regexp.test(qq);
}
var testEmail=function(){
var regexp=/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
var email=$("#email").val();
return regexp.test(email);
}
//提交按钮绑定单机事件
$("#sub").click(function(){
if(!(testName()&&testAge()&&testQq()
&&testEmail())){
return false;
}
});
})
</script>
</head>
<body>
<div class="container">
<div style="text-align: center;"><h3>添加联系人页面</h3></div>
<form action="${pageContext.request.contextPath}/addUserServlet" method="post">
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名">
</div>
<div class="form-group">
<label>性别:</label>
<input type="radio" name="gender" value="男" checked="checked"/>男
<input type="radio" name="gender" value="女"/>女
</div>
<div class="form-group">
<label for="age">年龄:</label>
<input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄">
</div>
<div class="form-group">
<label for="address">籍贯:</label>
<select name="address" class="form-control" id="address">
<option value="陕西">陕西</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
</select>
</div>
<div class="form-group">
<label for="qq">QQ:</label>
<input type="text" class="form-control" id="qq" name="qq" placeholder="请输入QQ号码"/>
</div>
<div class="form-group">
<label for="email">邮箱:</label>
<input type="text" class="form-control" id="email" name="email" placeholder="请输入邮箱地址"/>
</div>
<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" id="sub" value="提交" />
<input class="btn btn-default" type="reset" value="重置" />
<input class="btn btn-default" type="button" value="返回" />
</div>
</form>
</div>
</body>
</html>
script标签内主要是正则表达式匹配规范输入。
当我们提交之后,数据发送给addUserServlet,故我们在web.servlet包下创建AddUserServlet.java,为了篇幅,我这里只写doPost方法内容了:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.设置编码
request.setCharacterEncoding("utf-8");
//2.获取参数
Map<String, String[]> map = request.getParameterMap();
//3.封装对象
User user=new User();
try {
BeanUtils.populate(user,map);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
//4.调用Service保存
UserService service=new UserServiceImpl();
service.addUser(user);
//5.重定向到userListServlet接口
response.sendRedirect(request.getContextPath()+"/userListServlet");
}
我们给UserServlet添加方法,我这里列出接口实现:
@Override
public void addUser(User user) {
dao.add(user);
}
再往dao层走,我们给UserDao添加方法,我这里列出接口实现:
@Override
public void add(User user) {
//1.定义SQL(DML)
String sql="INSERT INTO user VALUE(NULL,?,?,?,?,?,?)";
//2.执行(参数要与占位符与数据库字段一一对应)
template.update(sql,
user.getName(),user.getGender(),
user.getAge(),user.getAddress(),
user.getQq(),user.getEmail());
}
如此一来,基本的添加用户信息功能就实现了!
删除用户
接下来我们来实现删除功能,即针对各个用户后面的删除。
前面我们的list.jsp已经写明,当点击删除,就会去调用方法deleteUser,并且将当前遍历对象的id传入。
href="javascript:deleteUser(${user.id});"
故,我们在list.jsp的上面写好对应的方法:
<script type="text/javascript">
function deleteUser(id){
if(confirm("您确定要删除吗?")){
//访问删除接口实现删除
location.href="${pageContext.request.contextPath}/delUserServlet?id="+id;
}
}
</script>
接下来我们在web.service包下创建Servlet——delUserServlet:
@WebServlet("/delUserServlet")
public class DelUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.获取id
String id = request.getParameter("id");
//2.调用service删除
UserService service=new UserServiceImpl();
service.deleteUser(id);
//3.跳转到查询所有的Servlet
response.sendRedirect(request.getContextPath()+"/userListServlet");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
}
给UserService添加方法,我这里只列出接口实现:
@Override
public void deleteUser(String id) {
dao.delete(Integer.parseInt(id));
}
对应的dao包下,UserDaoImpl中接口实现(接口声明就不列出了):
@Override
public void delete(int id) {
//1.定义sql
String sql="DELETE FROM user WHERE id=?";
//2.执行sql
template.update(sql,id);
}
这样就实现了,其实现在套路已经都差不多了。
后面我们还有实现用户的修改、用户的查询、分页等效果,篇幅原因就留到下一篇文章了,这算是我第一个简单的JavaWeb项目,故认真对待,篇幅繁琐,观者见谅。
商业转载 请联系作者获得授权,非商业转载 请标明出处,谢谢