servlet
javaEE实际上包含很多种规范,13种规范,其中servlet就是javaEE规范之一。
关于系统架构
- C/S架构
- 客户端/服务器架构
- 需要安装特定的客户端软件
- B/S架构
- 浏览器/服务器架构
B/S结构的通信原理
-
WEB系统的访问过程?
- 打开浏览器
- 地址栏输入合法的网址
- 回车
- 浏览器上会展示响应的内容
-
IP地址是什么?
- 计算机在网络中的一个身份证号。在同一个网络当中,IP地址是唯一的
-
端口号是什么?
- 一个端口代表一个软件
- 在同一个机器上,端口后具有唯一性
-
通信步骤:
- 第一步:用户输入网址(url)
- 第二步:域名解析器进行域名解析
- 第三步:浏览器软件在网络中搜索对应ip地址的主机,直到找到这台主机
- 第四步:根据端口号定位主机上的服务器软件
- 第五步:服务器软件得知想要的资源名
- 第六步:服务器软件找到对应资源,并且将资源的内容直接输出响应到浏览器上
- 第七步:浏览器接受到服务器响应的内容后,进行渲染
-
什么是url?
- 统一资源定位符
-
什么是请求?什么是响应?
- 请求和响应实际上说的是数据的流向不同
- 从Browser端发送数据到Server端,我们称为请求(request)
- 从Server端向浏览器Browser端发送数据,我们称为响应(response)
关于WEB服务器软件
-
web服务器有哪些?
-
tomcat
-
jetty
-
-
应用服务器和WEB服务器的关系?
- 应用服务器实现了javaEE的所有规范(javeEE有13种规范)
- web服务器只实现了javaEE的Servlet + JSP两个核心的规范。
Tomcat
-
tomcat下载
-
tomcat使用注意
- 是java语言编写的,运行需要计算机有java环境。
-
tomcat的特点
- 轻量级web服务器
- 体积小
- 运行快
-
Tomcat服务器目录介绍
- bin:存放Tomcat命令文件
- conf:配置文件的目录(例如server.xml文件中可以配置端口号,默认为8080)
- lib:Tomcat核心程序目录
- logs:Tomcat服务器的日志目录
- temp:临时目录
- webapps:存放大量web应用
- work:存放JSP文件,翻译之后的java文件以及编译之后的class文件。
-
Tomcat环境变量配置
- JAVA_HOME:jdk的根
- CATALINA_HOME:tomcat的根
- Path
-
Tomcat启动和关闭
- startup.bat
- shutdown.bat(建议把shutdown.bat文件重命名为stop.bat)【原因:shutdown命令是windows关机命令,避免误操作】
-
测试Tomcat服务器是否启动成功
- 浏览器访问:http://localhost:8080/
Tomcat乱码问题处理
-
控制台乱码
找到tomcat目录下的conf文件夹,打开loggin.properties文件
# 把 java.util.logging.ConsoleHandler.encoding = UTF-8 改为: java.util.logging.ConsoleHandler.encoding = GBK
web应用
一个web应用的请求和响应过程有哪些角色参与?
- 浏览器软件开发团队
- web Server开发团队
- 数据库开发团队
- webapp开发团队
角色之间需要遵循哪些规范,哪些协议?
- webapp团队 和 web Server开发团队 之间有一套规范:javaEE规范之一:Servlet规范【w3c组织指定】
- Servlet规范的作用是什么?
- web Server 和 webapp 解耦合
- Servlet规范的作用是什么?
- 浏览器 和 web Server之间有一套传输协议:HTTP协议(超文本传输协议)【sun公司制定】
- webapp 和 数据库 之间有一套规范:JDBC规范【sun公司制定】
需要做的哪些工作?
-
编写一个类实现Servlet接口
-
将编写的类配置到配置文件中,在配置文件中:指定 请求路径 和 类名 的关系。
注意:
- 配置文件的文件名不能乱写,固定的
- 配置文件的存放路径不能错,固定的
- 文件名、文件路径都是SUN公司制定的Servlet规范中的明细
-
严格来说Servlet其实并不单单是简单的一个接口:
Servlet规范中规定了:
- 一个合格的webapp应该是一个怎样的目录结构
- 一个合格的webapp应该有一个怎样的配置文件
- 一个合格的webapp配置文件路径放在哪里
- 一个合格的webapp中java程序放在哪里
Tomcat服务器要遵循Servlet规范,javaWeb程序员也要遵循Servlet规范,这样Tomcat服务器和webapp才能解耦合。
开发一个带有Servlet(java小程序)的webapp
开发步骤
-
在webapps目录下新建一个目录,起名为:xxx(这个就是项目名)
- 注意:项目xxx就是这个webapp的根
-
在webapp的根下新建一个目录:WEB-INF
- 注意:这个目录是必须,这个目录的名字是Servlet规范中规定的,固定的,禁止自定义命名
- 注意:WEB-INF目录是受保护的。放在这个目录下的资源,浏览器无法通过路径访问。
-
在WEB-INF目录下新建一个目录,命名为:classes
- 注意:这个目录是必须,这个目录的名字必须是全部小写的classes。这个也是Servlet规范中规定的。另外这个目录下一定存放的是java编译后的class文件(字节码文件)
-
在WEB-INF目录下新建一个目录:命名为:lib
- 注意:这个目录不是必须的,但如果一个webapp需要第三方的jar包的话,这个jar包要放到这个目录下,这个目录名也是固定的
-
在WEB-INF目录下新建一个文件:命名为:web.xml
- 注意:这个文件是必须,文件名和存放路径也是固定的。这个是一个配置文件,这个文件中描述了请求路径和Servlet类之间的对照关系。
- 建议:最好从别的webapp中拷贝过来,不要自己手写
下面是最简洁的配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0" metadata-complete="true"> </web-app>
-
编写java程序,这个java小程序也不能随意开发。这个java小程序必须实现Servlet接口。
- Servlet接口不在jdk中(Servlet不是javaSE的,而是javaEE)
- Servlet接口是javaEE规范中的一员
-
编译java小程序
- 重点:如果没有用集成工具开发时,需要在环境变量中配置Servlet的jar包路径
-
把编译之后的文件目录拷贝到WEB-INF/classes目录下
-
在web.xml文件中编写配置信息,让“请求路径”和“Servlet类名”关联到一起
- 即:在web.xml文件中注册Servlet
<!-- Servlet 描述信息 --> <!-- 任何一个servlet都对应一个servle-mapping --> <servlet> <servlet-name></servlet-name> <!-- 这个位置必须是带包名的全限定类名 --> <servlet-class></servlet-class> </servlet> <!-- Servlet 映射信息 --> <servlet-mapping> <!-- 这里可以顺便写,不过写的内容要和上面的一致 --> <servlet-name></servlet-name> <!-- 这里路径可以顺便写,但是必须以'/'开头 --> <url-pattern></url-pattern> </servlet-mapping>
-
启动Tomcat服务器
-
浏览器输入url,访问
- **注意:**浏览器上的请求路径和web.xml文件中的url-pattern一致;但唯一区别在于:浏览器的请求路径带项目名,url-pattern不带项目名
- 以后不需要我们编写main方法了,Tomcat服务器负责调用main方法,Tomcat服务器启动的时候执行的就是main方法,我们javaWeb程序员只需要编写Servlet接口的实现,然后将其注册到web.xml文件中即可。
合法的webapp目录结构
webapproot
|---- WEB-INF
|---- classes(存放字节码)
|---- lib(存放第三方类库)
|---- web.xml(注册Servlet)
|---- html
|---- css
|---- javascript
|---- images
...
案例
注意:需要引入Servlet.jar包
案例1
com.bz.demo01.UserServlet.java
package com.bz.demo01;
import jakarta.servlet.*;
import java.io.IOException;
public class UserServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
web.xml
注册Servlet
<servlet>
<servlet-name>userservlet</servlet-name>
<servlet-class>com.bz.demo01.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userservlet</servlet-name>
<url-pattern>/user</url-pattern>
</servlet-mapping>
案例2
注意:把mysql jdbc驱动jar包拷贝到WEB-INF目录的lib(如果不存在需要创建)目录下
com.bz.demo01.UserServlet.java
package com.bz.demo01;
import jakarta.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
/**
* 原始的Servlet实现
*/
public class UserServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
try {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://ip地址/库名", "mysql用户名", "mysql密码");
// 3.获取预编译数据库操作对象
String sql = "select loginName, loginPwd, name from t_user";
ps = conn.prepareStatement(sql);
// 4.执行sql
rs = ps.executeQuery();
// 5.结果集处理
while(rs.next()) {
System.out.println(rs.getString("loginName")
+ "\t" + rs.getString("loginPwd")
+ "\t" + rs.getString("name"));
out.print("<h1>" + rs.getString("loginName")
+ "\t" + rs.getString("loginPwd")
+ "\t" + rs.getString("name") + "</h1><br>");
}
} catch(Exception e) {
e.printStackTrace();
} finally {
// 6.释放资源
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
web.xml
<servlet>
<servlet-name>userlist</servlet-name>
<servlet-class>com.bz.demo01.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userlist</servlet-name>
<url-pattern>/userlist</url-pattern>
</servlet-mapping>
关于javaEE的版本
- javaEE目前最高版本为“javaEE8”
- javaEE被Oracle收购后,捐献给Apache,Apache将“javaEE”改名为"jakarta"。
- 所以"javaEE9"开始叫做"jakartaEE9"
- javaEE8时对应的Servlet类名是:javax.servlet.Servlet【Tomcat 9、Tomcat 9-】
- jakartaEE9开始对应的Servlet类名为:jakarta.servlet.Servlet【Tomcat 10、Tomcat 10+】
IDEA 项目搭建
-
创建项目
-
选择项
-
勾选项
-
src目录下创建包、类
-
模块设置,可以设置部署路径、添加jar包等操作
6. 添加jar包
- 配置部署路径(非必须)
8. 配置Tomcat
-
Tomcat详细配置
项目部署运行报错
1.java: 错误: 无效的源发行版:17
ServletConfig
是什么?
- Servlet对象的配置信息对象
- 是一个接口,是Servlet规范的一员
- ServletConfig对象中封装了web.xml文件中标签中的配置信息
- 一个Servlet对应一个ServletConfig对象
是谁创建?何时创建?
- Servlet对象是Tomcat服务器创建,并且ServletConfig对象也是Tomcat服务器创建
- 默认情况下,在用户第一次请求时创建
常用方法
// 1.通过初始化参数的name获取value
public String getInitParameter(String name);
// 2.获取所有初始化参数的name
public Enumeration<String> getInitParameterNames();
// 3.获取ServletContext对象
public ServletContext getServletContext();
// 4.获取Servlet的name
public String getServletName();
案例
注意:把mysql jdbc驱动jar包拷贝到WEB-INF目录的lib(如果不存在需要创建)目录下
com.bz.demo02.UserServlet.java
package com.bz.demo02;
import jakarta.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
import java.util.Enumeration;
/**
* 原始的Servlet实现
* ServletConfig案例
*/
public class UserServlet implements Servlet {
private ServletConfig config;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
this.config = servletConfig;
}
@Override
public ServletConfig getServletConfig() {
return this.config;
}
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
// 设置响应内容类型
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// 获取所有初始化参数的name
Enumeration<String> initParameterNames = this.config.getInitParameterNames();
while(initParameterNames.hasMoreElements()) {
String name = initParameterNames.nextElement();
// 通过初始化参数的name获取value
String value = this.config.getInitParameter(name);
out.print(name + " : " + value + "<br>");
}
try {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://ip地址/库名", "mysql用户名", "mysql密码");
// 3.获取预编译数据库操作对象
String sql = "select loginName, loginPwd, name from t_user";
ps = conn.prepareStatement(sql);
// 4.执行sql
rs = ps.executeQuery();
// 5.结果集处理
while(rs.next()) {
System.out.println(rs.getString("loginName")
+ "\t" + rs.getString("loginPwd")
+ "\t" + rs.getString("name"));
out.print("<h1>" + rs.getString("loginName")
+ "\t" + rs.getString("loginPwd")
+ "\t" + rs.getString("name") + "</h1><br>");
}
} catch(Exception e) {
e.printStackTrace();
} finally {
// 6.释放资源
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
web.xml
<servlet>
<servlet-name>userlist2</servlet-name>
<servlet-class>com.bz.demo02.UserServlet</servlet-class>
<!-- start 初始化字段值 -->
<init-param>
<param-name>aaa</param-name>
<param-value>111</param-value>
</init-param>
<init-param>
<param-name>bbb</param-name>
<param-value>222</param-value>
</init-param>
<!-- end 初始化字段值 -->
</servlet>
<servlet-mapping>
<servlet-name>userlist2</servlet-name>
<url-pattern>/userlist2</url-pattern>
</servlet-mapping>
ServletContext
是什么?
- 是一个接口,是Servlet规范的一员。
- Servlet对象的环境对象(Servlet对象的上下文对象)
- ServletContext对象其实对应的就是整个web.xml文件
- ServletContext对象是应用级对象,也称为:应用域
例子
50个学生,每个学生都是一个Servlet,这50个学生都在同一个教室里,那么这个教室就相当于ServletContext对象。
所以,放在ServletContext对象当中的数据,所有的Servlet一定是共享的。
是谁创建?何时创建?何时销毁?
- ServletContext对象是WEB服务器创建的
- ServletContext对象在WEB服务器启动时创建的
- ServletContext对象在服务器关闭时销毁
注意
- 对于一个webapp来说,ServletContext对象只有一个。
- Tomcat是一个容器,一个容器可以放多个webapp,一个webapp对应一个ServletContext对象。
常用方法
// 1.通过初始化参数的name获取value
public String getInitParameter(String name);
// 2.获取所有初始化参数的name
public Enumeration<String> getInitParameterNames();
// 3.获取根路径
public String getContextPath();
// 4.获取绝对路径(真实路径)
public String getRealPath(String path);
// 5.记录日志
// 日志会自动记录到CATALINA_HOME/logs目录下的localhost.2022-07-18.log文件
public void log(String message);
// 6.向ServletContext应用域存数据
public void setAttribute(String name, Object value);
// 7.向ServletContext应用域取数据
public Object getAttribute(String name);
// 8.向ServletContext应用域删除数据
public void removeAttribute(String name);
案例
案例1
com.bz.demo03.UserServlet.java
package com.bz.demo03;
import jakarta.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
import java.util.Enumeration;
/**
* 原始的Servlet实现
* ServletContext案例
* 日志记录
*/
public class UserServlet implements Servlet {
private ServletConfig config;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
this.config = servletConfig;
}
@Override
public ServletConfig getServletConfig() {
return this.config;
}
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
ServletContext servletContext = this.config.getServletContext();
// 项目根路径
out.print("项目根路径:" + servletContext.getContextPath() + "<br>");
// 获取web目录下的index.html文件
out.print(servletContext.getRealPath("/index.html") + "<br>");
// 记录日志
// 日志会自动记录到CATALINA_HOME/logs目录下的localhost.2022-07-18.log文件
servletContext.log("日志记录");
servletContext.log("异常日志", new RuntimeException("自定义异常"));
Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
while(initParameterNames.hasMoreElements()) {
String name = initParameterNames.nextElement();
String value = servletContext.getInitParameter(name);
out.print(name + " : " + value + "<br>");
}
try {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://ip地址/库名", "mysql用户名", "mysql密码");
// 3.获取预编译数据库操作对象
String sql = "select loginName, loginPwd, name from t_user";
ps = conn.prepareStatement(sql);
// 4.执行sql
rs = ps.executeQuery();
// 5.结果集处理
while(rs.next()) {
System.out.println(rs.getString("loginName")
+ "\t" + rs.getString("loginPwd")
+ "\t" + rs.getString("name"));
out.print("<h1>" + rs.getString("loginName")
+ "\t" + rs.getString("loginPwd")
+ "\t" + rs.getString("name") + "</h1><br>");
}
} catch(Exception e) {
e.printStackTrace();
} finally {
// 6.释放资源
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
web.xml
<!-- context-param配置信息,所有Servlet都共享 -->
<context-param>
<param-name>ccc</param-name>
<param-value>111</param-value>
</context-param>
<context-param>
<param-name>ddd</param-name>
<param-value>222</param-value>
</context-param>
<!-- context-param配置信息,所有Servlet都共享 -->
<servlet>
<servlet-name>userlist3</servlet-name>
<servlet-class>com.bz.demo03.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userlist3</servlet-name>
<url-pattern>/userlist3</url-pattern>
</servlet-mapping>
案例2
com.bz.demo04.UserServlet.java
package com.bz.demo04;
import jakarta.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
/**
* 原始的Servlet实现
* ServletContext应用域 存、取、删除数据
*/
public class UserServlet implements Servlet {
private ServletConfig config;
@Override
public void init(ServletConfig servletConfig) throws ServletException {
this.config = servletConfig;
}
@Override
public ServletConfig getServletConfig() {
return this.config;
}
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
response.setContentType("text/html");
PrintWriter out = response.getWriter();
ServletContext servletContext = this.config.getServletContext();
servletContext.setAttribute("name", "bz");
out.print(servletContext.getAttribute("name") + "<br>");
servletContext.removeAttribute("name");
out.print(servletContext.getAttribute("name") + "<br>");
try {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取连接
conn = DriverManager.getConnection("jdbc:mysql://ip地址/库名", "mysql用户名", "mysql密码");
// 3.获取预编译数据库操作对象
String sql = "select loginName, loginPwd, name from t_user";
ps = conn.prepareStatement(sql);
// 4.执行sql
rs = ps.executeQuery();
// 5.结果集处理
while(rs.next()) {
System.out.println(rs.getString("loginName")
+ "\t" + rs.getString("loginPwd")
+ "\t" + rs.getString("name"));
out.print("<h1>" + rs.getString("loginName")
+ "\t" + rs.getString("loginPwd")
+ "\t" + rs.getString("name") + "</h1><br>");
}
} catch(Exception e) {
e.printStackTrace();
} finally {
// 6.释放资源
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
web.xml
<servlet>
<servlet-name>userlist4</servlet-name>
<servlet-class>com.bz.demo04.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userlist4</servlet-name>
<url-pattern>/userlist4</url-pattern>
</servlet-mapping>
Tomcat服务器的logs目录下有哪些日志文件?
- catalina.2022-07-18.log
- 服务器端的java程序运行的控制台信息
- localhost.2022-07-18.log
- ServletContext对象调用log方法记录的日志信息
- localhost_access_log.2022-07-18.txt
- 访问日志
设计模式:适配器 - GenericServlet类
作用
- 简化代码,不需要程序员每次实现类时都实现全部方法
注意
以后的开发中我们在编写Servlet类时,实际上是不会去直接继承GenericServlet类的;因为我们采用的是B/S架构,这种系统是基于HTTP超文本传输协议,在Servlet规范当中,提供了一个类:HttpServlet,它是专门为HTTP协议准备的,所以我们编写的Servlet类要继承的是HttpServlet(HttpServlet是HTTP协议专用的)
案例
com.bz.demo02.UserServlet.java
package com.bz.demo02;
import jakarta.servlet.GenericServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
/**
* 使用适配器模式(GenericServlet)实现Servlet
*/
public class UserServlet extends GenericServlet {
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet res = null;
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://ip地址/库名", "mysql用户名", "mysql密码");
String sql = "select loginName, loginPwd, name from t_user";
ps = conn.prepareStatement(sql);
res = ps.executeQuery();
while(res.next()) {
String loginName = res.getString("loginName");
String loginPwd = res.getString("loginPwd");
String name = res.getString("name");
System.out.println(loginName + "\t" + loginPwd + "\t" + name);
pw.print(loginName + "\t\t" + loginPwd + "\t\t" + name);
}
} catch(Exception e) {
e.printStackTrace();
} finally {
if (res != null) {
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
web.xml
<servlet>
<servlet-name>userlist2</servlet-name>
<servlet-class>com.bz.demo02.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>userlist2</servlet-name>
<url-pattern>/userlist2</url-pattern>
</servlet-mapping>
适配器 - HttpServlet类
继承关系
jakarta.servlet.Servlet(接口)
jakarta.servlet.GenericServlet implements Servlet (抽象类)
jakarta.servlet.http.HttpServlet extends GenericServlet(抽象类)
以后我们写的Servlet类要继承HttpServlet类
HTTP协议
什么是协议?
- 协议本质就是一套规范,一套标准。
什么是HTTP协议?
- 是W3C制定的一种超文本传输协议。
- 这种协议游走在B和S之间;B向S发数据要遵循HTTP协议,S向B发数据同样需要遵循HTTP协议,这样B和S才能解耦合。
- 什么是解耦合?
- B不依赖S,S也不依赖B
- 什么是解耦合?
- HTTP协议包括:
- 请求协议
- 浏览器 向 WEB服务器发送数据
- 响应协议
- WEB服务器 向 浏览器发送数据
- 请求协议
HTTP的请求协议
HTTP的请求协议包括:4部分
- 请求行
- 包括:
- 请求方式(7种)
- get(常用)
- post(常用)
- delete
- put
- head
- options
- trace
- URI
- 什么是URI?
- 统一资源标识符,代表网络中某个资源的名字,但是通过URI是无法定位资源的。
- 什么是URL?
- 统一资源定位符,代表网络中某个资源,同时,通过URL是可以定位到该资源的。
- URL和URI有什么关系?有什么区别?
- URL包括URI
- URL可以定位资源,URI无法定位资源。
- 什么是URI?
- HTTP协议版本号
- 请求方式(7种)
- 包括:
- 请求头
- 请求的主机
- 主机的端口
- 浏览器信息
- 平台信息
- cookie等信息
- ……
- 空白行
- 空白行用来区分“请求头”和“请求体”
- 请求体
- 向服务器发送的具体数据
HTTP请求协议的具体报文:GET请求
GET /servlet04/getServlet?loginName=bz&loginPwd=123 HTTP/1.1 请求行
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 请求头
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Host: 127.0.0.1:8080
Referer: http://127.0.0.1:8080/servlet04/index.html
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
空白行
请求体
HTTP请求协议的具体报文:POST请求
POST /servlet04/postServlet HTTP/1.1 请求行
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 请求头
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 20
Content-Type: application/x-www-form-urlencoded
Host: 127.0.0.1:8080
Origin: http://127.0.0.1:8080
Referer: http://127.0.0.1:8080/servlet04/index.html
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
空白行
loginName=bz&loginPwd=111 请求体
GET请求和POST请求的区别?
- get请求发送数据时,数据会挂在URI后面(在“请求行”发送数据)。这样会导致发送的数据回显在浏览器地址栏上
- get请求只能发送普通字符串,并且发送的字符串长度有限制,不同浏览器限制不同。
- get请求比较适合从服务器端获取数据,所以是绝对安全的
- get请求支持缓存
- post请求发送数据时,在请求体当中发送数据(数据会存储在Form Data)。不会回显到浏览器地址栏上
- post请求可以发送任何类型的数据
- post请求可以发送大数据量,理论上没有限制
- post请求比较适合向服务器端传送数据,所以是危险的
- post请求不支持缓存
- get请求和post请求发送的数据格式相同,格式为:name=val&name=val…
GET请求和POST请求如何选择?
- get请求比较适合从服务器端获取数据
- post请求比较适合向服务器端传送数据
- 如果表单中有敏感信息,建议使用post请求,因为get请求会回显敏感信息到地址栏
- 文件上传,一定是post请求,因为要传的数据不是普通文本
HTTP的响应协议
HTTP的响应协议包括:4部分
- 状态行
- 组成:
- 协议版本号(HTTP/1.1)
- 状态码(HTTP协议中规定的响应状态号,不同的响应结果对应不同的号码)
- 200:表示请求响应成功,正常结束
- 404:表示访问的资源不存在,通常要么是路径写错,要么是服务器对应的资源不存在或者没有启动成功
- 405:表示前端发送的请求方式与后端请求的处理方式不一致
- 比如:前端是POST请求,后端的处理方式按照get方式进行处理是,发生405
- 比如:前端是GET请求,后端的处理方式按照post方式进行处理是,发生405
- 500:表示服务器端的程序发生异常,一般认为是服务器端的错误导致的
- 以4开头的状态码,一般来说是浏览器端的错误导致的。
- 以5开头的状态码,一般来说是服务器端的错误导致的。
- 状态的描述信息
- ok:表示正常成功结束
- not found:表示资源找不到
- 组成:
- 响应头
- 空白行
- 响应体
HTTP响应协议的具体报文
HTTP/1.1 200 ok 状态行
Content-Type: text/html;charset=UTF-8 响应头
Content-Length: 150
Date: Tue, 19 Jul 2022 02:48:11 GMT
Keep-Alive: timeout=20
Connection: keep-alive
空白行
<!DOCTYPE html> 响应体
<html>
<head>
<meta charset="UTF-8">
<title>getServlet</title>
</head>
<body>
<h1>getServlet</h1>
</body>
</html>
模板方法设计模式
什么是设计模式?
- 某个问题的固定的解决方案
有哪些设计模式?
- GoF设计模式
- 通常我们所说的23种设计模式(Gang of Four)
- 单例模式
- 工厂模式
- 代理模式
- 门面模式
- 责任链设计模式
- 观察者模式
- …
- JavaEE设计模式
- DAO
- DTO
- VO
- PO
- pojo
- …
- …
什么是模板方法设计模式?
- 在模板类的模板方法当中定义核心算法的骨架,具体的实现步骤可以延迟到子类当中实现
- 模板类通常是一个抽象类,模板类当中的模板方法定义核心算法,这个方法建议用final修饰
案例
没有使用模板方法设计模式
Student类
package com.bz.demo01;
/**
* Student类和Teacher类存在问题:
* 1.算法没有得到重复的使用
* 2.代码没有得到复用
*/
public class Student {
// 学生的一天
public void day() {
qiChuan();
xiShu();
chiZaoCan();
doSome();
chiWanFan();
shuiJiao();
}
public void qiChuan() {
System.out.println("起床");
}
public void xiShu() {
System.out.println("洗漱");
}
public void chiZaoCan() {
System.out.println("吃早餐");
}
public void doSome() {
System.out.println("上学,学习");
}
public void chiWanFan() {
System.out.println("吃晚饭");
}
public void shuiJiao() {
System.out.println("睡觉");
}
}
Teacher类
package com.bz.demo01;
/**
* Student类和Teacher类存在问题:
* 1.算法没有得到重复的使用
* 2.代码没有得到复用
*/
public class Teacher {
// 老师的一天
public void day() {
qiChuan();
xiShu();
chiZaoCan();
doSome();
chiWanFan();
shuiJiao();
}
public void qiChuan() {
System.out.println("起床");
}
public void xiShu() {
System.out.println("洗漱");
}
public void chiZaoCan() {
System.out.println("吃早餐");
}
public void doSome() {
System.out.println("上班,授课");
}
public void chiWanFan() {
System.out.println("吃晚饭");
}
public void shuiJiao() {
System.out.println("睡觉");
}
}
使用模板方法设计模式
Person类
package com.bz.demo02;
/**
* Student和Tearcher都是Person
*/
// 抽象方法只能出现在抽象类中
public abstract class Person { // 模板类通常是抽象类
/*
模版方法
这里使用final修饰,这个方法无法被覆盖,这样核心的算法也可以得到保护
模板方法定义核心的算法骨架,具体的实现步骤可以延迟到子类当中去实现
核心算法一方面是得到了保护,不能被改变;另一方面就是算法得到了重复使用。
另外代码也得到了复用,因为算法中某些步骤的代码是固定的,这些固定的代码不会随着子类的变化而变化,这一部分的代码可以写到模板类当中
*/
public final void day() {
qiChuan();
xiShu();
chiZaoCan();
doSome();
chiWanFan();
shuiJiao();
}
public void qiChuan() {
System.out.println("起床");
}
public void xiShu() {
System.out.println("洗漱");
}
public void chiZaoCan() {
System.out.println("吃早餐");
}
// 这个方法每个子类都不一样,所以定义为抽象方法,子类继承后重写该方法
public abstract void doSome();
public void chiWanFan() {
System.out.println("吃晚饭");
}
public void shuiJiao() {
System.out.println("睡觉");
}
}
Student类
package com.bz.demo02;
public class Student extends Person {
@Override
public void doSome() {
System.out.println("上学,学习");
}
}
Teacher类
package com.bz.demo02;
public class Teacher extends Person {
@Override
public void doSome() {
System.out.println("上班,授课");
}
}
Test类
package com.bz.demo02;
public class Test {
public static void main(String[] args) {
Person p1 = new Teacher();
Person p2 = new Student();
p1.day();
System.out.println("\n------------------------------------\n");
p2.day();
}
}
HttpServlet源码分析
- HttpServlet类是专门为Http协议准备的,比GenericServlet类更加适合HTTP协议下的开发
- HttpServlet类在jakarta.servlet.http.HttpServlet包下
- 到目前为止接触了Servlet规范中的哪些接口?
- jakarta.servlet.Servlet:核心接口(接口)
- jakarta.servlet.ServletConfig:Servlet配置信息接口(接口)
- jakarta.servlet.ServletContext:Servlet上下文接口(接口)
- jakarta.servlet.ServletRequest:Servlet请求接口(接口)
- jakarta.servlet.ServletResponse:Servlet响应接口(接口)
- jakarta.servlet.ServletException:Servlet异常(类)
- jakarta.servlet.GenericServlet:标准通用的Servlet类(抽象类)
- jakarta.servlet.http包下有哪些类和接口?
- jakarta.servlet.http.HttpServlet:(HTTP协议专用的Servlet类,抽象类)
- jakarta.servlet.http.HttpServletRequest:(HTTP协议专用的请求对象)
- jakarta.servlet.http.HttpServletResponse:(HTTP协议专用的响应对象)
- HttpServletRequest对象中封装了什么信息?
- HttpServletRequest简称request对象
- HttpServletRequest中封装了请求协议的全部内容
- HttpServletResponse对象是专门用来响应HTTP协议到浏览器的。
HttpServletRequest常用方法
-
获取前端浏览器用户提交的数据
String getParameter(String name); Map<String, String[]> getParameterMap(); Enumeration<String> getParameterNames(); String[] getParameterValues(String name);
-
其它常用方法
// 获取客户端ip地址 String ip = request.getRemoteAddr(); // Tomcat9之前版本请求含有中文会乱码,可以使用下面语句设置为utf-8 // 设置请求体的字符集(post请求的数据才是放在请求体) request.setCharacterEncoding("UTF-8"); // 设置响应体编码 response.setContentType("text/html;charset=UTF-8"); // 获取应用的根路径 String contextPath = request.getContextPath(); // 获取请求方式 String method = request.getMethod(); // 获取请求的URI String requestURI = request.getRequestURI(); // 获取Servlet路径 String servletPath = request.getServletPath();
请求域对象
- ”请求域“对象要比“应用域”对象范围小很多,生命周期短很多,请求域只在一次请求内有效
- 一个请求对象(request)对应一个请求域。一次请求结束后,这个请求域就销毁了
- 请求域对象也有三个方法
- void setAttribute(String name, Object value); // 6.向域存数据
- Object getAttribute(String name); // 7.向域取数据
- void removeAttribute(String name); // 向域删除数据
- 请求域和应用域的选用原则?
- 尽量使用小的域对象,因为小的域对象占用的资源较少
Servlet类的开发步骤(最终版):
- 编写一个Servlet类,继承HttpServlet类
- 重写doGet方法或者doPost方法(具体看实际需求)
- 将Servlet类配置到web.xml文件当中(又叫:注册Servlet)
- 准备前端页面调用
关于一个Web站点的欢迎页面
什么是一个web站点的欢迎页面?
- 对于一个webapp来说,我们是可以设置它的欢迎页面的。
- 设置了欢迎页面之后,当你访问这个webapp的时候,或者访问这个web站点时,没有指定任何“资源路径”,这时会默认访问你的欢迎页面。
- 注意:一个webapp可以有多个欢迎页,越靠上优先级越高,找不到时继续向下找。
如何设置欢迎页?
-
目录结构
webapp |---- WEB-INF |---- web.xml |---- index.html
-
在web目录下新建login.html页面
-
在web.xml中配置
<welcome-file-list> <welcome-file>login.html</welcome-file> </welcome-file-list>
<!-- 欢迎页可以是一个Servlet --> <!-- 取url-pattern的配置,不要开头的“/” --> <welcome-file-list> <welcome-file>loginPage</welcome-file> </welcome-file-list> <servlet> <servlet-name>getServlet</servlet-name> <servlet-class>com.bz.demo03.GetServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>getServlet</servlet-name> <url-pattern>/loginPage</url-pattern> </servlet-mapping>
注意:
- 配置欢迎页时,路径不需要以“/”开始;这个路径默认是从webapp的根下开始查找
-
启动服务器,浏览器输入地址访问
哪几个位置可以配置欢迎页?
- 在webapp内部的web.xml文件中配置(属于局部配置)
- 在CATALINA_HOME(即:Tomcat服务器根目录)/conf/web.xml文件中配置(属于全局配置)
- 注意原则:局部配置优先(就近原则)
请求转发
- 注意:
- 只要是Web容器的合法资源都能进行转发,不单单是Servlet。转发的路径以“/”开始,不要写项目名。
AServlet.java
package com.bz.demo04;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String ip = request.getRemoteAddr();
request.setAttribute("ip", ip);
Object ip1 = request.getAttribute("ip");
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.print("<h1>" + ip1 + "</h1>");
/*
get请求含有中文数据乱码的修改方案(Tomcat8之前才需要修改):
Tomcat的server.xml配置文件的Connector标签中,添加URIEncoding="UTF-8"
*/
// 获取请求转发器对象
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/b");
// 调用转发器的forward方法完成跳转/转发
requestDispatcher.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Tomcat9之前版本请求含有中文会乱码,可以使用下面语句设置为utf-8
// 设置请求体的字符集(post请求的数据才是放在请求体)
request.setCharacterEncoding("UTF-8");
}
}
BServlet.java
package com.bz.demo04;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class BServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
// response.setContentType("text/html;charset=UTF-8");
Object ip = request.getAttribute("ip");
PrintWriter out = response.getWriter();
out.print("<h1>" + ip + "</h1>");
}
}
web.xml
<servlet>
<servlet-name>a</servlet-name>
<servlet-class>com.bz.demo04.AServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>a</servlet-name>
<url-pattern>/a</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>b</servlet-name>
<servlet-class>com.bz.demo04.BServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>b</servlet-name>
<url-pattern>/b</url-pattern>
</servlet-mapping>
实现资源跳转
完成跳转的方式
- 转发
- 重定向
转发
-
语法
// servlet名为:/dept/list // 获取请求转发器对象,不需要加项目名 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/dept/list"); // 调用请求转发器对象的forward()完成转发 requestDispatcher.forward(request, response);
-
特点
- 不管转发多少次,都是一个请求
- 转发前后的请求(get、post)方式要保持一致
- 浏览器的地址栏还是转发前的地址
重定向
-
语法
String contextPath = request.getContextPath(); // 获取项目名 // servlet名为:/dept/list // 使用重定向方式,需要加项目名 // response对象将这个路径响应给浏览器后,浏览器会自发的请求这个路径 response.sendRedirect(contextPath + "/dept/list");
-
特点
- 每重定向一次,就是一个新的请求
- 转发前后的请求(get、post)方式不受影响
- 浏览器的地址栏会更新到重定向的地址
转发和重定向的区别
- 转发是由WEB服务器来控制的,A请求跳转到B请求,整个过程中都是Tomcat完成的。
- 重定向是浏览器完成的,具体跳转到哪个资源由浏览器决定的。
何时使用转发?何时使用重定向?
- 如果在上一个Servlet当中向request域当中绑定了数据,希望在下一个Servlet当中把request域里面的数据取出来,使用转发机制
- 其余情况都用重定向(使用较多)
1.使用纯Servlet实现的案例(只使用转发机制)
-
创建数据表(dept)
drop table if exists t_dept; -- 部门表 create table t_dept( deptno int primary key, -- 主键 dname varchar(200), address varchar(200) ); -- 插入测试数据 insert into t_dept (deptno, dname, address) values (1, '开发部', '广州'); insert into t_dept (deptno, dname, address) values (2, '销售部', '深圳'); insert into t_dept (deptno, dname, address) values (3, '人事部', '上海'); commit; -- 查询数据 select * from t_dept;
-
WEB-INF下的lib目录引入mysql jdbc包
-
目录结构
src |------com.bz.oa |------utils |------DBUtil.java |------web.action |------AddServlet.java |------DelServlet.java |------DeptListServlet.java |------DetailServlet.java |------EditDeptServlet.java |------UpdateDeptServlet.java |------resources |------jdbc.properties web |------WEB-INF |------lib |------mysql-connector-java-8.0.29.jar |------web.xml |------addDept.html |------error.html |------index.html
-
DBUtil.java
package com.bz.oa.utils; import java.sql.*; import java.util.ResourceBundle; /** * JDBC工具类 */ public class DBUtil { // 静态变量,在类加载时执行 // 并且是有顺序的,自上而下的顺序 // 注意:这里的resources目录是在src下的 private static ResourceBundle bundle = ResourceBundle.getBundle("resources.jdbc"); private static String driver = bundle.getString("driver"); private static String url = bundle.getString("url"); private static String user = bundle.getString("user"); private static String pwd = bundle.getString("pwd"); static { try { // 注册驱动 Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取数据库连接对象 * @return connection 数据库连接对象 * @throws SQLException */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, pwd); } /** * 释放资源 * @param conn 数据库连接对象 * @param stat 数据库操作对象 * @param res 结果集对象 */ public static void close(Connection conn, Statement stat, ResultSet res) { if (res != null) { try { res.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stat != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
-
AddServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class AddServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); String deptno = request.getParameter("deptno"); String dname = request.getParameter("dname"); String address = request.getParameter("address"); Connection conn = null; PreparedStatement ps = null; int count = 0; try { conn = DBUtil.getConnection(); // 开启事务 conn.setAutoCommit(false); String sql = "insert into t_dept (deptno, dname, address) values (?, ?, ?)"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); ps.setString(2, dname); ps.setString(3, address); count = ps.executeUpdate(); // 事务提交 conn.commit(); } catch (SQLException e) { // 异常回滚事务 if (conn != null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { DBUtil.close(conn, ps, null); } if(count > 0) { // 新增成功 // 这里应该用重定向,现阶段没学到,所以先用转发 // 转发的Servlet不是post方法,会报405错误,所以需要在DeptListServle类添加doPost方法 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/dept/list"); requestDispatcher.forward(request, response); } else { // 新增失败 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/error.html"); requestDispatcher.forward(request, response); } } }
-
DelServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.Servlet; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class DelServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String deptno = request.getParameter("deptno"); String contextPath = request.getContextPath(); Connection conn = null; PreparedStatement ps = null; int count = 0; try { conn = DBUtil.getConnection(); // 开启事务(自动提交机制关闭) conn.setAutoCommit(false); String sql = "delete from t_dept where deptno = ?"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); count = ps.executeUpdate(); // 事务提交 conn.commit(); } catch (SQLException e) { // 遇到异常要回滚 if (conn != null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { DBUtil.close(conn, ps, null); } if(count > 0) { // 删除成功 // 这里应该用重定向,现阶段没学到,所以先用转发 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/dept/list"); requestDispatcher.forward(request, response); } else { // 删除失败 // 新增失败 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/error.html"); requestDispatcher.forward(request, response); } } }
-
DeptListServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.*; public class DeptListServle extends HttpServlet{ // 暂时解决新增数据后转发报405错误 @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取应用的根路径 String contextPath = request.getContextPath(); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println(" <meta charset='utf-8' />"); out.println(" <title>部门列表</title>"); out.println("<script type='text/javascript'>"); out.println(" function del(deptno) {"); out.println(" if (window.confirm('删除后无法 恢复,是否确定删除?')) {"); // document.location.href = ''; // document.location = ''; // window.location.href = ''; // window.location = ''; out.println(" document.location.href = '" + contextPath + "/dept/delete?deptno='+deptno"); out.println(" }"); out.println(" }"); out.println("</script>"); out.println("</head>"); out.println("<body>"); out.println(" <h1>部门列表</h1>"); out.println(" <hr>"); out.println(" <table border='1' align='center' width='50%'>"); out.println(" <tr>"); out.println(" <th>部门编号</th>"); out.println(" <th>部门名称</th>"); out.println(" <th>操作</th>"); out.println(" </tr>"); Connection conn = null; PreparedStatement ps = null; ResultSet res = null; try { conn = DBUtil.getConnection(); String sql = "select deptno, dname, address from t_dept"; ps = conn.prepareStatement(sql); res = ps.executeQuery(); while(res.next()) { int deptno = res.getInt("deptno"); String dname = res.getString("dname"); String address = res.getString("address"); System.out.println(deptno + ", " + dname + ", " + address); out.println("<tr>"); out.println(" <td>" + deptno + "</td>"); out.println(" <td>" + dname + "</td>"); out.println(" <td>"); out.println(" <a href='javascript:void(0);' onClick='del(" + deptno + ")'>删除</a>"); out.println(" <a href='" + contextPath + "/dept/edit?deptno=" + deptno + "'>编辑</a>"); out.println(" <a href='" + contextPath + "/dept/detail?deptno=" + deptno + "'>详情</a>"); out.println(" </td>"); out.println("</tr>"); } }catch(SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, res); out.println(" </table>"); out.println(" <hr/>"); out.println("<a href='" + contextPath + "/addDept.html'>新增部门</a>"); out.println("</body>"); out.println("</html>"); } } }
-
DetailServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DetailServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String deptno = request.getParameter("deptno"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println(" <meta charset='utf-8' />"); out.println(" <title>部门列表</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>部门详情</h1>"); out.println("<hr>"); Connection conn = null; PreparedStatement ps = null; ResultSet res = null; try { conn = DBUtil.getConnection(); String sql = "select dname, address from t_dept where deptno = ?"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); res = ps.executeQuery(); if(res.next()) { out.println("<p>部门编号:" + deptno + "</p>"); out.println("<p>部门名称:" + res.getString("dname") + "</p>"); out.println("<p>部门地址:" + res.getString("address") + "</p>"); } }catch(SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, res); } out.println(" <input type='button' value='返回' onClick='window.history.back()' />"); out.println(" </table>"); out.println("</body>"); out.println("</html>"); } }
-
EditDeptServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class EditDeptServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String contextPath = request.getContextPath(); // 获取部门编号 String deptno = request.getParameter("deptno"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println("<meta charset='UTF-8'>"); out.println("<title>修改部门</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>修改部门</h1>"); out.println("<hr/>"); Connection conn = null; PreparedStatement ps = null; ResultSet res = null; try { conn = DBUtil.getConnection(); String sql = "select deptno, dname, address from t_dept where deptno = ?"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); res = ps.executeQuery(); if(res.next()) { String dname = res.getString("dname"); String address = res.getString("address"); // ?deptno=" + deptno + "&dname=" + dname + "&address=" + address + " out.println("<form action='" + contextPath + "/dept/update' method='post'>"); out.println("部门编号<input type='number' name='deptno' value='" + deptno + "' readonly /><br/>"); out.println("部门名称<input type='text' name='dname' value='" + dname + "' /><br/>"); out.println("部门位置<input type='text' name='address' value='" + address + "' /><br/>"); out.println("<input type='submit' value='保存' />"); out.println("</form>"); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, res); } out.println("</body>"); out.println("</html>"); } }
-
UpdateDeptServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class UpdateDeptServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取表单的数据 String deptno = request.getParameter("deptno"); String dname = request.getParameter("dname"); String address = request.getParameter("address"); // 解决请求体的中文乱码问题 request.setCharacterEncoding("UTF-8"); Connection conn = null; PreparedStatement ps = null; int count = 0; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); String sql = "update t_dept set dname=?, address=? where deptno=?"; ps = conn.prepareStatement(sql); ps.setString(1, dname); ps.setString(2, address); ps.setString(3, deptno); count = ps.executeUpdate(); conn.commit(); } catch (SQLException e) { if(conn != null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { DBUtil.close(conn, ps, null); } if (count > 0) { // 修改成功 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/dept/list"); requestDispatcher.forward(request, response); } else { // 修改失败 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/error.html"); requestDispatcher.forward(request, response); } } }
-
jdbc.properties
# 驱动品牌 driver=com.mysql.cj.jdbc.Driver # 地址 url=jdbc:mysql://ip地址:3306/数据库 # 用户 user=root # 密码 pwd=root.5354
-
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0"> <!-- 欢迎页 --> <welcome-file-list> <welcome-file>dept/list</welcome-file> </welcome-file-list> <!-- start 列表 --> <servlet> <servlet-name>deptList</servlet-name> <servlet-class>com.bz.oa.web.action.DeptListServle</servlet-class> </servlet> <servlet-mapping> <servlet-name>deptList</servlet-name> <url-pattern>/dept/list</url-pattern> </servlet-mapping> <!-- end 列表 --> <!-- start 详情 --> <servlet> <servlet-name>detail</servlet-name> <servlet-class>com.bz.oa.web.action.DetailServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>detail</servlet-name> <url-pattern>/dept/detail</url-pattern> </servlet-mapping> <!-- end 详情 --> <!-- start 删除部门 --> <servlet> <servlet-name>delete</servlet-name> <servlet-class>com.bz.oa.web.action.DelServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>delete</servlet-name> <url-pattern>/dept/delete</url-pattern> </servlet-mapping> <!-- end 删除部门 --> <!-- start 新增部门 --> /dept/add <servlet> <servlet-name>add</servlet-name> <servlet-class>com.bz.oa.web.action.AddServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>add</servlet-name> <url-pattern>/dept/add</url-pattern> </servlet-mapping> <!-- end 新增部门 --> <!-- start 跳转到部门编辑页面 --> <servlet> <servlet-name>editDept</servlet-name> <servlet-class>com.bz.oa.web.action.EditDeptServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>editDept</servlet-name> <url-pattern>/dept/edit</url-pattern> </servlet-mapping> <!-- end 跳转到部门编辑页面 --> <!-- start 部门编辑 --> <servlet> <servlet-name>updateDept</servlet-name> <servlet-class>com.bz.oa.web.action.UpdateDeptServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>updateDept</servlet-name> <url-pattern>/dept/update</url-pattern> </servlet-mapping> <!-- end 部门编辑 --> </web-app>
-
addDept.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>新增部门</title> </head> <body> <h1>新增部门</h1> <hr/> <!-- 项目名为/servlet07 --> <form action="/servlet07/dept/add" method="post"> 部门编号<input type="number" name="deptno" /><br/> 部门名称<input type="text" name="dname" /><br/> 部门位置<input type="text" name="address" /><br/> <input type="submit" value="保存" /> </form> </body> </html>
-
error.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>error</title> </head> <body> <h1>操作失败</h1> <a href="javascript:void(0);" onClick="window.history.back();">返回</a> </body> </html>
-
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>oa</title> </head> <body> </body> </html>
2.使用纯Servlet实现的案例(使用重定向机制)
-
创建数据表(dept)
drop table if exists t_dept; -- 部门表 create table t_dept( deptno int primary key, -- 主键 dname varchar(200), address varchar(200) ); -- 插入测试数据 insert into t_dept (deptno, dname, address) values (1, '开发部', '广州'); insert into t_dept (deptno, dname, address) values (2, '销售部', '深圳'); insert into t_dept (deptno, dname, address) values (3, '人事部', '上海'); commit; -- 查询数据 select * from t_dept;
-
WEB-INF下的lib目录引入mysql jdbc包
-
目录结构
src |------com.bz.oa |------utils |------DBUtil.java |------web.action |------AddServlet.java |------DelServlet.java |------DeptListServlet.java |------DetailServlet.java |------EditDeptServlet.java |------UpdateDeptServlet.java |------resources |------jdbc.properties web |------WEB-INF |------lib |------mysql-connector-java-8.0.29.jar |------web.xml |------addDept.html |------error.html |------index.html
-
DBUtil.java
package com.bz.oa.utils; import java.sql.*; import java.util.ResourceBundle; /** * JDBC工具类 */ public class DBUtil { // 静态变量,在类加载时执行 // 并且是有顺序的,自上而下的顺序 // 注意:这里的resources目录是在src下的 private static ResourceBundle bundle = ResourceBundle.getBundle("resources.jdbc"); private static String driver = bundle.getString("driver"); private static String url = bundle.getString("url"); private static String user = bundle.getString("user"); private static String pwd = bundle.getString("pwd"); static { try { // 注册驱动 Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获取数据库连接对象 * @return connection 数据库连接对象 * @throws SQLException */ public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, pwd); } /** * 释放资源 * @param conn 数据库连接对象 * @param stat 数据库操作对象 * @param res 结果集对象 */ public static void close(Connection conn, Statement stat, ResultSet res) { if (res != null) { try { res.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stat != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
-
AddServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class AddServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String contextPath = request.getContextPath(); request.setCharacterEncoding("UTF-8"); String deptno = request.getParameter("deptno"); String dname = request.getParameter("dname"); String address = request.getParameter("address"); Connection conn = null; PreparedStatement ps = null; int count = 0; try { conn = DBUtil.getConnection(); // 开启事务 conn.setAutoCommit(false); String sql = "insert into t_dept (deptno, dname, address) values (?, ?, ?)"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); ps.setString(2, dname); ps.setString(3, address); count = ps.executeUpdate(); // 事务提交 conn.commit(); } catch (SQLException e) { // 异常回滚事务 if (conn != null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { DBUtil.close(conn, ps, null); } if(count > 0) { // 新增成功 // 使用重定向方式,需要加项目名 response.sendRedirect(contextPath + "/dept/list"); } else { // 新增失败 response.sendRedirect(contextPath + "/error.html"); } } }
-
DelServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.Servlet; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class DelServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String deptno = request.getParameter("deptno"); String contextPath = request.getContextPath(); Connection conn = null; PreparedStatement ps = null; int count = 0; try { conn = DBUtil.getConnection(); // 开启事务(自动提交机制关闭) conn.setAutoCommit(false); String sql = "delete from t_dept where deptno = ?"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); count = ps.executeUpdate(); // 事务提交 conn.commit(); } catch (SQLException e) { // 遇到异常要回滚 if (conn != null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { DBUtil.close(conn, ps, null); } if(count > 0) { // 删除成功 // 使用重定向方式,需要加项目名 response.sendRedirect(contextPath + "/dept/list"); } else { // 删除失败 // 新增失败 response.sendRedirect(contextPath + "/error.html"); } } }
-
DeptListServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.*; public class DeptListServle extends HttpServlet{ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取应用的根路径 String contextPath = request.getContextPath(); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println(" <meta charset='utf-8' />"); out.println(" <title>部门列表</title>"); out.println("<script type='text/javascript'>"); out.println(" function del(deptno) {"); out.println(" if (window.confirm('删除后无法 恢复,是否确定删除?')) {"); // document.location.href = ''; // document.location = ''; // window.location.href = ''; // window.location = ''; out.println(" document.location.href = '" + contextPath + "/dept/delete?deptno='+deptno"); out.println(" }"); out.println(" }"); out.println("</script>"); out.println("</head>"); out.println("<body>"); out.println(" <h1>部门列表</h1>"); out.println(" <hr>"); out.println(" <table border='1' align='center' width='50%'>"); out.println(" <tr>"); out.println(" <th>部门编号</th>"); out.println(" <th>部门名称</th>"); out.println(" <th>操作</th>"); out.println(" </tr>"); Connection conn = null; PreparedStatement ps = null; ResultSet res = null; try { conn = DBUtil.getConnection(); String sql = "select deptno, dname, address from t_dept"; ps = conn.prepareStatement(sql); res = ps.executeQuery(); while(res.next()) { int deptno = res.getInt("deptno"); String dname = res.getString("dname"); String address = res.getString("address"); System.out.println(deptno + ", " + dname + ", " + address); out.println("<tr>"); out.println(" <td>" + deptno + "</td>"); out.println(" <td>" + dname + "</td>"); out.println(" <td>"); out.println(" <a href='javascript:void(0);' onClick='del(" + deptno + ")'>删除</a>"); out.println(" <a href='" + contextPath + "/dept/edit?deptno=" + deptno + "'>编辑</a>"); out.println(" <a href='" + contextPath + "/dept/detail?deptno=" + deptno + "'>详情</a>"); out.println(" </td>"); out.println("</tr>"); } }catch(SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, res); out.println(" </table>"); out.println(" <hr/>"); out.println("<a href='" + contextPath + "/addDept.html'>新增部门</a>"); out.println("</body>"); out.println("</html>"); } } }
-
DetailServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class DetailServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String deptno = request.getParameter("deptno"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println(" <meta charset='utf-8' />"); out.println(" <title>部门列表</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>部门详情</h1>"); out.println("<hr>"); Connection conn = null; PreparedStatement ps = null; ResultSet res = null; try { conn = DBUtil.getConnection(); String sql = "select dname, address from t_dept where deptno = ?"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); res = ps.executeQuery(); if(res.next()) { out.println("<p>部门编号:" + deptno + "</p>"); out.println("<p>部门名称:" + res.getString("dname") + "</p>"); out.println("<p>部门地址:" + res.getString("address") + "</p>"); } }catch(SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, res); } out.println(" <input type='button' value='返回' onClick='window.history.back()' />"); out.println(" </table>"); out.println("</body>"); out.println("</html>"); } }
-
EditDeptServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class EditDeptServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String contextPath = request.getContextPath(); // 获取部门编号 String deptno = request.getParameter("deptno"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE html>"); out.println("<html>"); out.println("<head>"); out.println("<meta charset='UTF-8'>"); out.println("<title>修改部门</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>修改部门</h1>"); out.println("<hr/>"); Connection conn = null; PreparedStatement ps = null; ResultSet res = null; try { conn = DBUtil.getConnection(); String sql = "select deptno, dname, address from t_dept where deptno = ?"; ps = conn.prepareStatement(sql); ps.setString(1, deptno); res = ps.executeQuery(); if(res.next()) { String dname = res.getString("dname"); String address = res.getString("address"); // ?deptno=" + deptno + "&dname=" + dname + "&address=" + address + " out.println("<form action='" + contextPath + "/dept/update' method='post'>"); out.println("部门编号<input type='number' name='deptno' value='" + deptno + "' readonly /><br/>"); out.println("部门名称<input type='text' name='dname' value='" + dname + "' /><br/>"); out.println("部门位置<input type='text' name='address' value='" + address + "' /><br/>"); out.println("<input type='submit' value='保存' />"); out.println("</form>"); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, res); } out.println("</body>"); out.println("</html>"); } }
-
UpdateDeptServlet.java
package com.bz.oa.web.action; import com.bz.oa.utils.DBUtil; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class UpdateDeptServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取应用的根路径 String contextPath = request.getContextPath(); // 获取表单的数据 String deptno = request.getParameter("deptno"); String dname = request.getParameter("dname"); String address = request.getParameter("address"); // 解决请求体的中文乱码问题 request.setCharacterEncoding("UTF-8"); Connection conn = null; PreparedStatement ps = null; int count = 0; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); String sql = "update t_dept set dname=?, address=? where deptno=?"; ps = conn.prepareStatement(sql); ps.setString(1, dname); ps.setString(2, address); ps.setString(3, deptno); count = ps.executeUpdate(); conn.commit(); } catch (SQLException e) { if(conn != null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { DBUtil.close(conn, ps, null); } if (count > 0) { // 修改成功 // 使用重定向方式,需要加项目名 response.sendRedirect(contextPath + "/dept/list"); } else { // 修改失败 response.sendRedirect(contextPath + "/error.html"); } } }
-
jdbc.properties
# 驱动品牌 driver=com.mysql.cj.jdbc.Driver # 地址 url=jdbc:mysql://ip地址:3306/数据库 # 用户 user=root # 密码 pwd=root.5354
-
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0"> <!-- 欢迎页 --> <welcome-file-list> <welcome-file>dept/list</welcome-file> </welcome-file-list> <!-- start 列表 --> <servlet> <servlet-name>deptList</servlet-name> <servlet-class>com.bz.oa.web.action.DeptListServle</servlet-class> </servlet> <servlet-mapping> <servlet-name>deptList</servlet-name> <url-pattern>/dept/list</url-pattern> </servlet-mapping> <!-- end 列表 --> <!-- start 详情 --> <servlet> <servlet-name>detail</servlet-name> <servlet-class>com.bz.oa.web.action.DetailServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>detail</servlet-name> <url-pattern>/dept/detail</url-pattern> </servlet-mapping> <!-- end 详情 --> <!-- start 删除部门 --> <servlet> <servlet-name>delete</servlet-name> <servlet-class>com.bz.oa.web.action.DelServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>delete</servlet-name> <url-pattern>/dept/delete</url-pattern> </servlet-mapping> <!-- end 删除部门 --> <!-- start 新增部门 --> /dept/add <servlet> <servlet-name>add</servlet-name> <servlet-class>com.bz.oa.web.action.AddServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>add</servlet-name> <url-pattern>/dept/add</url-pattern> </servlet-mapping> <!-- end 新增部门 --> <!-- start 跳转到部门编辑页面 --> <servlet> <servlet-name>editDept</servlet-name> <servlet-class>com.bz.oa.web.action.EditDeptServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>editDept</servlet-name> <url-pattern>/dept/edit</url-pattern> </servlet-mapping> <!-- end 跳转到部门编辑页面 --> <!-- start 部门编辑 --> <servlet> <servlet-name>updateDept</servlet-name> <servlet-class>com.bz.oa.web.action.UpdateDeptServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>updateDept</servlet-name> <url-pattern>/dept/update</url-pattern> </servlet-mapping> <!-- end 部门编辑 --> </web-app>
-
addDept.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>新增部门</title> </head> <body> <h1>新增部门</h1> <hr/> <!-- 项目名为/servlet07 --> <form action="/servlet07/dept/add" method="post"> 部门编号<input type="number" name="deptno" /><br/> 部门名称<input type="text" name="dname" /><br/> 部门位置<input type="text" name="address" /><br/> <input type="submit" value="保存" /> </form> </body> </html>
-
error.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>error</title> </head> <body> <h1>操作失败</h1> <!-- href="/项目名/Servlet" --> <a href="/servlet07/dept/list">返回</a> </body> </html>
-
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>oa</title> </head> <body> </body> </html>