学习JavaWeb中场案例——三层架构与新手小案例(上)

前言

学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");

开发

  1. 环境搭建
    1. 数据库创建
    2. 创建项目,导入需要的jar包
  2. 编码

测试

部署运维

编码之前

环境搭建

数据库下

上面已经写好SQL语句了,复制过去执行即可。

创建好sometest库下的user表、administrator表(暂定管理员——金庸,123456)。

 

IDEA下

创建一个项目,导入需要的jar包:

  1. druid
  2. BeanUtils
  3. jstl
  4. mysql驱动
  5. spring-jdbc

这里我分享一波:

链接:https://pan.baidu.com/s/1AAHCgcB6td5OuBxsaW4Nlw
提取码:r5q8

 

另外,为了方便我们的前端美化,我们使用bootstrap这一框架,故请在web目录下导入bootstrap需要的js、css等目录文件。

 

分析项目

分析项目:

 

开始编码

1.大体框架

好,接下来我们来具体写代码:

先在web项目的src下创建五个包(前面都是 域名.公司.项目.):

  1. dao
    1. impl
  2. service
    1. impl
  3. web
    1. servlet
  4. util
  5. 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>&nbsp;
                    <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>&nbsp;
                    <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">&laquo;</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">&raquo;</span>
                    </a>
                </li>
                <span style="font-size: 25px;margin: 5px">
                    共16条记录,共4页
                </span>
            </ul>
        </nav>
    </div>

</div>
</body>

bootstrap这个前端框架真是牛逼,轻轻松松帮助我们完成了页面的美化!

 

登录页面

list.jsp这边先放着,我们接下来来完成这个项目的登录页面及其功能。

步骤:

  1. 创建login.jsp
  2. 调整页面,加入验证码功能
  3. 处理登录逻辑

首先是我们的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>&times;</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项目,故认真对待,篇幅繁琐,观者见谅。

 

 

 

 

 

 

商业转载 请联系作者获得授权,非商业转载 请标明出处,谢谢

 

 

发表评论