Bootstrap

JavaWeb 笔记:后端部分

后端内容学习

Day 1

1.BS / CS


CS:客户端服务器架构模式
优点:充分利用客户端机器的字段,减轻服务器的负荷
一部分安全要求不高的计算任务和存储任务放在客户端执行,不把所有的 计算和存储都在服务器端执行,从而减轻服务器的压力,也能减轻网络的负 荷
缺点:需要安装、升级维护的成本较+·高

BS:浏览器服务器架构模式
优点:无需安装、维护成本较低
缺点:所有的计算和存储任务都是放在服务器端的,服务器的负荷较重,在服务端计算完成后再把数据传送给客户端,因此客户端和服务器端会进行非常频繁的通信,从而网络的符合较重。

2.Tomcat


1.Tomcat 的安装和配置

1)解压:不要有中文路径和空格
2)目录结构说明
bin:可执行文件目录
conf:配置文件目录
logs:日志文件目录
webapps:项目部署的目录
works:工作目录
temp:临时目录
lib:存放 lib 的目录
3)配置环境变量
因为 tomcat 也是用 Java 和 C 来写的,因此需要 JRE,需要配置 JAVA_HOME
4)启动 tomcat 然后访问主页面
在 bin 目录下的 startup 启动项目,在浏览器中利用 8080 端口来让问主页面
5)新建项目
在 workapp 中新建一个项目文件,再创建一个 WEB-INF 目录

2.在 idea 下新建web项目

3.Servlet入门 - 获取参数


package com.atguigu.servlets;

import com.atguigu.fruit.dao.FruitDAO;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AddServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        System.out.println(name);
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="add" method="post">
    名称:<input type="text" name="fname"/><br/>
    <input type="submit" value="添加" />
</form>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>AddServlet</servlet-name>
        <servlet-class>com.atguigu.servlets.AddServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>AddServlet</servlet-name>
        <url-pattern>/add</url-pattern>
    </servlet-mapping>
    <!-- 
    执行流程
		用户发送一个 add 请求,先查找到 web.xml 在里面找到 url-pattern 是 /add
		然后根据 mapping 中的 servlet-name 对象找到 servlet 中的 name
		再找到其中的 class 类
		根据发送的是 post 请求,自动调用 该类中的 doPost 方法
 -->
</web-app>

Day2

1.Review


1)新建项目 - 新建模块
2)在模块中添加 web
3)创建 artifact 部署包
4)ib - artifact:先有 artifact,后来才添加的 jar 包,此时,这个 jar 包并没有添加到部署包中,另外,我们也可以直接在 WEB-INF 下创建 lib 文件夹,这样不好的地方是这个 lib 只能由当前的项目独享,如果有第二个项目则需要新建 lib。
5)在部署的时候,服务器选项卡 URL 的值指的是 tomcat 启动完成后自动打 开指定的浏览器来访问的网址,启动后报错 404 表示找不到所需要的资源。
6)405 问题,当前请求的方法不支持,比如我们表单 method = post,那么 Servlet 必须对 doPost,否则报 405 错误。
7)空指针或者 NumberFormatException,获取到的结果是空指针,无法根据name 来得到数据。
8) 是以 / 开头的

2.处理请求参数中文乱码的问题


//post 方式下设置编码,防止中文乱码
//get 方式下不需要设置编码,基于 tomcat8
//设置编码的语言必须在获取参数之前
request.setCharacterEncoding("UTF-8");

3.Servlet 继承关系及 service 方法


1)继承关系
javax.servlet.Servlet 接口
javax.servlet.GenericServlet 抽象类
javax.servlet.http.HttpServlet 抽象子类

2)相关方法
java.servlet.Servlet 接口
void init(config) - 初始化方法
void service(request, responce) - 服务方法
void destory() - 销毁方法

javax.servlet.GenericServlet 抽象类
​ void service(request, responce) 仍然是抽象的

javax.servlet.http.HttpServlet 抽象子类
​ void service(qeuest, responce) 不是抽象的

