JavaEE-jsp、el、jstl和显示用户综合案例

1. jsp基础

1.1 jsp概念

  • JSP(java server Pages),java的服务器页面,里面包含html和java代码。其中html负责静态内容,Java代码负责动态内容。
  • 特点:
    • 跨平台
    • 业务代码相分离
    • 组件重组
    • 预编译
  • jsp解决的问题:
    • 简化html书写,动态生成页面

1.2 jsp的执行原理

图解:

1536805943433

  • jsp的底层是一个Servlet。
  • jsp在服务器中先翻译成一个java文件(一个类),该类继承HttpJspBase,而HttpJspBase又是继承httpServlet。故jsp代码中可以直接调用Servlet的request和response对象。
  • 编写在jsp的代码在翻译时会封装到该Servlet的service方法中。
  • 服务器会完成jsp的翻译,编译成.class文件,以及加载的操作,最后将操作之后的html页面发送给浏览器

1.3 jsp的基本语法

1.3.1 jsp注释

  • 格式:<%-- jsp注释 --%>
  • 特点:
    • jsp的注释能注释静态内容和java代码,且不会显示在源码上,更加安全;

    • html注释通过查看网页源代码仍可看到;

      html注释只能注释静态内容(html、css、js),而里面如0有java代码仍能运行

    • 推荐使用jsp的注释。

1.3.2 jsp编写java代码方式

1.3.2.1 脚本片段格式
  • 格式:<% Java代码片段 %>
  • 特点和作用:在脚本片段中书写的Java代码,会翻译到java文件中的_jspService方法中
  • 注意事项:脚本片段可以分开书写,但最后会组合在一起
1.3.2.2 脚本声明
  • 格式:<%! 全局成员 %>

  • 特点和作用:在脚本声明中书写的Java代码,会翻译在类的成员位置上,用来声明成员变量或具有返回值的成员方法

  • 注意事项:声明方法的时候,不要声明与jsp翻译的java文件中默认的一些方法或者变量同名的方法或者变量

1.3.2.3 脚本表达式
  • 格式:<%= 输出页面的内容 %>

  • 特点:脚本表达式书写的java代码,会翻译到java文件中的_jspService方法内,被out.print()输出到页面

    这里的out对象是一个字符输出流

  • 作用:代替response向页面输出内容

  • 注意事项:

    • 脚本表达式和response不能同时使用,否则会出现页面输出顺序和代码顺序错乱的情况;
    • 脚本表达式不能包含分号
1.3.2.4 jsp编写java示例代码:
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>jsp基本语法</title>
</head>
<body>
<h4>1.脚本片段</h4>
<%
    //在jsp内可以编写java代码
    //使用集合存储列表
    List<String> userList = new ArrayList<>();
    userList.add("明明");
    userList.add("大黄");
    userList.add("狗蛋");
    userList.add("jojo");
%>
<table width="50%" border="1px" style="border-collapse: collapse;text-align:center" align="center">
    <tr>
        <th>序号</th>
        <th>姓名</th>
    </tr>
    <%--如果按照原来的做法,在html需要一个个的添加td。而使用jsp可以直接插入Java代码--%>
    <%for (int i = 0; i < userList.size(); i++) {%>
    <tr>
        <td><%out.write(i + 1);%></td>
        <td><%out.write(userList.get(i));%></td>
    </tr>
    <%}%>
</table>

<h4>2.脚本表达式</h4>
<%--脚本表达式可以将out.write()或者out.print()进行简化--%>
<table width="50%" border="1px" style="border-collapse: collapse;text-align:center" align="center">
    <tr>
        <th>序号</th>
        <th>姓名</th>
    </tr>
    <%for (int i = 0; i < userList.size(); i++) {%>
    <tr>
        <td><%=i + 1%>
        </td>
        <td><%=userList.get(i)%>
        </td>
    </tr>
    <%}%>
</table>

<h4>3.脚本声明</h4>
<%--在成员位置声明变量或者方法--%>
<%!
    /*定义方法*/
    public int sum(int i, int j) {
        return i + j;
    }
%>
<%--调用方法--%>
<p>1+2的和:<%=sum(1, 2)%></p>

</body>
</html>

