Servlet基础笔记

149 阅读9分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Servlet

什么是Servlet

  1. Servlet是JavaEE规范之一。规范就是接口
  2. Servlet就是JavaWeb三大组件之一(Servlet程序、Filter过滤器、Listener监听器)
  3. Servlet是运行在服务器上的一个java小程序,它可以接收客户端发送过来的请求,并响应数据给客户端

手动实现Servlet程序

  1. 编写一个类去实现Servlet接口
  2. 实现service方法,处理请求,并响应数据
  3. 到web.xml中去配置Servlet程序的访问地址

创建Servlet程序

  1. 在src目录下新建包,包中创建Servlet实现类

  2. 类中继承接口,并将方法覆盖重写(alt+insert) 要注意引入了jar包,我在这里将jar包复制进web/WEB-INF/lib文件夹下(要记得右击添加到类库哦,下拉框选模块)👇

    package com.hexing.servlet;
    
    import jakarta.servlet.*;
    
    import java.io.IOException;
    
    public class HelloServlet implements Servlet {
        @Override
        public void init(ServletConfig servletConfig) throws ServletException {
    
        }
    
        @Override
        public ServletConfig getServletConfig() {
            return null;
        }
    
    //    service方法是专门用来处理请求和相应的
    //    @param servletRequest
    //    @param servletResponse
    //    @throws ServletException
    //    @throws IOException
    //
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
            System.out.println("Hello Servlet 被访问了");
        }
    
        @Override
        public String getServletInfo() {
            return null;
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    
    
  3. 在web.xml文件中配置Servlet程序👇

    <!--  servlet标签给Tomcat配置Servlet程序  -->
        <servlet>
        <!--    servlet-name标签 Servlet程序起一个别名(一般是类名)    -->
            <servlet-name>HelloServlet</servlet-name>
        <!--    servlet-class是Servlet程序的全类名    -->
            <servlet-class>com.hexing.servlet.HelloServlet</servlet-class>
        </servlet>
    
        <!--    servlet-mapping标签给servlet程序配置访问地址    -->
        <servlet-mapping>
            <!--    servelet-name标签的作用是告诉服务器,我当前配置的地址给哪个Servlet程序使用    -->
            <servlet-name>HelloServlet</servlet-name>
            <!--    url-pattern标签配置访问地址     <br/>
                    /在服务器解析的时候,表示地址为:http://ip:port/配置Tomcat时填写的工程路径    <br/>
    
            -->
            <url-pattern>/hello</url-pattern>
        </servlet-mapping>
    
  4. 最后记住配置的地址,在运行打开网页后,在链接后跟url-pattern,即可访问servlet程序

创建过程中的常见错误:

  1. url-pattern中配置的路径没有以斜杠打头
  2. servlet-name配置的值不存在

Servlet-url到Servlet程序的访问过程

Servlet的生命周期

  1. 执行Servlet构造器方法

  2. 执行init初始化方法

    第1、2步,是在第一次访问的时候创建Servlet程序会调用

  3. 执行service方法

    第3步,每次访问都会调用

  4. 执行destroy销毁方法

    第4步,在web工程停止的时候调用

public void HelloSevlet(){
        System.out.println("1 构造器方法");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("2 初始化方法");
    }
    
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("3 Service方法---Hello Servlet 被访问了");
    }
    
    @Override
    public void destroy() {
        System.out.println("4 destroy销毁方法");
    }

请求的分发处理

获取请求方式

@Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("3 Service方法---Hello Servlet 被访问了");
        //类型转换(因为它有getMethod()方法)
        HttpServletRequest HttpServletRequest = (HttpServletRequest) servletRequest;
        //获取请求的方式
        String method = HttpServletRequest.getMethod();
        System.out.println(method);
        
        if ("GET".equals(method)){
            doGet();
        }else if ("POST".equals(method)){
            doPost();
        }
    }
//    做get请求的操作
    public void doGet(){
        System.out.println("get请求");
    }

//    做post请求的操作
    public void doPost(){
        System.out.println("post请求");
    }