1. String method = req.getMethod(); 获取请求的方式
2. ......else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
   下面是很多 if-else 语句来根据请求方式的不同决定去调用不同的方法
3. 在该抽象类中,不同的 do 方法都差不多,例如,下面是 doPost 方法
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

3)小结
- 继承关系: HttpServlet - GenericServlet - Servlet
Servlet 中的核心方法:init( ) service( ) destory( )
- 服务方法:当有请求过来的时候 service 方法会自动相应,其实是由 tomcat 容器调用的,在 HttpServlet 中,我们会去分析请求 的方式,然后再去决定调哪个 do 开头的方法
但在该类中,这些方法都是 405 风格的,需要我们的子类去实现对应的方法,否则会报 405 错误
因此,我们在新建 Servlet 的时候,我们才会去考虑请求方法,从而决定重写哪个 do 方法


4.Servlet 的生命周期

1)生命周期:从出生到死亡的过程就是生命周期。对应 Servlet 中的三个方法:init( ), service( ), destory( )

2)默认情况下:
第一次接收请求时,这个 Servlet 会进行实例化、初始化、然后服务,
第二次请求开始,每一次都是服务,当容器关闭的时候,所有的 Servlet 实例都会被销毁,
Servlet 实例化,tomcat 只会执行一次,所有的请求都是这个实例去响应的,
默认情况下,第一次请求的时候, tomcat 才会去实例化和初始化,可以提高系统的启动速度,缺点是第一次请求的时候耗时较长,因此如果希望提升系统的启动速度默认情况下就是这样的,可如果希望提升相应的速度,应该设置 Servlet 的响应时机。
Servlet 的初始化时机
默认是第一次接收请求的时候去实例化和初始化,我们可以通过 来设置 servlet 启动的先后顺序,数字越小启动越靠前,最小值为 0。不设置的时候会随着第一个用户发请求的时候再实例化,而设置以后 ,会随着 tomcat 服务的启动而实例化。
Servlet 在容器中是:单例的、线程不安全的。
单例的:所有的请求都是在同一个实例中去相应的
线程不安全:一个线程需要根据这个实例中的某个成员变量值去做逻辑判断,但是在中间的某个实际,另一个线程改变了这个成员变量,从而导致第一个线程的执行路径发生变化,从而发生了线程不安全。
我们已经知道了 servlet 是线程不安全的,没给我们的启发是:尽量不要在 servlet 中去定义成员变量,如果不得不定义成员变量,那么不要去根据成员变量的值去做一些逻辑判断。


5.Http 协议

HTTP 协议,是超文本传输协议。它最大的作用就是确定了请求相应的数据的格式。

1)HTTP 是无状态的
当有两次请求发过来后,服务器无法判断这两次请求是同一个客户端还是不同的客户端发过来的。
无状态带来的现实问题:第一次请求商品到购物车,第二次结账,如果两个请求无法区分是同一个用户的就会导致混乱。
通过会话跟踪技术来解决无状态的问题。

2)HTTP 请求相应包含两个部分:请求和相应

3)请求包含三个部分:请求行、请求消息头和请求主体。
请求行:
包含三个信息:请求的方式,请求的 url,请求的版本一般是 1.1。
请求消息头:
包含了很多客户端需要告诉服务器的信息,比如浏览器型号、版本、能接受的类型、发送信息的类型等等。
请求主体:
分成三种情况:
get 方式,没有请求体,但有一个 queryString
post 方式,有请求体,form data
json格式:有请求体,request payload

4)相应也包含三个部分:相应行、响应头和响应体
相应行:
包含三个信息:协议、相应状态码、相应状态
响应头:
包含了服务器的信息,服务器发给浏览器的信息
响应体:
相应的实际内容


6.session 会话跟踪技术

客户端第一次发请求给服务器,服务器获取 session,如果获取不到,就创建新的,然后相应给客户端。下一次客户端发请求的时候,把 sessionId 带给服务器,服务器就能获取到了,那么服务器就能判断这次请求和上次请求是否是一个客户端。

常用的 API

