Servlet

文章目录


1. 概念

  1. Servlet 是 JavaEE 规范之一。 规范就是接口
  2. Servlet 就 JavaWeb 三大组件之一。 三大组件分别是: Servlet 程序、 Filter 过滤器、 Listener 监
    听器。
  3. Servlet服务于HTTP协议的服务端的一个小程序,"接收请求,解析请求,根据请求执行业务逻辑,
    做出响应

也就是说 servlet是一个用来处理 请求 做出回应的容器,对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象。

2.基础案例

从Servlet3.0开始,配置Servlet支持注解方式,但还是保留了配置web.xml方式,所有使用Servlet有两

种方式:

(1)Servlet类上使用@WebServlet注解进行配置

(2)web.xml文件中配置

1.基于注解的配置

这个基于注解的配置关键在于@WebServlet("/hello")这个用来设置虚拟路径然后才有了访问的地址

@WebServlet常用属性

  1. loadOnStartup属性::标记容器是否在启动应用时就加载Servlet,默认不配置或数值为负数时表示客户端第一次请求Servlet时再加载;0或正数表示启动应用就加载,正数情况下,数值越小,加载该Servlet的优先级越高;
go 复制代码
@WebServlet(value="/test1",loadOnStartup=1)
  1. urlPatterns的常用规则
  • /*或者/:拦截所有(所谓拦截也就是意思只有这个范围下的地址可以被访问)
    如果放行特定的请求比如静态资源html,css,jpg,可以配置如下:
go 复制代码
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
  • *.do:拦截指定后缀

  • 使用注解时,需要注意

根元素中不能配置属性metadata-complete="true",否则无法加载Servlet。metadata-complete属性表示通知Web容器是否寻找注解,默认不写或者设置false,容器会扫描注解,为Web应用程序构建有效的元数据;metadata-complete="true",会在启动时不扫描注解(annotation)。如果不扫描注解的话,用注解进行的配置就无法生效,例如:@WebServlet

1.引入依赖

2.创建HttpServlet

bash 复制代码
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        BufferedReader in = new BufferedReader(new
                InputStreamReader(request.getInputStream()));
        String line = null;
        while ((line = in.readLine()) != null) {
            System.out.println(line);
        }
        in.close();
    }

    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
        System.out.println("queryString = " + request.getQueryString());
        response.getWriter().print(request.getQueryString());
    }
}

3.表单访问

bash 复制代码
<h4>get</h4>
<form action="http://localhost:8080/servlet-demo/hello" method="get">
  <input type="text" name="username" value="mickey"><br>
  <input type="text" name="password" value="123456"><br>
  <input type="submit" value="提交">
</form>
<h4>post</h4>
<form action="http://localhost:8080/servlet-demo/hello" method="post">
  <input type="text" name="username" value="mickey"><br>
  <input type="text" name="password" value="123456"><br>
  <input type="submit" value="提交">
</form>

2.基于XML配置

这个基于XML配置的关键就在于下面图的资源路径 也就是虚拟路径 这样才可以找到这个页面

web.xml

bash 复制代码
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.lxs.demo.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

执行地址到servlet的关系

3.servlet生命周期

Servlet 是 Java Web 开发中的一种用于处理请求和响应的组件。它具有自己的生命周期,包括以下几个阶段:

  1. 加载:当容器启动首次请求到达时,Servlet 容器会加载 Servlet 类。这个阶段会创建 Servlet 类的实例,并调用其 init() 方法进行初始化。

  2. 初始化:在加载后,Servlet 容器会调用 Servlet 实例的 init() 方法进行初始化。在初始化阶段,可以执行一些必要的设置,例如读取配置文件、建立数据库连接等。init() 方法在 Servlet 的生命周期中只会被调用一次。

  3. 处理请求:在初始化完成后,Servlet 容器会根据每个请求创建一个线程,调用 Servlet 实例的 service() 方法来处理请求。在 service() 方法中,可以根据请求的类型(如 GET、POST 等)执行相应的逻辑,生成响应数据。

  4. 销毁:当容器关闭或者需要卸载 Servlet 时,会调用 Servlet 实例的 destroy() 方法进行清理操作。在该方法中,可以进行资源释放、数据库连接关闭等善后工作。destroy() 方法也只会被调用一次。

需要注意的是,每次请求都会创建一个单独的线程来处理,而不是每个请求都创建一个新的 Servlet 实例。Servlet 实例是多线程共享的,因此需要在实现中保证线程安全性。

配置参数解决输出中文乱码问题

bash 复制代码
-Dfile.encoding=UTF-8 -Dconsole.encoding=UTF-8

4.ServletConfig接口

当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象。

配置参数都在web.xml里面配置

其中几个方法如下

  1. String getServletName():获取当前 Servlet 的名称。

  2. ServletContext getServletContext():获取与当前 Servlet 相关联的 Servlet 上下文对象。

  3. String getInitParameter(String name):根据给定参数名获取相应的初始化参数值。

  4. Enumeration<String> getInitParameterNames():获取所有初始化参数的名称的枚举。

总之,ServletConfig 接口提供了一种机制,允许 Servlet 访问它的配置信息和初始化参数。这些信息对于 Servlet 的运行时行为和逻辑可能会非常有用。

5.ServletContext对象

ServletContext 对象是 Java Web 应用程序中的一个接口,它代表了整个 Web 应用程序的上下文环境。每个 Web 应用程序只有一个 ServletContext 实例,由 Servlet 容器在启动应用程序时创建,并在关闭应用程序时销毁。

ServletContext 接口提供了一系列方法,用于访问和操作与当前 Web 应用程序相关的信息和资源,包括:

  1. 获取初始化参数:可以使用 getInitParameter(String name) 方法获取部署描述符(如 web.xml 文件)中配置的初始化参数的值。通过 getInitParameterNames() 方法可以获取所有初始化参数的名称。

  2. 获取上下文路径:可以使用 getContextPath() 方法获取当前 Web 应用程序的上下文路径(Context Path)。上下文路径是 Web 应用程序被部署后的访问路径的一部分。

  3. 获取真实路径:可以使用 getRealPath(String path) 方法将给定的相对路径转换为在文件系统中的真实路径。此方法通常用于获取在 Web 应用程序中的资源的物理路径。

  4. 获取资源:可以使用 getResource(String path)getResourceAsStream(String path) 方法获取位于 Web 应用程序中的某个资源的 URL 或输入流。

  5. 设置和获取属性:可以使用 setAttribute(String name, Object value) 方法设置一个在 ServletContext 中的属性。使用 getAttribute(String name) 方法可以获取指定名称的属性的值。

除了以上几点,ServletContext 还提供了其他一些方法,用于获取 Servlet 注册信息、获取和操作 ServletContext 初始化参数等。通过 ServletContext 对象,可以在整个 Web 应用程序范围内共享数据和资源,以及访问应用程序的配置信息

6.HttpServlet抽象类

HttpServlet抽象类是继承于GenericServlet抽象类而来的。使用HttpServlet抽象类时,还需要借助分别代表Servlet请求和Servlet响应 HttpServletRequest和HttpServletResponse对象。

在实现这个抽象类之后我们可以通过重写Service方法来处理请求即可

HttpServlet 类定义了以下几个主要方法:

  1. void service(HttpServletRequest request, HttpServletResponse response):这是 HttpServlet 的核心方法,用于处理 HTTP 请求和生成 HTTP 响应。在该方法中,可以根据不同的 HTTP 方法(如 GET、POST 等)执行相应的逻辑来处理请求的参数、生成响应内容等。

  2. protected void doGet(HttpServletRequest request, HttpServletResponse response):用于处理 HTTP GET 请求的方法。默认情况下,service() 方法会调用此方法来处理 GET 请求。

  3. protected void doPost(HttpServletRequest request, HttpServletResponse response):用于处理 HTTP POST 请求的方法。默认情况下,service() 方法会调用此方法来处理 POST 请求。

  4. protected void doPut(HttpServletRequest request, HttpServletResponse response):用于处理 HTTP PUT 请求的方法。

  5. protected void doDelete(HttpServletRequest request,HttpServletResponse response):用于处理 HTTP DELETE 请求的方法。

除了上述方法,HttpServlet 还提供了一些其他的方法,如 doOptions() 用于处理 HTTP OPTIONS 请求,doHead() 用于处理 HTTP HEAD 请求等。这些方法可以根据需要进行覆盖,以实现对不同类型的 HTTP 请求的处理

7.中文乱码问题

出现中文乱码问题通常就是编码和解码不一致导致

  1. Get 请求的中文乱码解决:
    get的默认编码utf-8,以前老版本tomcat中get编码是iso-8859-1
go 复制代码
// 获取请求参数
String username = req.getParameter("username");
//1 先以 iso8859-1 进行编码
//2 再以 utf-8 进行解码
username = new String(username.getBytes("iso-8859-1"), "UTF-8");
  1. POST 请求的中文乱码解决
go 复制代码
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException,
IOException {
// 设置请求体的字符集为 UTF-8, 从而解决 post 请求的中文乱码问题
req.setCharacterEncoding("UTF-8");
System.out.println("-------------doPost------------");
// 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名: " + username);
System.out.println("密码: " + password);
System.out.println("兴趣爱好: " + Arrays.asList(hobby));
}
  1. response的乱码解决
    方式1:
go 复制代码
// 设置服务器字符集为 UTF-8
resp.setCharacterEncoding("UTF-8");
// 通过响应头, 设置浏览器也使用 UTF-8 字符集
resp.setHeader("Content-Type", "text/html; charset=UTF-8");

解决响应中文乱码方案二(推荐) :

go 复制代码
// 它会同时设置服务器和客户端都使用 UTF-8 字符集, 还设置了响应头
// 此方法一定要在获取流对象之前调用才有效
resp.setContentType("text/html; charset=UTF-8");

8.请求转发与重定向

二者区别:

一次请求与两次请求!

    1. 定义:请求转发是在服务器内部进行的一种机制,将请求从一个组件(如 Servlet)直接转发给另一个组件。重定向是通过发送特殊的响应状态码和 URL 到客户端浏览器,让浏览器重新发送一个新的请求来达到页面跳转的目的。
    1. 浏览器行为:请求转发是在服务器内部完成的,对浏览器是透明的,浏览器的 URL 不会发生变化。而重定向会向浏览器发送一个新的响应,浏览器会根据响应中的 URL 进行请求的重新发送,因此浏览器的 URL 会发生变化。
    1. 请求次数:请求转发只需要一次请求和响应的往返,所以在网络传输上效率更高。而重定向会导致两次请求和响应的往返,一次是原始请求的响应,一次是重定向后新请求的响应,相对来说会增加一定的网络开销。
    1. 共享数据:请求转发时,可以共享同一个 request 对象,在多个组件之间传递数据。而重定向是两次请求,每个请求都会有一个新的 request 对象,数据不能直接共享,需要使用其他机制(如 URL 参数、Session 等)来传递数据。
    1. 场景应用:请求转发常用于在服务器内部进行组件之间的流转,如多个 Servlet 之间的数据交互,MVC 架构中的控制器转发等。重定向常用于页面的跳转,错误处理,或者需要刷新页面的场景。

1.请求转发

请求转发(Request Forwarding)是一种在服务器端将请求从一个 Servlet 转发给另一个 Servlet 或 JSP 页面的机制。在请求转发中,客户端只发送一次请求,而服务器在内部将请求从一个组件传递到另一个组件,然后将响应返回给客户端。

  1. 在要进行请求转发的 Servlet 中,获得 RequestDispatcher 实例,可以使用以下代码:
go 复制代码
RequestDispatcher dispatcher = request.getRequestDispatcher("/targetServlet");

其中,/targetServlet 是目标 Servlet 的路径。

  1. 调用 forward() 方法来执行请求转发:
go 复制代码
dispatcher.forward(request, response);

其中,request 和 response 分别是当前 Servlet 的 HttpServletRequest 和 HttpServletResponse 对象。

请求转发的主要优点是

  • 内部流转:客户端对转发过程毫无察觉,URL 保持不变。
  • 资源共享:由于转发操作使用同一个 request 对象,可以方便地在多个组件之间共享数据。
  • 减少网络开销:只有一次请求和响应的往返,减少了网络开销。

请求转发通常用于以下情况

  • Servlet 之间数据交互:可以将请求从一个 Servlet 转发到另一个 Servlet,以便在它们之间共享数据。
  • MVC 架构中的控制器转发:根据请求的不同,将请求转发到不同的控制器来处理特定的业务逻辑。
  • 错误处理:在出现错误时,转发到专门的错误处理 Servlet 或 JSP 页面来显示错误信息。
    servlet1代码
go 复制代码
package Servlet;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/servlet1")
public class servlet1 extends HttpServlet {


    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username=req.getParameter("username");
        System.out.println(("在Servlet1(柜台1)中查看参数(材料):"+username));

        req.setAttribute("key1","柜台1的章");
        RequestDispatcher requestDispatcher =
                req.getRequestDispatcher("/servlet2");

        requestDispatcher.forward(req,resp);

    }
}

servlet2代码

go 复制代码
package Servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/servlet2")
public class servlet2 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        System.out.println("在Servlet2(柜台2)中查看参数(材料):" + username);
// 查看 柜台1 是否有盖章
        Object key1 = req.getAttribute("key1");
        System.out.println("柜台1是否有章:" + key1);
// 处理自己的业务
        System.out.println("Servlet2 处理自己的业务 ");
    }
}

2.请求重定向

请求重定向是客户端向服务器发送请求后,服务器告诉客户端要通过新的地址进行访问的过程。这个过程中,浏览器的地址栏会发生变化,发生两次请求。与请求转发不同的是,请求重定向不能共享Request域中的数据,也不能直接访问WEB-INF下的资源,但可以访问工程外的资源。123

方式一:

go 复制代码
// 设置响应状态码 302 , 表示重定向, (已搬迁)
resp.setStatus(302);
// 设置响应头, 说明 新的地址在哪里
resp.setHeader("Location", "http://localhost:8080");

方式二:

go 复制代码
resp.sendRedirect("http://localhost:8080");

servlet3:

go 复制代码
package chongdingxiang;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/servlet3")
public class servlet3 extends HttpServlet {


    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username=req.getParameter("username");
        System.out.println(("在Servlet3(柜台1)中查看参数(材料):"+username));
        this.getServletContext().setAttribute("globalKey", "hello servlet global");
        req.setAttribute("key3","柜台3的章");
//        resp.sendRedirect("http://localhost:8080/servletdemo1/servlet4");

        resp.setStatus(HttpServletResponse.SC_FOUND);
        resp.setHeader("Location","http://localhost:8080/servletdemo1/servlet4");
    }
}

servlet4:

go 复制代码
package chongdingxiang;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/servlet4")
public class servlet4 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        System.out.println("在Servlet4(柜台4)中查看参数(材料):" + username);
        System.out.println(this.getServletContext().getAttribute("globalKey"));
// 查看 柜台1 是否有盖章
        Object key1 = req.getAttribute("key3");
        System.out.println("柜台3是否有章:" + key1);
// 处理自己的业务
        System.out.println("Servlet4 处理自己的业务 ");
    }
}
相关推荐
lied16636348069 小时前
List导出到Excel文件
servlet·list·excel
starfalling102411 小时前
【hive】一种高效增量表的实现
hive
顧棟13 小时前
【Yarn实战】Yarn 2.9.1滚动升级到3.4.1调研与实践验证
hadoop·yarn
D明明就是我15 小时前
Hive 拉链表
数据仓库·hive·hadoop
嘉禾望岗50319 小时前
hive join优化和数据倾斜处理
数据仓库·hive·hadoop
yumgpkpm19 小时前
华为鲲鹏 Aarch64 环境下多 Oracle 数据库汇聚操作指南 CMP(类 Cloudera CDP 7.3)
大数据·hive·hadoop·elasticsearch·zookeeper·big data·cloudera
忧郁火龙果20 小时前
六、Hive的基本使用
数据仓库·hive·hadoop
忧郁火龙果21 小时前
五、安装配置hive
数据仓库·hive·hadoop
Predestination王瀞潞1 天前
Java EE开发技术(Servlet整合JDBC银行管理系统-上)
java·servlet·java-ee·jdbc
chad__chang1 天前
dolphinscheduler安装过程
hive·hadoop