1.4 jsp和Servlet技术的选用

  • servlet:主要负责产生动态资源数据。接收浏览器请求,从数据库中获取数据,并存储在域对象中,然后跳转到jsp页面
  • jsp:主要负责显示布局动态资源数据。获取域对象的数据,并使用html布局动态页面响应浏览器。
图解

1536929667661

1.5 简化jsp

  • 页面上的脚本表达式<%=java代码%>☞使用EL技术代替
  • 页面上的脚本代码片段<%java代码;%>的循环、条件判断等☞使用JSTL技术代替

2. EL表达式

EL(Expression Language):代替jsp中脚本表达式的功能,简化对java代码的操作。

2.1 EL表达式的格式和作用

  • 格式:${域里面的key或者表达式}
  • 作用:从域对象中查找指定的数据
  • 前提:数据都必须存入域对象el才能获取到!!

2.2 EL表达式的使用

2.2.1 EL获得容器(域对象)的数据

  • el通过域对象中的name,来获取对应的value。如果name不一样,可以直接用name来获取value;
  • 默认情况下,el会依次从request==>session==>servletContext的顺序获取name对应value,一旦获取成功将不会继续往下获取。如果多个域对象的name一样,只会按照顺序获取第一个;
  • el如果没有获取到name对应的value,则不会显示,而不是返回null;
  • 如果要获取指定的域对象数据,使用下表的el对象.域对象name获取(重要)。如果不指定则按默认处理。
域对象 对应的el对象
request requestScope
session sessionScope
servletContext applicationScope
<h3>使用el获取域对象数据</h3>
<%
    //往各个域里面存储数据
    request.setAttribute("requestName","requestAdmin");
    session.setAttribute("sessionName","sessionAdmin");
request.getServletContext().setAttribute("servletContextName","servletContextAdmin");
%>
<%--使用el表达式获取域里面的数据--%>
<p>从request里面获取数据:${requestName}</p>
<p>从session里面获取数据:${sessionName}</p>
<p>从servletContext里面获取数据:${servletContextName}</p>

<%
    //往各个域里面存储数据
    request.setAttribute("name","requestAdmin");
    session.setAttribute("name","sessio nAdmin");
    request.getServletContext().setAttribute("name","servletContextAdmin");
%>
<p>从域里面获取数据:${name}</p><%--输出requestAdmin,el获取域里面的数据会依次从request/session/servletContext获取数据,查找到为止--%>

<p>从session域里面name数据:${sessionScope.name}</p>
<p>从servletContext域里面name数据:${applicationScope.name}</p>
<p>从request域里面name数据:${requestScope.name}</p>

2.2.2 EL获取和解析复杂数据

2.2.2.1 获取数组的元素
  • 获取数组:${数组名}

  • 格式:${数组名[index]},其中index为元素的索引

  • 如果元素是一个实体类对象,如果要获取对象的变量,格式为:${数组名[index].变量名}

2.2.2.2 获取集合的元素
  • 获取集合:${List集合名}${Map集合名}

  • List集合获取元素与数组相同,${List集合名[index]}

  • Map集合根据key获取value:${Map集合名[key]}或者${Map集合名.key}

  • 注意事项:设置map集合数据的key,尽量不要出现”.“,如果出现,只能用[]获取

2.2.2.3 获取JavaBean数据
  • 如果要获取JavaBean对象的属性值,可以直接用属性名调取,el自动调用对应的getXxx方法
  • 格式:${JavaBean对象.属性名}${JavaBean对象[属性名]}
2.2.2.4 el获取数据的示例代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>el获取复杂数据</title>
</head>
<body>

<h4>1.使用el获得数组的数据</h4>
<%
    /*添加数据到数组中*/
    User[] users = new User[2];
    users[0] = new User("狗蛋",18);
    users[1] = new User("明明",20);
    //记得el必须要将数据添加到域对象中
    request.setAttribute("users",users );
%>
<p>获取数组里面第一个元素的name属性值:${users[0].name}</p>
<p>获取数组里面第一个元素的age属性值: ${users[0].age}</p>
<p>获取数组里面第二个元素的name属性值:${users[1].name}</p>
<p>获取数组里面第二个元素的age属性值:${users[1].age}</p>

<h4>2.使用el获得list集合的数据</h4>
<%
    /*添加数据到数组中*/
    List<User> list = new ArrayList<>();
    list.add(new User("王全",20));
    list.add(new User("dio",98));
    //记得el必须要将数据添加到域对象中
    request.setAttribute("list",list );