代码作用
request.getSession( )获取当前会话,没有则创建新的会话
request.getSession(true)效果和不大i参数相同
request.gettSession(false)获取当前会话,没有则返回 null,不会创建
session.getId获取 sessionID
session.isNew判断当前的 session 是否是新的
session.getMaxInactiveInterval( )session 的非激活间隔时长,默认 1800 秒,也就是半个小时。
session.setMaxInactiveInterval( )设置上述的时长
session.invalidate( )让会话立即失效

session 保存作用域
session 保存作用域是和某个 session 对应的

代码
void session.setAttribute(k, v)
Object session.getAttribute(k)
void removeAttributee(k)

7.服务器内部转发以及客户端重定向

request.getRequestDispatcher(“…”).forward(request,response)服务器内部转发
response.sendRedirect(“…”)客户端重定向

服务器内部转发

  • 是一次请求响应的过程,对客户端而言,内部经过了多少次转发,客户端是不知道的,地址栏是没有变化的。

客户端重定向

  • 是两次请求响应的过程,客户端肯定直到请求 url 有变化,地址栏是有变化的。

7.Thymeleaf 视图模板技术

在服务器中引入 Thymeleaf 环境
1)添加 thymeleaf 的 jar 包
2)在 web.xml 中添加配置
配置前缀和后缀

<!-- 在上下文参数中配置视图前缀和视图后缀 -->
<context-param>
    <param-name>view-prefix</param-name>
    <param-value>/WEB-INF/view/</param-value>
</context-param>
<context-param>
    <param-name>view-suffix</param-name>
    <param-value>.html</param-value>
</context-param>

3)新建一个 Servlet 类 viewBaseServlet
4)使得我们 Servlet 继承这个类

@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
    @Override
    public void doGet(HttpServletRequest request , HttpServletResponse response)throws IOException, ServletException {
        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getFruitList();
        //保存到session作用域
        HttpSession session = request.getSession() ;
        session.setAttribute("fruitList",fruitList);
        //此处的视图名称是 index
        //那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
        //逻辑视图名称 :   index
        //物理视图名称 :   view-prefix + 逻辑视图名称 + view-suffix
        //所以真实的视图名称是:      /       index       .html
        super.processTemplate("index",request,response);
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!-- 配置上下文参数 -->
    <context-param>
        <param-name>view-prefix</param-name>
        <param-value>/</param-value>
    </context-param>
    <context-param>
        <param-name>view-suffix</param-name>
        <param-value>.html</param-value>
    </context-param>


</web-app>

5)使用 thymeleaf 标签
th.if th.unless th.each th.text

Day3

1.Servelet 保存作用域


​ 原始情况下,我们可以认为有四个保存作用域:page(页面界别,现在几乎不用)、request(一次请求的相应范围)、session(一次会话的范围)、application(整个应用程序的范围)

演示 request 作用域

解析
​ 第一张图片是两次响应的传递,而 request 的作用域是一次响应,即第一张图片的请求1 和 响应 1 就会失效,上图应用的是客 户端的重定向,需要客户端再次向服务器发送一次请求,而下图中,利用了服务器的内部转发去调用 demo02,是属于一次响应的, 所以存储的变量并不会失效。

@WebServlet("/demo01")
public class Demo01Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.向request保存作用域保存数据
        request.setAttribute("uname","lili");
        //2.客户端重定向
        //response.sendRedirect("demo02");

        //3.服务器端转发
        request.getRequestDispatcher("demo02").forward(request,response);
    }
}

@WebServlet("/demo02")
public class Demo02Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取request保存作用域保存的数据,key为uname
        Object unameObj = request.getAttribute("uname");
        System.out.println("unameObj = " + unameObj);
    }
}

演示 session 作用域

解析
​ session 作用域即是作用于一次会话,上图中向服务器请求服务 demo,下图中的客户端直接向服务器请求打印请求 1 传输的数 据,则会失效,因为上图和下图是属于两个会话。

//演示session保存作用域(demo03和demo04)
@WebServlet("/demo03")
public class Demo03Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.向session保存作用域保存数据
        request.getSession().setAttribute("uname","lili");
        //2.客户端重定向
        response.sendRedirect("demo04");

        //3.服务器端转发
        //request.getRequestDispatcher("demo04").forward(request,response);
    }
}

