目录
1 Http协议
1.1 概述
1.2 get请求和post请求
2 HttpServlet源码分析
3 关于web站点的欢迎页面
4 HttpServletRequest接口详解
4.1 概述
4.2 HttpServletRequest常用方法
4.3 请求域对象
4.4 HttpServletRequest其它常用的方法
5 使用纯Servlet做一个单表的增删改查
6 转发和重定向
7 Servlet注解,简化配置
9 使用模板方法设计模式优化oa项目
10 详细代码
好消息好消息,我们今后不用GenericServlet了,改用HttpServlet了,好像又白学了。。。
并没有白学,它是继承GenericServlet的,很多相同的地方,因为我们是B/S架构的系统,这种系统是基于HTTP超文本传输协议的,HttpServlet处理HTTP协议更便捷。
在学习HttpServlet之前我们先了解一下HTTP协议
先写一些代码协助我们理解:
代码主要就是写一个html页面,其中使用到form标签,并且提交使用get和post两种方式,响应到servlet并输出servlet中的信息。
get and post
get方法提交
post方法提交
HTTP协议包括请求协议和响应协议
HTTP请求协议:
请求协议是浏览器向服务器发送请求,请求协议包含四部分:请求行、请求头、空白行、请求体
根据我们写的代码可以得到HTTP响应协议具体报文,得到报文的方法是在浏览器按F12键,network中记录着报文内容:
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,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 28
Content-Type: application/x-www-form-urlencoded
Cookie: Idea-35e4271=01328648-8b36-4624-b567-815b69706ef0
Host: localhost:8080
Origin: http://localhost:8080
Referer: http://localhost: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/103.0.0.0 Safari/537.36
sec-ch-ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
username: wangwu
password: 123
然后后面的不想学了。。再见
HTTP响应协议:
响应协议是服务器向浏览器发送响应,响应协议包含四部分:状态行、响应头、空白行、响应体
其中状态行中的200是状态码(HTTP协议中规定的响应状态号,不同响应结果对应不同号码),200表示响应成功,正常结束;404表示访问资源不存在,通常是路径写错了,或者服务器中对应的资源没有启动成功,404错误是前端错误;405表示前端发送的请求与后端的处理方式不一致发生的,比如前端是get而后端是post;500表示服务器端的程序出现了异常,一般是服务器端的错误;以4开始一般是浏览器错误,以5开始一般是服务器错误。
怎么向服务器发送GET请求,怎么向服务器发送POST请求?
到目前为止,只有一种情况可以发POST请求:使用form表单属性method=“post”。其它所有情况都是get请求。
get请求和post请求区别?
get和post请求该如何选择?
请求是获取服务器的数据建议使用get,如果是为了向服务器提交数据建议使用post
不管是get还是post请求,发送数据格式一样都是:name=value&name=value
name和value是什么?以form表单为例就是input标签中的name和value
此处分析只分析之前没遇到的,遇到的基本上在之前都已经分析过了。
HttpServlet中的方法首先还是执行init方法然后是再执行service方法
这是HttpServlet里的其中一个service方法,Tomcat会先调用这个service方法,因为参数原因,接着把ServletRequest和ServletResponse对象转为HttpServletRequest和HttpServletResponse,都是带Http的,然后再调用另一个service方法(重载的service方法),把转型好的两个对象传入。下面是重载的service方法
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} 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);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
我们看到首先就调用getMethod方法来获取请求方式,也就是之前学的get或post请求或者其它的。接着判断获取的是什么请求然后执行相应的方法(doPost、doGet等等方法)。也就是说假如我们使用form表单并且使用post请求来提交信息,service方法就会识别到这是post请求也就会执行doPost方法,但是需要我们重写doPost方法,如果我们没有重写这个方法,那么就会执行父类的也就是HttpServlet中的doPost方法,就会报错。但是如果我们直接重写service方法就不会报错,因为重写了service方法就不会调用doPost方法了。假如我们自己重写service方法,就没有错误提示了,所以是不是建议我们不自己重写service呢???
总结一下一个Servlet类的开发步骤:
什么是欢迎页面?
设置了欢迎页面,当你访问这个webapp时,没有指定任何“资源路径”,这个时候会默认访问你的欢迎页面。
怎么设置欢迎页面?
login.html
但是我们发现当文件命名为index.html的时候不需要配置就可以直接访问,为什么捏?
这是因为小猫咪已经提前配置好了,实际上有两个地方可以配置
我们打开源码瞅瞅,果然有这样的配置:
当我们自己配置欢迎页面就会默认访问我们配置的,我们不配置就会访问小猫咪配置的index
欢迎页面可以是servlet吗?
当然可以,只要把路径改为servlet的路径即可,下面展示如何配置:
da/w/wf
welcomeServlet
com.itzw.javaweb.servlet.WelcomeServlet
welcomeServlet
/da/w/wf
HttpServletRequest对象中都有什么信息,都包装了什么信息?
request和response对象的生命周期
HttpServletRequest接口中有哪些常用的方法
Map getParameter() 获取Map
Enumeration getParameterNames() 获取Map集合所有的key
String getParameter(String name) 根据key获取value这个一维数组中的第一个元素
String[] getParameterValues(String name) 根据key获取value
之所以有一个是返回一个value,有一个是返回value数组,是因为有的value不止一个,比如爱好这个key,它可以有多个爱好,而map集合中的key不能重复。但是我们用的最多的还是一个key对应一个value。
演示:
package com.itzw.javaweb.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.util.Enumeration;
public class RequestTest extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("注册成功!
");
//获取我提交的信息
//获取所有key
Enumeration parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()){
String name = parameterNames.nextElement();
System.out.println(name);
}
//根据key获取value
String username = request.getParameter("username");
System.out.println(username);
String password = request.getParameter("password");
System.out.println(password);
String[] hobbies = request.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
}
}
username
password
hobby
zhangsan
123
smoke
drink
tangtou
request对象是什么?request对象又称请求域对象
还记得之前学的应用域对象(ServletContext),什么时候会用应用域对象呢?
void setAttribute(String name,Object obj);//向域中绑定数据
Object getAttribute(String name);//从域中根据name获取数据
void removeAttribute(String name);//将域中绑定的数据移除
请求域对象
void setAttribute(String name,Object obj);//向域中绑定数据
Object getAttribute(String name);//从域中根据name获取数据
void removeAttribute(String name);//将域中绑定的数据移除
请求域不是共享的,当我们在一个servlet中存数据,只能在这个servlet中取出数据和删除数据,在另一个servlet中是无法取出数据和删除数据的。
演示效果:
package com.itzw.javaweb.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.util.Date;
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
Date thisTime = new Date();
request.setAttribute("nowTime",thisTime);
/*Object nowTime = request.getAttribute("nowTime");
out.print("nowTime:" + nowTime);*/
}
}
package com.itzw.javaweb.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;
public class BServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
Object nowTime = request.getAttribute("nowTime");
out.print("nowTime:" + nowTime);
}
}
很显然访问BServlet访问不到信息
两个servlet怎么共享数据?
使用请求域共享数据具体操作:
在AServlet中加入下面代码:
RequestDispatcher dispatcher = request.getRequestDispatcher("/b");
dispatcher.forward(request,response);
这样AServlet中的request就能跳转到BServlet
需要注意的是:路径的规范前面要加“/”,不需要加项目名。同时不仅可以转到Servlet也可以访问别的文件,比如html,此时路径是以根目录也就是web目录开始,也就是说写在web目录下的文件的路径直接写文件名即可。
request.getRequestDispatcher("/test.html").forward(request,response);
还需要注意的是:request对象中两个非常容易混淆的方法
request.getParameter("username");//这是获取用户在浏览器上提交的数据
request.getAttribute("name");//这获取的是请求域当中绑定的数据
request.getRemoteAddr();//获取客户端IP地址
request.setCharacterEncoding("UTF-8");
设置请求体字符集,也就是设置post请求在请求体中提交的数据,只能解决post请求的乱码问题,并且是后端输出的乱发问题,前端也就是浏览器输出的内容乱码需要使用response.setContentType("text/html;charset=UTF-8");
get请求:修改CATALINA_HOME/conf/server.xml配置文件
但其实使用tomcat10这些问题都不会存在。
request.getContextPath();获取应用的根路径(/servlet06)
request.getMethod();获取请求方式(GET/POST)
request.getRequestURI();获取请求的URI(/servlet06/testRequest)
request.getServletPath();获取servlet path(testRequest)
使用servlet完成单表【对部门】的增删改查操作(B/S结构)。
实现步骤
第一步:准备一张数据库表
USE db1;
drop table if EXISTS dept;
create table dept(
deptno int primary key,
dname varchar(255),
loc varchar(255)
);
insert into dept(deptno,dname,loc) values(10,'销售部','上海');
insert into dept(deptno,dname,loc) values(20,'研发部','南京');
insert into dept(deptno,dname,loc) values(30,'技术部','苏州');
commit;
select * from dept;
第二步:准备一套HTML页面
应该设计哪些页面呢?
第三步:分析我们这个系统包括哪些功能?
什么叫做一个功能?
包括哪些功能?
第四步:在IDEA中搭建开发环境
第五步:实现第一个功能--查看部门列表
我们应该怎样实现一个功能呢?可以先从后端一步步往前端写或者从前端一步步往后端写,最好不要想到哪就写哪。
第六步:查看部门详情
首先想的是用户点击的是什么?用户点击的东西在哪里?因为本次小测试只用了servlet,所以前端的东西都用后端实现,详情也在后端的java小程序中,点击详情是要连接数据库 的,所以这个超连接点击后需要执行一段java代码。
注意:这个路径需要加项目名(前端路径都要加项目名),项目名可以动态获取。向服务器提交的数据格式:url?name=value&name=value
编写web.xml文件和一个servlet类重写doGet方法
第七步:删除部门
从前端页面开始,用户点击删除按钮的时候,应该提示用户是否删除,因为删除这个动作是比较危险的,任何系统在进行删除之前都必须提示用户。在前端页面使用JS代码提示用户是否删除。
删除
注意这里的javascript:void(0)表示仍然保留超连接的样子,点击此超链接之后不进行页面的跳转。也就是说我只希望用户点击该超链接的时候执行一段js代码,不进行页面跳转。
function del(dno){
var ok = window.confirm("亲,删除了不能恢复哦!")
if (ok){
document.location.href="/oa/dept/delete?deptno=" + dno;
}
}
注意这里的JS代码中的window.confirm就是弹出确认框,点击确认会返回true,点击取消返回false在JS代码中如何发送请求给服务器呢? 使用document.location.href="";或者window.location.href或者去掉href也可以。
以上的代码要写在后端java小程序中,和之前的方式一样。
第八步:新增部门
注意:最后保存成功后,转发到/dept/list的时候会出现405,为什么??因为保存用的是post请求,底层要执行doPost方法,但转发到的list中只有doGet方法。
怎么解决??
- 第一种:在list中添加doPost方法,在doPost方法中调用doGet,相当于欺骗小猫咪。
- 第二种:重定向(还没学)。
第九步:跳转到修改页面
第十步:修改部门信息
在写修改部门信息的代码时出现了一个bug,找了半天,接收到的deptno是空的,我第一反应是name写错了,但确实没写错,懵逼了,然后思考了一下,原来是我接收到的信息是input标签传来的,所以name要和input标签中的name写的一样,当时写的name为dno而不是deptno。
完整代码:
6 转发和重定向
在一个web中如何完成资源的跳转,有两种方式:
- 第一种:转发
- 第二种:重定向
转发和重定向有什么区别
代码上的区别:
- 转发
request.getRequestDispatcher("/b").forward(request,response);
- 重定向
response.sendRedirect(request.getContextPath()+"/b");
形式上有什么区别?
- 转发:一次请求,在浏览器地址栏发送的请求是http://localhost:8080/servlet07/a,最终请求结束后,浏览器地址栏上的地址还是这个没有变化。这就是为什么转发的代码有forword里面传的是request和response,就是当前的request和response传到了另一个servlet,都只是一个请求罢了。
- 重定向:两次请求,重定向的路径要加项目名,因为response对象蒋政路径响应给了浏览器,浏览器又向服务器发送了一个新的请求:http://localhost:8080/servlet07/b,所以一共发了两次请求,一次是a一次是b。
转发和重定向的本质区别?
- 转发:是由web服务器控制的,A资源跳转到B资源,这个跳转动作是Tomcat服务器内部完成的。
- 重定向:是浏览器完成的。
转发和重定向如何选择??
- 如果上一个Servlet当中向request域当中绑定了数据,希望从下一个Servlet当中把request域里面的数据取出来,使用转发机制。
- 上下的均使用重定向(重定向使用较多)
转发会存在浏览器刷新问题
此话怎讲呢,因为转发只是一次请求,比如在我们添加数据的时候,添加完数据跳转到一个页面,当我们不断刷新此页面会发现仍然在添加数据,但重定向不会发生这个问题,因为重定向是两次请求,第二次请求已经和添加数据的请求毫无关系。
7 Servlet注解,简化配置
经过之前做的小项目来看,只是一个小小的项目web.xml文件就写了如此多的信息,如果是一个大的项目的话将会非常麻烦,开发效率极低,而且这些配置是很少被修改的,所以这种配置可不可以直接写在java类中呢?当然可以,从servlet3.0版本后就推出了各种servlet基于注解式开发。这样的优点有哪些呢?开发效率高,不需要编写大量的配置信息,直接在java类上使用注解进行标注;web.xml文件变小了。但并不是有了注解就不需要web.xml文件了,有一些需要变化的信息还是需要web.xml文件,一般不会经常修改的建议使用注解,可能会修改的写到配置文件中。
我们的第一个注解
- 在servlet类上使用:@WebServlet,注解中有哪些属性呢?
- name属性:用来指定Servlet的名字,等同于
- urlPatterns属性:用来指定Servlet的映射路径,可以指定多个,等同于
- loadOnStartUp属性:用来指定在服务器启动阶段是否加载该Servlet,等同于
- value属性:当注解的属性名是value时,value属性名是可以省略的
- 注意:并不是将所有属性都写上去,需要啥写啥,并且属性是一个数组的时候,如果数组只有一个元素是可以省略大括号的,所以一般我们写注解都是只写一个value属性就可以了,形式为:WebServlet("/hello"),非常的方便
- 注意:注解的格式@注解名称(属性名=属性值,属性名=属性值...)
当我在写注解的时候出现了一个错误,找了半天,原来是注解中的value属性,也就是指定Servlet的路径,前面没加/
9 使用模板方法设计模式优化oa项目
上面解决了配置文件问题,但是现在的oa项目仍然存在一个比较臃肿的问题:一个简单的增删改查就写了6个servlet。如果一个复杂的系统业务,这种方式会导致类爆炸(类的数量太多),可以使用模板方式解决这个问题。
怎么解决类爆炸问题?
以前是一个请求一个Servlet,现在可以这样:一个请求对应一个方法,一个业务对应一个Servlet类。比如处理部门相关业务的对应一个DeptServlet,处理用户相关业务的对应一个UserServlet等等。
步骤:
- 第一步:创建一个模块,把上个模块中的文件除了servlet类都赋值到这个模块中
- 第二步:创建一个Servlet类,使用注解将项目用到的路径写在一个注解中
- 第三步:重写service方法,获取servlet path,使用方法来代替之前的servlet类就可以了。
10 详细代码
经过上面的改造,目前得到的详细代码如下
首先项目目录结构
工具类DBUtil:
package com.itzw.oa.util;
import java.sql.*;
import java.util.ResourceBundle;
public class DBUtil {
//静态变量在类加载时执行
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 password = bundle.getString("password");
static {
//注册驱动
//注册驱动执行一次就可以,所以放在静态代码块,类加载时就执行且执行一次
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取数据库连接对象
* @return
* @throws SQLException
*/
public static Connection getConnection () throws SQLException {
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
/**
* 释放资源
* @param conn
* @param st
* @param rs
*/
public static void close(Connection conn, Statement st, ResultSet rs){
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
配置文件jdbc.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/db1
user=root
password=123456
servlet类DeptServlet:
package com.itzw.oa.web.action;
import com.itzw.oa.util.DBUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebServlet;
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;
@WebServlet({"/dept/list","/dept/detail","/dept/delete","/dept/save","/dept/edit","/dept/modify"})
public class DeptServlet extends HttpServlet {
//重写service方法
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取Servlet path
String servletPath = request.getServletPath();
if ("/dept/list".equals(servletPath)){
doList(request,response);
}else if ("/dept/detail".equals(servletPath)){
doDetail(request,response);
}else if ("/dept/delete".equals(servletPath)){
doDel(request,response);
}else if ("/dept/save".equals(servletPath)){
doSave(request,response);
}else if ("/dept/edit".equals(servletPath)){
doEdit(request,response);
}else if ("/dept/modify".equals(servletPath)){
doModify(request,response);
}
}
private void doList(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String contextPath = request.getContextPath();
out.print("");
out.print("");
out.print(" ");
out.print(" ");
out.print(" 部门列表 ");
out.print("");
out.print(" ");
out.print(" ");
out.print(" 部门信息
");
out.print("
");
out.print(" ");
out.print(" ");
out.print(" 序号 ");
out.print(" 部门编号 ");
out.print(" 部门名称 ");
out.print(" 操作 ");
out.print(" ");
//连接数据库
try {
conn = DBUtil.getConnection();
String sql = "select deptno,dname,loc from dept";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
int i = 1;
while (rs.next()){
//获取部门信息
int deptno = rs.getInt("deptno");
String dname = rs.getString("dname");
out.print(" ");
out.print(" "+ (i++) + " ");
out.print(" "+ deptno +" ");
out.print(" "+dname+" ");
out.print(" 删除");
out.print(" 修改");
out.print(" 详情");
out.print(" ");
out.print(" ");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(conn,ps,rs);
}
out.print("
");
out.print("
");
out.print(" 添加信息");
out.print(" ");
out.print("");
}
private void doDetail(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
out.print("");
out.print("");
out.print(" ");
out.print(" ");
out.print(" 详情信息 ");
out.print(" ");
out.print(" ");
out.print(" 详情信息
");
out.print("
");
//获取前端提交的数据中的name,本次测试其实是在后端编写的html
String deptno = request.getParameter("deptno");
//连接数据库
try {
conn = DBUtil.getConnection();
String sql = "select deptno,dname,loc from dept where deptno = ?";
ps = conn.prepareStatement(sql);
//将收到的name传入到?中也就是SQL语句中
ps.setString(1,deptno);
rs = ps.executeQuery();
while (rs.next()){
//获取部门信息
String dname = rs.getString("dname");
String loc = rs.getString("loc");
out.print("部门编号:"+deptno+"
");
out.print("部门名称:"+dname+"
");
out.print("部门位置:"+loc+"
");
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(conn,ps,rs);
}
out.print(" ");
out.print(" ");
out.print("");
}
private void doDel(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
Connection conn = null;
PreparedStatement ps = null;
//获取前端提交的数据中的name,本次测试其实是在后端编写的html
String deptno = request.getParameter("deptno");
int count = 0;
//连接数据库
try {
conn = DBUtil.getConnection();
//开启事务(自动提交关闭)
conn.setAutoCommit(false);
String sql = "delete from dept where deptno = ?";
ps = conn.prepareStatement(sql);
//将收到的name传入到?中也就是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 == 1){
//删除成功,仍然跳转到部门列表页面,这里使用转发
//request.getRequestDispatcher("/dept/list").forward(request,response);
//改成重定向会好一点
response.sendRedirect(request.getContextPath()+"/dept/list");
}else {
//删除失败
//request.getRequestDispatcher("/error.html").forward(request,response);
response.sendRedirect(request.getContextPath()+"/error.html");
}
}
private void doSave(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
response.setContentType("text/html");
Connection conn = null;
PreparedStatement ps = null;
//接收用户输入的信息
String dno = request.getParameter("dno");
String dname = request.getParameter("dname");
String loc = request.getParameter("loc");
int count = 0;
try {
//获取连接
conn = DBUtil.getConnection();
//开启事务(本次小测试其实没有使用事务的必要)
conn.setAutoCommit(false);
String sql = "insert into dept(deptno,dname,loc) values (?,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1,dno);
ps.setString(2,dname);
ps.setString(3,loc);
count = ps.executeUpdate();
//提交事务
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//回滚事务
try {
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
DBUtil.close(conn,ps,null);
}
if (count == 1){
//添加成功
//request.getRequestDispatcher("/dept/list").forward(request,response);
response.sendRedirect(request.getContextPath()+"/dept/list");
}else{
//添加失败
//request.getRequestDispatcher("/error.html").forward(request,response);
response.sendRedirect(request.getContextPath()+"/error.html");
}
}
private void doEdit(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String contextPath = request.getContextPath();
out.print(" ");
out.print("");
out.print(" ");
out.print(" ");
out.print(" 修改信息 ");
out.print(" ");
out.print(" ");
out.print(" 修改信息
");
out.print("
");
out.print(" ");
out.print(" ");
out.print("");
}
private void doModify(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
//解决请求体乱码的问题
request.setCharacterEncoding("UTF-8");
//获取部门信息
String deptno = request.getParameter("dno");
String dname = request.getParameter("dname");
String loc = request.getParameter("loc");
//连接数据库
Connection conn = null;
PreparedStatement ps = null;
int count = 0;
try {
conn = DBUtil.getConnection();
String sql = "update dept set dname = ?,loc = ? where deptno = ?";
ps = conn.prepareStatement(sql);
ps.setString(1,dname);
ps.setString(2,loc);
ps.setString(3,deptno);
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(conn,ps,null);
}
if (count == 1){
//修改成功
//request.getRequestDispatcher("/dept/list").forward(request,response);
response.sendRedirect(request.getContextPath()+"/dept/list");
}else{
//修改失败
//request.getRequestDispatcher("/error.html").forward(request,response);
response.sendRedirect(request.getContextPath()+"/error.html");
}
}
}
add.html:
新增页面
添加信息
error.html
失败
操作失败,返回
index.html
欢迎页面
查看部门列表
因为使用了注解,所以web.xml文件没有任何配置
结果:
小小总结一波:本次小项目做了挺久,因为只使用了servlet,过程比较繁琐,尤其是遇到前端部分,只能强行将前端代码塞进后端。接着学到了注解,大大提高了开发效率,最后是模板方式,解决了类太多的问题。那么后面就开始学习别的内容来解决前端代码写在后端的问题。
你可能感兴趣的:(javaweb,Java,servlet,java,web)