%>
<p>获取List里面第一个元素的name属性值:${list[0].name}</p>
<p>获取List里面第一个元素的age属性值: ${list[0].age}</p>
<p>获取List里面第二个元素的name属性值:${list[1].name}</p>
<p>获取List里面第二个元素的age属性值:${list[1].age}</p>

<h4>3.使用el获得map集合的数据</h4>
<%
    /*添加数据到数组中*/
    Map<String,User> map = new HashMap<>();
    map.put("zs",new User("张三",20));
    map.put("ls",new User("李四",30));
    //记得el必须要将数据添加到域对象中
    request.setAttribute("map",map );
%>
<p>获取Map里面第一个元素的name属性值:${map.zs.name}</p>
<p>获取Map里面第一个元素的age属性值: ${map.zs.age}</p>
<p>获取Map里面第二个元素的name属性值:${map[lisi].name}</p>
<p>获取Map里面第二个元素的age属性值:${map[lisi].age}</p>

<h4>4.使用el获得JavaBean的数据</h4>
<%
    //往域里面写javaBean
    request.setAttribute("user",new User("JoJO",18));
    //el获取javaBean数据时,".属性名"就会自动调用属性的get封装方法。
%>
<p>获取user对象里面name属性值:${user.name}</p>
<p>获取user对象里面age属性值:${user.age}</p>


</body>
</html>

2.2.3 EL执行运算

2.2.3.1 算术运算符
  • 在el表达式中可使用算术运算符
注意事项
  1. 在EL中,只要是数字就能执行运算,EL在执行计算的时候,会将数字除尽,最多保留16位小数(而java中整数相除取整数);
  2. 在EL中,如果在一个算式中有数据不存在,那么这个数据不参与运算,不报错继续执行
  3. 在EL中,算术运算符只能做数学运算,不具备java代码中的拼字符串的功能,即3+"5"的结果是8而不是35。
  4. 使用时都必须先将判断的条件提交到域对象中!
2.2.3.2 逻辑运算符

1536813232709

注意事项
  • el运算符不支持异或^运算
2.2.3.3 比较运算

1536813412813

注意事项
  • 使用比较运算符要保证数据是存在的并且是可比较
2.2.3.4 Empty运算符和三目运算符
  • Empty运算符:${empty 域里面的数据}

    常用的Empty运算 运行结果
    ${empty ""} 如果数据为空字符串,则返回true
    ${empty null} 如果数据为null,返回true
    ${empty list} 如果list元素个数为0,返回true
    ${empty str} 如果字符串为空,返回true

    Empty运算符对应的取反方法

    ${not empty 域里面的数据}

  • 三目运算符,用法与Java一致:${三目运算符}

3. JSTL的核心标签库使用

3.1 JSTL概述

  • JSTL(jsp的标准标签库:Jsp Standard Tag Library)。保存许多服务器端标签(封装了具有特定的功能的java代码,以标签形式编写,代替特定功能的java代码)。

3.2 jstl标签的安装

3.2.1 导包

  • javax.servlet.jsp.jstl.jar

  • jstl-impl.jar

3.2.2 使用taglib指令在jsp页面导入要使用的jstl标签库

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

其中:taglib是导入标签库,uri选择核心标签库core,prefix用于指定将要使用的标签起前缀名,一般是标签库的第一个字母

3.3 常用的jstl标签

3.3.1 if标签

  • 起判断的作用,相当于java代码的if(){}
3.3.1.1 if标签属性介绍
属性名 是否支持el 属性类型 属性描述
test boolean 编写el条件表达式(表达式结果为true执行,为false不执行)
var × String 设置保存test属性的结果保存的域对象的名称
scope × String 指定保存test属性的结果的域对象。

3.3.2 choose标签

  • <c:choose>标签用于指定多个条件选择的组合边界,它必须与<c:when><c:otherwise>标签一起使用。三个标签组合发挥java代码if(){}else if(){} else{}语句的作用

  • 其中: <c:otherwise>,相当于else{}。 <c:when>,相当于if(){}else if(){}<c:when>标签含有test属性,作用与if相同

  • 注意事项:三个标签必须组合使用,一组标签中不能出现两个<c:otherwise>

3.3.3 foreach标签

  • 相当于Java的for循环