@WebServlet("/demo04")
public class Demo04Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取session保存作用域保存的数据,key为uname
        Object unameObj = request.getSession().getAttribute("uname");
        System.out.println("unameObj = " + unameObj);
    }
}

演示 application 作用域
解析
在这里插入图片描述

​ 如图所示,下面两个会话去访问第一个会话的内容,是可以访问成功的,因为 application 的作用域是整个程序的运行期间,即 除非重启 tomcat,则作用域中的数据不会失效。

//演示application保存作用域(demo05和demo06)
//Java 中的 ServletContext 类是代表 Servlet 容器中全局上下文的对象。它提供了一些方法,可以访问应用程序的全局属性,例如文件系统路径、MIME 类型和其他应用程序配置。ServletContext 对象也是 Servlet 程序的实例的父类,所以它也提供了一些方法,可以访问和修改 Servlet 程序的属性。此外,ServletContext 对象还提供了一些方法,可以访问 Servlet 容器的其他功能,例如可以向 Servlet 	容器发送请求,以执行其他应用程序功能。
@WebServlet("/demo05")
public class Demo05Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.向application保存作用域保存数据
        //ServletContext : Servlet上下文
        ServletContext application = request.getServletContext();
        application.setAttribute("uname","lili");
        //2.客户端重定向
        response.sendRedirect("demo06");

        //3.服务器端转发
        //request.getRequestDispatcher("demo04").forward(request,response);
    }
}

2.Servlet 的路径问题


相对路径和绝对路径
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

解析
​ 上图中展示的是一个项目的结构,然后叙述了 servlet 的路径问题,比如想在 user 的 login.html 中去引用 css 中的 css 文件, 则可以使用相对路径的方式,但是如果需要引用 css 文件的文件在很深的目录下,则需要使用很多的 …/ 来去找到上级目录,因此容 易出现混淆,则我们需要使用到绝对路径,因此建议以后都使用绝对路径来进行路径的描述。
​ 在 html 中有个 base 标签,能够去指定这个项目的第一个文件,在使用了 base 标签后,后面的问价引用可以直接从第一个文 件开始写起,如 css 的引用只需要写 css/shopping 即可。

3.项目实战1:编辑和修改功能


涉及到的类
index.html
EditServlet
StringUtil
util.html
UpdateServlet
FruitDAOImpl
FruitDAO

index.html

<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta charset="utf-8">
		<link rel="stylesheet" href="css/index.css">
	</head>
	<body>
		<div id="div_container">
			<div id="div_fruit_list">
				<p class="center f30">欢迎使用水果库存后台管理系统</p>
				<table id="tbl_fruit">
					<tr>
						<th class="w20">名称</th>
						<th class="w20">单价</th>
						<th class="w20">库存</th>
						<th>操作</th>
					</tr>
					<tr th:if="${#lists.isEmpty(session.fruitList)}">
						<td colspan="4">对不起,库存为空!</td>
					</tr>
                   	<!--在list中的名称部分设置超链接,使得其转到编辑界面-->
					<tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit : ${session.fruitList}">
                        <!--这里对 edit.do 组件发送 get 请求想其传输自己的 id-->
						<td><a th:text="${fruit.fname}" th:href="@{/edit.do(fid=${fruit.fid})}">苹果</a></td>
						<td th:text="${fruit.price}">5</td>
						<td th:text="${fruit.fcount}">20</td>
						<td></td>
					</tr>
				</table>
			</div>
		</div>
	</body>
</html>

EditServlet

/**
* @author kangqing
* @date 2023/10/7 8:05
*/
@WebServlet("/edit.do")
public class EditServlet extends ViewBaseServlet {
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从 req 中取出 fid 的值,然后再得到该 fruit 对象,从而利用 Thymeleaf 转到编辑页面 util。
        String fidStr = req.getParameter("fid");
        if (StringUtil.isNotEmpty(fidStr)) {
            int fid = Integer.parseInt(fidStr);
            FruitDAO fruitDAO = new FruitDAOImpl();
            Fruit fruit = fruitDAO.getFruitByFid(fid);
            req.setAttribute("fruit", fruit);
            super.processTemplate("/util", req, resp);
        }
    }
}