通过继承HttpServlet实现Servlet程序

一般在实际项目开发中,都是使用继承HttpServlet类的方式去实现Servlet程序

  1. 编写一个类去继承HttpServlet类

  2. 根据业务需要重写doGet或doPost方法

    package com.hexing.servlet;
    
    import jakarta.servlet.ServletException;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    
    public class HelloServlet2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doGet(req, resp);
        }
    }
    
  3. 到web.xml中配置Servlet程序的访问地址

    <servlet>
            <servlet-name>HelloServlet2</servlet-name>
            <servlet-class>HelloSer</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>HelloServlet2</servlet-name>
            <url-pattern>/hello2</url-pattern>
        </servlet-mapping>
    

IDEA菜单生成Servlet程序

右键包→new→Create New Servlet

最后在xml文件中配置一下就欧克啦

Servlet类的继承体系

ServletConfig类

Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用。

Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象。

三大作用

  1. 获取Servlet程序的别名servlet-name的值(servletConfig.getServletName();)

  2. 获取初始化参数init-param(写在xml的<servlet>中)(servletConfig.getInitParameter("username");)

    		<init-param>
                <!--      参数名      -->
                <param-name>username</param-name>
                <!--      参数值      -->
                <param-value>root</param-value>
            </init-param>
            <init-param>
                <!--      参数名      -->
                <param-name>url</param-name>
                <!--      参数值      -->
                <param-value>jdbc:mysql//localhost:3306/test</param-value>
            </init-param>
    
  3. 获取ServletContext对象(servletConfig.getServletContext();)

创建ServletConfig对象

ServletConfig servletConfig = getServletConfig();

一些注意事项

如果重写init方法,要注意调用父方法

super.init(config);

父方法中有this.config = config这一保存过程,将tomcat服务器提供的config对象保存在GenericServlet对象中,若重写子方法后未调用则会导致该过程丢失,出现报错

ServletContext类

  1. Servlet是一个接口,它表示Servlet上下文对象
  2. 一个web工程,只有一个ServletContext对象实例,创建多个则可当作别名,实质上还是一个对象
  3. ServletContext对象是一个域对象

域对象:

可以像Map一样存取数据的对象,叫域对象

这里的域指的是存取数据的操作范围

存数据取数据删除数据
Mapput()get()remove()
域对象setAttribute()getAttribute()removeAttribute()

四大作用

  1. 获取web.xml中配置的上下文参数context-param

    <!--  context-param是上下文参数(它属于整个web工程)  -->
        <context-param>
            <param-name>username</param-name>
            <param-value>context</param-value>
        </context-param>
        <!--  context-param是上下文参数(它属于整个web工程)  -->
        <context-param>
            <param-name>password</param-name>
            <param-value>root</param-value>
        </context-param>
    
    ServletContext context = getServletConfig().getServletContext();
    //或直接ServletContext context = getServletContext();该方法里面写的就是上面的形式
    context.getInitParameter(param-name);
    
  2. 获取当前的工程路径,格式:/工程路径

    contetx.getContextPath();
    
  3. 获取工程部署后在服务器硬盘上的绝对路径(以/作为参数表示当前相对路径的根目录---工程目录)

      context.getRealPath("/");
    
  4. 像Map一样存取数据

    //存储,存储前key1的值为null
    context.setAttribute("key1","value1");
    //获取
    context.getAttribute("key1");
    

HTTP协议

请求的HTTP协议格式

客户端给服务器发送数据叫请求,服务器给客户端回传数据叫相应

请求又分为GET请求和POST请求两种

GET请求
  1. 请求行
    1. 请求方式 GET
    2. 请求的资源路径[+?+请求参数]
    3. 请求的协议的版本号 HTTP/1.0
  2. 请求头 key:value组成,不同的键值对,表示不同的含义

POST请求

  1. 请求行
    1. 请求方式 POST
    2. 请求的资源路径[+?+请求参数]
    3. 请求的协议的版本号 HTTP/1.0
  2. 请求头
    1. key:value 不同的请求头,有不同的含义 空行
  3. 请求体