属性名 是否支持el 属性类型 属性描述
var × String 在不循环对象的时候,保存的是控制循环的变量;在循环对象的时候,保存的是被循环对象中的元素
items 任何类型 指定要循环的对象
varStatus × String 存储循环过程变量信息(循环索引、循环序号)
begin int 循环开始变量值
end int 循环结束变量值
step int 循环变量递增值,没有设置默认是1
注意事项
  • varStatus,存储循环过程变量信息。在forEach循环过程中产生很多循环信息,比如循环索引,循环序号。
  • forEach标签会将这些信息存储到varStatus对象里面:
    index,循环索引,从0开始
    count,循环序号,从1开始
3.3.3.1 有限次数的循环
  • 格式:

    <c:forEach begin="开始变量值" end="结束变量值" step="变量递增值">
        <%--循环体代码--%>
    </c:forEach>
    
3.3.3.2 循环对象(数组、list、map)
  • 格式:

    <c:forEach items="使用el获取域里存储的集合数据" var="接收循环遍历每个元素对象">
        <%--循环代码--%>
    </c:forEach>
    

3.4 jstl标签示例代码

<%@ page import="model.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>if、choose、foreach</title>
</head>
<body>
<h4>1.if标签</h4>
<c:if test="${true}" scope="session" var="flag">
    if标签示例1
</c:if>
<br/>测试if标签,获取test属性的值,从知道的session容器中获取:${sessionScope.flag}
<%
    session.setAttribute("user","admin" );
%>
<c:if test="${not empty user}">
    <p>您好,欢迎${user}登录</p>
</c:if>
<c:if test="${empty user}">
    <p>您还没登录呢</p>
</c:if>

<h4>2.choose标签</h4>
<c:choose>
    <c:when test="${not empty user}">
        <p>您好,欢迎${user}登录</p>
    </c:when>
    <c:otherwise>
        <p>您还没登录呢</p>
    </c:otherwise>
</c:choose>

<h4>3.foreach标签</h4>
<h5>5.1 有限循环次数</h5>
<c:forEach begin="1" end="5" step="1">
    <%--循环打印5次--%>
    <%="你好,java"%>
<br/>
</c:forEach>

<h5>5.2 遍历集合</h5>
<%
    List<User> userList = new ArrayList<User>();
    userList.add(new User("王全",20));
    userList.add(new User("dio",98));
    userList.add(new User("JoJo",18));
    //一定要往域里面放域对象
    request.setAttribute("userList", userList);
%>
<table width="50%" border="1px" style="border-collapse: collapse;text-align:center" align="center">
    <tr>
        <th>序号</th>
        <th>人员姓名</th>
        <th>人员年龄</th>
    </tr>
    <c:forEach items="${userList}" var="user" varStatus="i">
        <tr>
            <td>${i.count}</td>
            <td>${user.name}</td>
            <td>${user.age}</td>
        </tr>
    </c:forEach>
</table>
</html>

4. 三层架构和MVC模式

图解

1536841440537

其中javabean就只用于负责封装数据

5. MVC+三层架构完成联系人列表案例

5.1 准备工作

  1. 导入包,包括druid、JdbcTemplate、数据库驱动包、beanutils包。放到web/WEB-INF/lib目录下

  2. 准备好druid配置文件

  3. 准备好bootstrap资源,放在web目录下

  4. 构建架构

    1537154771074

  5. 创建实体类

    public class Contact {
        private int id;
        private String name;
        private String sex;
        private int age;
        private String address;
        private String qq;
        private String email;
    
        public Contact() {
        }
    
        public Contact(int id, String name, String sex, int age, String address, String qq, String email) {
            this.id = id;
            this.name = name;
            this.sex = sex;
            this.age = age;
            this.address = address;
            this.qq = qq;
            this.email = email;
        }
        /*此处省略toString()和getter&setter,实际是有的*/
    }
    
  6. 放入JDBCUtils工具类

5.2 三层架构

5.2.1 dao层

/*
底层如果出现异常,要手动抛给上一层。通过web层展示出异常的情况,从而找对应的人维护。
下面用数据库最大的异常SQLException
 */