StringUtil

package com.atguigu.myssm.utils;
/**
* @author kangqing
* @date 2023/10/7 8:09
*/
public class StringUtil {
    //实现对空字符串的判断来简化代码
    public static boolean isEmpty(String str) {
        return str == null || "".equals(str);
    }
    public static boolean isNotEmpty(String str) {
        return !(str == null || "".equals(str));
    }
}

util.html

<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta charset="utf-8">
		<link rel="stylesheet" href="css/util.css">
	</head>
	<body>
		<div id="div_container">
			<div id="div_fruit_list">
				<p class="center f30">修改库存信息</p>
                <!--构建表单项,用于向服务器发送修改的数据,将数据发送到 update.do 的组件中-->
			<form th:action="@{/update.do}" method="post">
				<input type="hidden" name="fid" th:value="${fruit.fid}">
				<table id="tbl_fruit">
					<tr>
						<th class="w20">名称</th>
                        <!--input 里面的是 value 值,利用 ThymeLeaf 来实现对表单项的渲染-->
						<td><input type="text" name="fname" th:value="${fruit.fname}"/></td>
					</tr>
					<tr>
						<th class="w20">单价</th>
						<td><input type="text" name="price" th:value="${fruit.price}"/></td>
					</tr>

					<tr>
						<th class="w20">库存</th>
						<td><input type="text" name="fcount" th:value="${fruit.fcount}"/></td>
					</tr>

					<tr>
						<th class="w20">备注</th>
						<td><input type="text" name="remark" th:value="${fruit.remark}"/></td>
					</tr>

					<tr>
						<td></td>
						<td><input type="submit" value="修改"/></td>
					</tr>

				</table>
			</form>
			</div>
		</div>
	</body>
</html>

UpdateServlet

/**
* @author kangqing
* @date 2023/10/7 9:10
*/
@WebServlet("/update.do")
public class UpdateServlet extends ViewBaseServlet {
    private FruitDAO fruitDao = new FruitDAOImpl();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String fidStr = req.getParameter("fid");
        int fid = Integer.parseInt(fidStr);
        String fname = req.getParameter("fname");
        String priceStr = req.getParameter("price");
        int price = Integer.parseInt(priceStr);
        String fcountStr = req.getParameter("fcount");
        int fcount = Integer.parseInt(fcountStr);
        String remark = req.getParameter("remark");

        Fruit fruit = new Fruit(fid, fname, price, fcount, remark);
        fruitDao.update(fruit);
        IndexServlet indexServlet = new IndexServlet();
        //此处需要重定向,重新给 IndexServlet 发请求,因为上述的操作都是在一次会话中进行的,session 作用域中仍是旧数据
        resp.sendRedirect("index");
    }
}

4.项目实战2:添加和删除功能


删除功能涉及到的类

index.html

<!--<td th:text="x" th:οnclick="'deleatFruit('+${fruit.fid}+')'"></td>-->
<!--通过 JavaScript 的函数去执行删除操作-->
<td th:text="x" th:onclick="'deleteFruit('+${fruit.fid}+')'"></td>

index.js

function deleteFruit(fid) {
    if (confirm("是否确定删除?")) {
        //跳转到 del.do 的模块并且向其发送 get 请求
        window.location.href='del.do?fid='+fid;
    }
}

DeleteServlet

/**
* @author kangqing
* @date 2023/10/7 10:48
*/
@WebServlet("/del.do")
public class DeleteServlet extends ViewBaseServlet {
    private FruitDAO fruitDAO = new FruitDAOImpl();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String fidStr = req.getParameter("fid");
        if (StringUtil.isNotEmpty(fidStr)){
            int fid = Integer.parseInt(fidStr);
            //通过调用 fruitDAO 的 delFruit 方法
            fruitDAO.delFruit(fid);
            resp.sendRedirect("index");
        }
    }
}

