【JavaWeb】Servlet

Servlet

1、Servlet概述

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

2、Servlet的语法格式

第一步:创建包(com.hang.servlet.demo)

第二步:创建类(com.hang.servlet.demo.MyServlet),并且需要实现Servlet接口中的所有方法

package com.hang.servlet.demo;
 
import javax.servlet.*;
import java.io.IOException;
 
public class MyServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("MyServlet init ...");
    }
 
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
 
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) 
            throws ServletException, IOException {
        System.out.println("MyServlet service ...");
    }
 
    @Override
    public String getServletInfo() {
        return null;
    }
 
    @Override
    public void destroy() {
        System.out.println("MyServlet destroy ...");
    }
}

方法介绍:

  • init:Servlet初始化时调用的方法
  • getServletConfig:获取当前Servlet的配置信息
  • service:调用Servlet真正去处理逻辑的方法
  • getServletInfo:它提供有关Servlet的信息,如作者、版本、版权
  • destroy:Servlet销毁时调用的方法

配置映射(web.xml中新增以下代码)

    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.hang.servlet.demo.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyServlet</url-pattern>
    </servlet-mapping>

配置介绍:

servlet标签用于配置Servlet的基本信息

  1. servlet-class:代表当前Servlet的具体类路径,注意最后不包含.java
  2. servlet-name:代表当前Servlet的别名,可以和原Servlet名称一样,也可以不一样,一般我们就一样就行了

servlet-mapping标签用于配置请求路径与具体处理Servlet的对应关系

  1. url-pattern:这里写你要匹配的地址路径
  2. servlet-name:如果匹配到请求,该交给哪一个Servlet处理,这里的servlet-name其实就是一个Servlet的别名

第四步:启动Tomcat

在这里插入图片描述

第五步:正常关闭Tomcat服务器,我们会看到调用销毁方法
在这里插入图片描述

3、Servlet执行过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xdo65Id3-1667446459217)(Servlet.assets/c8f679219d42f4c42a4c35fda25872a1.png)]

4、Servlet生命周期

Servlet运行在Servlet容器中,其生命周期由容器来管理。

Servlet的生命周期通过javax.servlet.Servlet接口中的init()、service()和destroy()方法来表示。

Servlet的生命周期包含了下面4个阶段:

  1. 类加载和实例化
  2. 初始化:init()
  3. 请求处理:service()
  4. 销毁:destroy()

5、servlet的继承体系

其实我们不难发现,现有的Servlet它的方法比较多,而且大多需要我们自己来实现,那有没有一种它的实现子类,把大部分方法都是实现了,而我们只要关注请求处理就行了,那答案肯定是有的,这个类就是HttpServlet,我们只要继承这个类重写GET、POST方法就能实现一个简单的Servlet请求处理,Servlet的继承体系如下图:

在这里插入图片描述

既然我们知道HttpServlet这个类了,我们就要使用一下:

第一步:创建类(com.hang.servlet.demo.MyHttpServlet),并且需要继承HttpServlet实现doPost、doGet方法。

package com.hang.servlet.demo;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
public class MyHttpServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        System.out.println("doPost method invoke ...");
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        System.out.println("doGet method invoke ...");
    }
}

第二步:配置映射(在web.xml文件中新增以下代码)

    <servlet>
        <servlet-name>MyHttpServlet</servlet-name>
        <servlet-class>com.hang.servlet.demo.MyHttpServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyHttpServlet</servlet-name>
        <url-pattern>/MyHttpServlet</url-pattern>
    </servlet-mapping>

第三步:重启Tomcat

在这里插入图片描述