public class ContactDao {
    private JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());


    public List<Contact> getAllContacts() {
        String sql = "select * from contact;";
        return jdbcTemplate.query(sql,new BeanPropertyRowMapper<Contact>(Contact.class));
    }


    public int addContactToDao(Contact contact) {
        String sql = "insert into contact values(null,?,?,?,?,?,?);";
        return jdbcTemplate.update(sql, contact.getName(), contact.getSex(),
                contact.getAge(), contact.getAddress(), contact.getQq(), contact.getEmail());
    }

    public int deleteContactFromDao(String id) {
        String sql = "delete from contact where id = ?;";
        return jdbcTemplate.update(sql, id);
    }

    public int updateContactToDao(Contact updateContact) {
        System.out.println("dao:" + updateContact);
        String sql = "update contact set sex = ?,age = ?,address = ?,qq = ?,email = ? where id = ?;";
        return jdbcTemplate.update(sql,updateContact.getSex(),updateContact.getAge(),updateContact.getAddress(),
                updateContact.getQq(),updateContact.getEmail(),updateContact.getId());
    }

    public Contact findById(int id) {
        String sql = "select * from contact where id = ?;";
        return jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<>(Contact.class),id);
    }
}

5.2.2 service层

/*
业务层编写要求:
将异常手动抛到web层,由web层根据不同的异常做出不同的提示
(一方面给用户友好的提示,一方面给后台人员提醒是哪部分出问题,从而安排对应的程序员维护)

下面代码是手动抛最大的异常,实际工程可以细分

此外,deleteContact()、updateContact()可以不用返回值
 */
public class ContactService {
    private ContactDao contactDao = new ContactDao();

    public List<Contact> getContacts(){
        return contactDao.getAllContacts();
    }

    public boolean addContact(Contact contact) throws Exception{
        //如果联系人姓名为空,那么视为添加失败
        if (contact.getName() != null) {
            int rows = contactDao.addContactToDao(contact);
            return rows > 0;
        } else {
            return false;
        }
    }

    public boolean deleteContact(String id) throws Exception{
        //根据id删除联系人
       return contactDao.deleteContactFromDao(id) > 0;

    }

    public boolean updateContact(Contact updateContact) throws Exception{
        //调用dao修改联系人
        return contactDao.updateContactToDao(updateContact) > 0;
    }

    public Contact queryById(int id) throws Exception{
        return contactDao.findById(id);
    }
}

5.2.3 web层和用户页面

5.2.3.1 展示所有联系人
浏览器端:list.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--导入jstl包--%>
<%@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>Bootstrap模板</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="${contactList}" var="contact">
        <tr>
            <td>${contact.id}</td>
            <td>${contact.name}</td>
            <td>${contact.sex}</td>
            <td>${contact.age}</td>
            <td>${contact.address}</td>
            <td>${contact.qq}</td>
            <td>${contact.email}</td>
            <td><a class="btn btn-default btn-sm" href="/QueryByIDServlet?id=${contact.id}">修改</a>&nbsp;<a class="btn btn-default btn-sm" href="/DeleteContactServlet?id=${contact.id}">删除</a></td>
        </tr>
        </c:forEach>
        <tr>
            <td colspan="8" align="center"><a class="btn btn-primary" href="add.jsp">添加联系人</a></td>
        </tr>
    </table>
</div>
</body>
</html>
服务器端:
@WebServlet(urlPatterns = "/ContactServlet")
public class ContactServlet extends HttpServlet {

    private ContactService service = new ContactService();

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获得数据库的数据
        List<Contact> contactList = service.getContacts();
        //封装到request域中
        request.setAttribute("contactList", contactList);
        //请求转发到jsp中
        request.getRequestDispatcher("list.jsp").forward(request,response );

    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //*如果post方式的执行内容与get不同,则删掉下面代码重写即可
        doGet(request, response);
    }
}
5.2.3.2 添加联系人:add.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- HTML5文档-->
<!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>
</head>
<body>
<div class="container">
    <center><h3>添加联系人页面</h3></center>
    <form action="/AddContactServlet" 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="sex" value="男" checked="checked"/>男
            <input type="radio" name="sex" 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="jiguan">
                <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" name="qq" placeholder="请输入QQ号码"/>
        </div>

        <div class="form-group">
            <label for="email">Email:</label>
            <input type="text" class="form-control" name="email" placeholder="请输入邮箱地址"/>
        </div>

        <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交" />
            <input class="btn btn-default" type="reset" value="重置" />
            <input class="btn btn-default" type="button" value="返回" onclick="goback()" />
        </div>
    </form>