常用请求头

  • Accept:表示客户端可以接收的数据类型
  • Accept-Languege:表示客户端可以接收的语言类型
  • User-Agent:表示客户端浏览器的信息
  • Host:表示请求时的服务器IP和端口号

GET请求动作与POST请求动作

GET请求
  • form标签 method = get
  • a标签
  • link标签引入css
  • Script标签引入js文件
  • img标签引入图片
  • iframe引入html页面
  • 在浏览器地址栏中输入地址后敲回车
POST请求
  • form标签 method = post

响应的HTTP协议格式

  1. 响应行
    1. 响应的协议和版本号 HTTP/1.1
    2. 响应状态码 200
    3. 响应状态描述符 ok
  2. 响应头
    1. key:value 不同的响应头,有其不同含义 空行
  3. 响应体:回传给客户端的数据

常用的响应码

  • 200 表示请求成功
  • 302 表示请求重定向
  • 404 表示请求服务器已收到,但数据不存在(请求地址错误)
  • 500 表示服务器已经收到请求,但是服务器内部错误(代码)

MIME(Multipurpose Internet Mail Extensions)类型说明

MIME是HTTP协议中数据类型,MIME类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应

谷歌、火狐浏览器查看HTTP协议

HttpServletRequest类

每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中,然后传递到service方法(doGet和doPost)中给我们使用。我们可以通过HttpServletRequest对象,获取到所有请求的信息。

常用方法
  1. getRequestURI()----获取请求的资源路径
  2. getRequestURL()----获取请求的统一资源定位符(绝对路径)
  3. getRemoteHost()---获取客户端的ip地址
  4. getHeader()-----获取请求头
  5. getParameter()----获取请求的参数
  6. getParameterValues()----获取请求的参数(多个值的时候使用)
  7. getMethod()----获取请求的方式GET/POST
  8. setAttribute(key, value)---设置域数据
  9. getAttribute(key)----获取域数据
  10. getRequestDispatcher()----获取请求转发对象

**注意:**post请求时中文会乱码,需在获取请求参数前调用httpServletRequest.setCharacterEncoding("UTF-8");来更改编码格式

请求转发

请求转发是指,服务器收到请求后,从一个资源跳转到另一个资源的操作叫做转发。

RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");//“/”映射到web目录
requestDispatcher.forward(req,resp);

特点:

  1. 浏览器地址栏没有变化
  2. 他们是一次请求
  3. 他们共享Request域中的数据
  4. 可以转发到WEB-INF目录下
  5. 不可以访问工程以外的资源

base标签

base标签可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转

web中“/”的不同意义

在web中“/”是一种绝对路径

如果“/”被浏览器解析,得到的地址是:http://ip:port/

如果被服务器解析,得到的地址是:http://ip:port/工程路径

但如果是response.sendRediect("/"); 将“/”发送给浏览器解析,得到http://ip:port/

HttpServletResponse类

HttpServletResponse类和HttpServletRRequest类一样。每次请求进来,Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用。HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有响应的信息。

如果需要设置返回给客户端的信息,都可以通过HttpServletResponse对象来进行设置。

两个输出流
  • 字节流---getOutputStream();---常用于下载(传递二进制数据)
  • 字符流---getWriter();---常用于回传字符串

两个流同时只能使用一个

使用了字节流,就不能再使用字符流,反之亦然,否则会报错。

//解决乱码问题方案一:
resp.setCharacterEncoding("UTF-8");//设置服务器字符集
resp.setHeader("Content-Type","text/html; charset=UTF-8");//通过响应头设置浏览器字符集


//解决乱码问题方案二:
resp.setContentType("text/html; charset-UTF-8");//它会同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头。但此方法一定要在获取流对象之前调用才有效

请求重定向

特点:

  1. 浏览器地址栏会发生变化
  2. 两次请求
  3. 不共享Request域中数据
  4. 不能访问WEB-INF下的资源
  5. 可以访问工程外的资源
请求重定向第二种实现方式
resp.sendRedirect("http://localhost:8080");

JavaEE三层架构

分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。