我们注意url-pattern它可以有多种拦截形式:

  • 全路径匹配:/a
  • 前半段匹配:/a/b/c/*
  • 扩展名匹配:*.action

6、ServletContext

每个web工程都只有一个ServletContext对象,也就是不管在哪个Servlet里面,获取到的这个类的对象都是同一个,它用来获取Servlet的上下文,在服务器启动的时候,会为托管的每一个web应用程序,创建一个ServletContext对象,当从服务器移除托管或者是关闭服务器时,ServletContext将会被销毁。它主要有以下几方面作用:

  1. 获取全局配置参数
  2. 获取web工程中的资源
  3. 在servlet间共享数据域对象

6.1 ServletContext

ServletContext官方叫Servlet上下文。服务器会为每一个工程创建一个对象,这个对象就是ServletContext对象。这个对象全局唯一,而且工程内部的所有servlet都共享这个对象。所以叫全局应用程序共享对象。

作用

  1. 是一个域对象
  2. 可以读取全局配置参数
  3. 可以搜索当前工程目录下面的资源文件
  4. 可以获取当前工程名字(了解)

域对象介绍

域对象是服务器在内存上创建的存储空间,用于在不同动态资源(servlet)之间传递与共享数据。

域对象方法

凡是域对象都有如下3个方法:

setAttribute(name,value);name是String类型,value是Object类型;往域对象里面添加数据,添加时以key-value形式添加
getAttribute(name);根据指定的key读取域对象里面的数据
removeAttribute(name);根据指定的key从域对象里面删除数据

HttpServletRequest

HttpServletRequest这个对象封装了客户端提交过来的一切数据。

第一步:修改 index.jsp

<form action="RegisterServlet" method="get">
    账户:<input type="text" name="username"><br>
    密码:<input type="text" name="password"><br>
         <input type="submit" value="注册">
</form>

第二步:创建类(RegisterServlet)

package com.hang.servlet.demo;
 
import javafx.print.Collation;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
 
public class RegisterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取客户端传递过来的头部信息
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            System.out.println(headerName + ":" + headerValue);
        }
        System.out.println("====================");
 
        // 获取客户端传递过来的参数信息
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String parameterName = parameterNames.nextElement();
            String parameterValue = request.getParameter(parameterName);
            // 如果值有多个请使用:request.getParameterValues(parameterName)
            System.out.println(parameterName + ":" + parameterValue);
        }
        System.out.println("====================");
 
        // 以Map集合的形式获取客户端传递过来的参数信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        Set<String> names = parameterMap.keySet();
        for (String name : names) {
            String[] value = parameterMap.get(name);
            System.out.println(name + ":" + Arrays.toString(value));
        }
        System.out.println("====================");
 
        // 获取一些其它地址、查询等信息
        StringBuffer requestURL = request.getRequestURL();
        String requestURI = request.getRequestURI();
        String servletPath = request.getServletPath();
        String queryString = request.getQueryString();
        System.out.println("requestURL:" + requestURL);
        System.out.println("requestURI:" + requestURI);
        System.out.println("servletPath:" + servletPath);
        System.out.println("queryString:" + queryString);
    }
}

第三步:在web.xml中新增映射信息

    <servlet>
        <servlet-name>RegisterServlet</servlet-name>
        <servlet-class>com.hang.servlet.demo.RegisterServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RegisterServlet</servlet-name>
        <url-pattern>/RegisterServlet</url-pattern>
    </servlet-mapping>

第四步:重启Tomcat服务器

在表单输入数据,然后点击提交

在这里插入图片描述

查看IDEA的控制台信息

host:localhost:8080
connection:keep-alive
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
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
sec-fetch-site:same-origin
sec-fetch-mode:navigate
sec-fetch-user:?1
sec-fetch-dest:document
referer:http://localhost:8080/myJavaWebDemo_war_exploded/
accept-encoding:gzip, deflate, br
accept-language:zh-CN,zh;q=0.9
cookie:JSESSIONID=4342FA7CB5F51C5E4A5251E485E36E38
====================
username:zhangsan
password:123456
====================
username:[zhangsan]
password:[123456]
====================
requestURL:http://localhost:8080/myJavaWebDemo_war_exploded/RegisterServlet
requestURI:/myJavaWebDemo_war_exploded/RegisterServlet
servletPath:/RegisterServlet
queryString:username=zhangsan&password=123456

如何解决请求数据中文乱码问题?

GET方法

// 先用原来的编码解码再用UTF—8重新编码。
String newUsername = new String(username.getBytes("ISO-8859-1"), "UTF-8");

POST方法

// 这行设置一定要写在getParameter之前。
request.setCharacterEncoding("UTF-8");

HttpServletResponse

HttpServletResponse这个对象负责返回数据给客户端。

第一步:创建类(DisplayServlet)

package com.hang.servlet.demo;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
public class DisplayServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        /**
         * 注意:以下两种方式一次只能使用一种,我们就用字符流方式了,另一种自己演示
         */
        // 以字符流的方式写数据
        response.getWriter().write("<h1>hello response 111 ...</h1>");
 
        // 以字节流的方式写数据
        // response.getOutputStream().write("hello response 222 ...".getBytes());
    }
}