</div>
<script>
    function goback() {
        history.back();
    }
</script>
</body>
</html>

服务器端:

@WebServlet(urlPatterns = "/AddContactServlet")
public class AddContactServlet extends HttpServlet {

    private ContactService service = new ContactService();

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //解决响应乱码问题
        response.setContentType("text/html;charset=utf-8");
        //解决请求乱码问题
        request.setCharacterEncoding("utf-8");
        try {
            Map<String, String[]> ContactMap = request.getParameterMap();
            Contact contact = new Contact();
            BeanUtils.populate(contact,ContactMap);
            //使用service的添加联系人方法
            boolean flag = service.addContact(contact);
            if (!flag){
                response.getWriter().write("alert('您还没有添加联系人姓名!请重新添加');");
            } else {
                //添加成功请求转发到ContactServlet
                //request.getRequestDispatcher("/ContactServlet").forward(request,response);
                //也可以用重定向。因为用请求转发的话添加完的路径仍为add,会为用户造成困扰,这里就建议用重定向
                response.sendRedirect("/ContactServlet");
            }
        } catch (Exception e) {
            //操作台打印异常给维护人员看
            e.printStackTrace();
            //给用户友好提示
            response.getWriter().write("业务繁忙,请稍后再试");
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //*如果post方式的执行内容与get不同,则删掉下面代码重写即可
        doGet(request, response);
    }
}
5.2.3.3 删除联系人
服务器端:
@WebServlet(urlPatterns = "/DeleteContactServlet")
public class DeleteContactServlet extends HttpServlet {
    /*
    思路:删除联系人前必须知道是哪个联系人,可以通过主键找出需要删除的联系人数据,所以在list.jsp中需要将主键传过来。
         可以通过在请求参数中添加?id=${contact.id}来传递,这是利用了get提交方式发送请求参数
     */
    private ContactService service = new ContactService();

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求参数id
        String id = request.getParameter("id");
        //根据id删除联系人
        try {
            service.deleteContact(id);
        } catch (Exception e) {
            //操作台打印异常给维护人员看
            e.printStackTrace();
            //给用户友好提示
            response.getWriter().write("业务繁忙,请稍后再试");
        }
        //删除完后直接跳转到ContactServlet
        response.sendRedirect("/ContactServlet");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //*如果post方式的执行内容与get不同,则删掉下面代码重写即可
        doGet(request, response);
    }
5.2.3.4 修改联系人

注意:修改联系人首先得将需要修改的联系人信息全部显示,所以先要实现找到联系人的功能,在实现修改的功能

5.2.3.4.1 找到联系人
  • 通过id找到联系人信息,所以在list.jsp中,修改按钮需要跳转到QueryByIDServlet,并将id传输过来
@WebServlet(urlPatterns = "/QueryByIDServlet")
public class QueryByIDServlet extends HttpServlet {

    private ContactService service = new ContactService();

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //根据Id获取信息
        int id = Integer.parseInt(request.getParameter("id"));
        Contact oldContact = null;
        try {
            oldContact = service.queryById(id);
        } catch (Exception e) {
            //操作台打印异常给维护人员看
            e.printStackTrace();
            //给用户友好提示
            response.getWriter().write("业务繁忙,请稍后再试");
        }
        //将对象封装到域中
        request.setAttribute("contact",oldContact );
        //请求转发到update.jsp
        request.getRequestDispatcher("update.jsp").forward(request,response );
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //*如果post方式的执行内容与get不同,则删掉下面代码重写即可
        doGet(request, response);
    }
}
5.2.3.4.2 转到更新页面 update.jsp

此时,更新页面就能将需要修改的联系人信息显示出来

注意事项:非常重要的一点。由于联系人id不需要显示出来,而找到找到需要id(否则id永远为0,则永远找不到该联系人),所以需要使用隐藏input标签将id传递

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
    String path = request.getContextPath();
    String basePath =
            request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<!‐‐ 网页使用的语言 ‐‐>