添加功能涉及到的类
index.html

<div style="border:0px solid red;width:60%;margin-left:20%;text-align:right;">
	<a href="add.html"  style="border:0px solid blue;margin-bottom:4px;">添加水果库存</a>
</div>

add.html

	<body>
		<div id="div_container">
			<div id="div_fruit_list">
				<p class="center f30">添加库存1</p>
                <!--向add.do组件发送post请求-->
			<form action="add.do" method="post">
				<input type="hidden" name="fid">
				<table id="tbl_fruit">
					<tr>
						<th class="w20">名称</th>
						<td><input type="text" name="fname"/></td>
					</tr>
					<tr>
						<th class="w20">单价</th>
						<td><input type="text" name="price"/></td>
					</tr>

					<tr>
						<th class="w20">库存</th>
						<td><input type="text" name="fcount"/></td>
					</tr>

					<tr>
						<th class="w20">备注</th>
						<td><input type="text" name="remark"/></td>
					</tr>

					<tr>
						<td></td>
						<td><input type="submit" value="添加"/></td>
					</tr>

				</table>
			</form>
			</div>
		</div>
	</body>
</html>

AddServlet

/**
* @author kangqing
* @date 2023/10/7 11:19
*/
@WebServlet("/add.do")
public class AddServlet extends ViewBaseServlet {
    private FruitDAO fruitDAO = new FruitDAOImpl();
    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String fname = req.getParameter("fname");
        int price = Integer.parseInt(req.getParameter("price"));
        int fcount = Integer.parseInt(req.getParameter("fcount"));
        String remark = req.getParameter("remark");
        Fruit fruit = new Fruit(null, fname, price, fcount, remark);

        fruitDAO.addFruit(fruit);
		//客户端重定向到 index 原因和上节相同
        resp.sendRedirect("/index");
    }
}

5.查询的实现


执行查询功能使用的类
index.html

<!--定义了一个表单项去收集传输的关键字,发现显示的方法和 index 中的相同,则使用相同的 Servlet 去处理该请求-->
<form  th:action="@{/index}" style="float:right;margin-right:20%">
					<input type="hidden" name="op" value="search">
					请输入查询的关键词:<input type="text" name="key" th:value="${session.key}">
					<input type="submit" value="查询">
				</form>

IndexServlet

@WebServlet("/index")
public class IndexServlet extends ViewBaseServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        int pageNum = 1;
        String op = req.getParameter("op");
        op = req.getParameter("op");
        String key = null;
        HttpSession session = req.getSession();
        if (StringUtil.isNotEmpty(op) && "search".equals(op)){
            //如果 op 不是 null 则说明是通过查询按钮进入的
            pageNum = 1;
            key = req.getParameter("key");
            if(key == null) {
                key = "";
            }
            //保存 key
            session.setAttribute("key", key);
        } else {
            //如果 op 是 null 则说明不是通过查询按钮进入的,或者是查询之后再去点击第几页,这时候为了保证 key 和上一次的关键字查询一致,则需要利用 session 将 if 中的 key 保存下来。
            String pageNumStr = req.getParameter("pageNum");
            Object keyObj = req.getParameter("key");
            if (StringUtil.isNotEmpty(pageNumStr)) {
                pageNum = Integer.parseInt(pageNumStr);
            }
            if (keyObj == null) {
                key = "";
            } else {
                key  = String.valueOf(keyObj);
            }
        }

        FruitDAO fruitDAO = new FruitDAOImpl();
        List<Fruit> fruitList = fruitDAO.getFruitPageList(pageNum, key);

        Long fruitCount = (fruitDAO.getFruitCount(key)+4) / 5;

        session.setAttribute("fruitList", fruitList);
        session.setAttribute("pageNum", pageNum);
        session.setAttribute("count", fruitCount);

        super.processTemplate("index", req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //表单发送的是 doPost 请求,将其传给 doGet 方法,因为需要的结构是相同的
        doGet(req, resp);
    }
}

;