第二步:在web.xml文件中新增以下映射信息

    <servlet>
        <servlet-name>DisplayServlet</servlet-name>
        <servlet-class>com.hang.servlet.demo.DisplayServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DisplayServlet</servlet-name>
        <url-pattern>/DisplayServlet</url-pattern>
    </servlet-mapping>

第三步:重启Tomcat服务器

在这里插入图片描述

如何解决响应数据中文乱码问题?

  • 以字符流输出:response.getWriter()

    • response.setCharacterEncoding("UTF-8");
      response.setHeader("Content-Type", "text/html; charset=UTF-8");
      response.getWriter().write("你好,世界!");
      
  • 以字节流输出:response.getOutputStream()

    • response.setHeader("Content-Type", "text/html;charset=UTF-8");
      response.getOutputStream().write("你好,世界!".getBytes("UTF-8"));
      

重定向和请求转发

在这里插入图片描述

重定向

	// 第一种:使用示例
	response.setStatus(302);
	response.setHeader("Location", "login_success.html");*/
		
	// 第二种:使用示例
	response.sendRedirect("login_success.html");
 
	1. 地址上显示的是最后的那个资源的路径地址。
 
	2. 请求次数最少有两次,服务器在第一次请求后,会返回302以及一个地址,浏览器在根据这个地址,执行第二次访问。
 
	3. 可以跳转到任意路径,不是自己的工程也可以跳。
 
	4. 效率稍微低一点,执行两次请求。 
 
	5. 后续的请求,没法使用上一次的request存储的数据,或者没法使用上一次的request对象,因为这是两次不同的请求。

请求转发

// 使用示例:
request.getRequestDispatcher("login_success.html").forward(request, response);
 
1. 地址上显示的是请求servlet的地址,返回200ok。
 
2. 请求次数只有一次,因为是服务器内部帮客户端执行了后续的工作。 
 
3. 只能跳转自己项目的资源路径。  
 
4. 效率上稍微高一点,因为只执行一次请求。 
 
5. 可以使用上一次的request对象。

Cookie

Cookie其实是一份小数据,它是服务器给客户端并且存储在客户端上的一份小数据。
在这里插入图片描述

Cookie[] cookies = req.getCookies(); //获得Cookie
cookie.getName(); //获得cookie中的key
cookie.getValue(); //获得cookie中的vlaue
new Cookie("lastLoginTime", System.currentTimeMillis()+""); //新建一个cookie
cookie.setMaxAge(24*60*60); //设置cookie的有效期
resp.addCookie(cookie); //响应给客户端一个cookie
  • 一个Cookie只能保存一个信息;
  • 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie;
  • Cookie大小有限制4kb;
  • 300个cookie浏览器上限
  • 不设置有效期,关闭浏览器,自动失效;
  • 设置有效期时间为 0 ;

Session

由于Cookie会保存在客户端上,所以有安全隐患问题。还有一个问题,Cookie的大小与个数有限制,为了解决这个问题,于是就有了Session,Session是基于Cookie的一种会话机制。Cookie是服务器返回一小份数据给客户端,并且存放在客户端上。Session是数据存放在服务器端。

常见用法:

// 获取Session对象
HttpSession session = request.getSession();

// 获取SessionID
String id = session.getId();

//存值
session.setAttribute(name, value);

//取值
session.getAttribute(name);

//删值
session.removeAttribute(name);

生命周期:

  • 创建:如果有在servlet里面调用了 request.getSession()
  • 销毁:关闭服务器或者session会话时间过期。默认有效期: 30分钟。

限制,为了解决这个问题,于是就有了Session,Session是基于Cookie的一种会话机制。Cookie是服务器返回一小份数据给客户端,并且存放在客户端上。Session是数据存放在服务器端。

常见用法:

// 获取Session对象
HttpSession session = request.getSession();

// 获取SessionID
String id = session.getId();

//存值
session.setAttribute(name, value);

//取值
session.getAttribute(name);

//删值
session.removeAttribute(name);

生命周期:

  • 创建:如果有在servlet里面调用了 request.getSession()
  • 销毁:关闭服务器或者session会话时间过期。默认有效期: 30分钟。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值