<html lang="zh-CN">
<head>
    <base href="<%=basePath%>"/>
    <!‐‐ 指定字符集 ‐‐>
    <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>
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <script src="js/jquery-2.1.0.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container" style="width: 400px;">
    <h3 style="text-align: center;">修改联系人</h3>
    <form action="/UpdateContactServlet" method="post">
        <div>
            <%--这里必须要保存原有id,否则提交的时候id永远为0!!!!!这里使用隐藏域保存--%>
            <input type="hidden" name="id" value="${contact.id}">
        </div>
        <div class="form-group">
            <label for="name">姓名:</label>
            <input type="text" class="form-control" id="name" name="name" value="${contact.name}"
                   readonly="readonly" placeholder="请输入姓名" />
        </div>
        <div class="form-group">
            <label>性别:</label>
            <input type="radio" name="sex" value="男" <c:if test="${contact.sex ==
'男'}">checked="checked"</c:if>/>男
            <input type="radio" name="sex" value="女" <c:if test="${contact.sex ==
'女'}">checked="checked"</c:if>/>女
        </div>
        <div class="form-group">
            <label for="age">年龄:</label>
            <input type="text" class="form-control" id="age" name="age" value="${contact.age}"
                   placeholder="请输入年龄" />
        </div>
        <div class="form-group">
            <label for="address">籍贯:</label>
            <select name="address" class="form-control" >
                <option value="广东" <c:if test="${contact.address == '广东'}">selected="selected"
                </c:if>>广东</option>
                <option value="广西" <c:if test="${contact.address == '广西'}">selected="selected"
                </c:if>>广西</option>
                <option value="湖南" <c:if test="${contact.address == '湖南'}">selected="selected"
                </c:if>>湖南</option>
            </select>
        </div>
        <div class="form-group">
            <label for="qq">QQ:</label>
            <input type="text" class="form-control" name="qq" value="${contact.qq}" placeholder="请输入
QQ号码"/>
        </div>
        <div class="form-group">
            <label for="email">Email:</label>
            <input type="text" class="form-control" name="email" value="${contact.email}"
                   placeholder="请输入邮箱地址"/>
        </div>
        <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交" />
            <input class="btn btn-default" type="reset" value="重置" />
            <input class="btn btn-default" type="button" value="返回"/>
        </div>
    </form>
</div>
</body>
</html>
5.2.3.4.2 实现修改

服务器端

@WebServlet(urlPatterns = "/UpdateContactServlet")
public class UpdateContactServlet extends HttpServlet {
    /*
    思路:在修改联系人前首先要获得被修改的联系人信息,先将联系人原信息在update.jsp中显示,然后提交到UpdateContactServlet
         再往数据库修改数据后返回到ContactServlet。
         由于需要在update.jsp显示原信息,可以先根据要修改的联系人id跳转到查询QueryByIDServlet中获取信息,通过与对象将信息传输到update.jsp
     */
    private ContactService service = new ContactService();

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //解决请求乱码问题
        request.setCharacterEncoding("utf-8");
        //将修改数据封装到一个对象中
        Map<String, String[]> updateMap = request.getParameterMap();
        Contact updateContact = new Contact();
        try {
            BeanUtils.populate(updateContact,updateMap );
            System.out.println(updateContact);
            //将封装数据发送给数据库
            service.updateContact(updateContact);
            //重定向到ContactServlet
            response.sendRedirect("/ContactServlet");
        } catch (Exception e) {
            //操作台打印异常给维护人员看
            e.printStackTrace();
            //给用户友好提示
            response.getWriter().write("业务繁忙,请稍后再试");
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //*如果post方式的执行内容与get不同,则删掉下面代码重写即可
        doGet(request, response);
    }
}

5.2.4 本案例的注意事项

  1. 显示联系人的页面是list.jsp,而页面里面的内容需要通过ContactServlet获取,所以不管是显示、添加、删除和更新的操作,最后都要重定向到ContactServlet,然后才能在list.jsp中显示。
  2. 因为展现给用户和维护人员的是web层,所以底层的异常、service层的异常需要往上抛到web层。但是为了用户的体验,我们需要对异常包装给用户。而展现给维护人员的可以不用包装。
  3. 删除和更新是对原有的数据进行操作,一般是通过id找到需要删除和更新的数据。所以需要传递id值。另外更新操作要保证提交表单的时候,原联系人的id值要同时提交,所以用到隐藏input元素。

猜你喜欢

转载自blog.csdn.net/KeepStruggling/article/details/82767913