2.3.3 Servlet, 生命周期, 体系结构, xml配置, 请求和响应对象, 转发与重定向, ServletContext共享数据

2023-11-18

目录

一 Servlet概述

二 Servlet快速入门

2.1 案例需求:编写一个普通的java类,通过浏览器可以访问

2.2 servlet执行原理

三 Servlet生命周期

3.1 生命周期相关

3.1.1 思想介绍

3.1.2 代码演示

四 Servlet体系结构

4.1 GenericServlet

4.2 HttpServlet

五 url-pattern的配置方式

5.1 Servlet映射多个url

5.2 url映射模式

六 Request对象

6.1 request对象概述

6.2 获取请求行信息

6.3 获取请求头信息

6.4 获取请求体信息(请求参数)【重点】

6.5 请求转发

6.6 域对象(共享数据)

七 Response对象

7.1 概述

7.2 设置Http响应消息

7.3 响应重定向

7.4 响应中文

八 ServletContext

8.1 概述

8.2 域对象(共享数据)

8.3 获取资源在服务器的真实地址

8.4 获取全局的配置参数

8.5 获取文件MIME类型

8.6 案例:统计网站的访问次数


 

一 Servlet概述

servlet= server+applet :运行在服务器端的java程序。
Servlet是一个接口,一个类要想通过浏览器被访问到,那么这个类就必须直接或间接的实现Servlet接口

作用
接收请求,处理逻辑,响应结果

二 Servlet快速入门

2.1 案例需求:编写一个普通的java类,通过浏览器可以访问

步骤分析:

① 创建web项目
② 编写普通java类,实现servlet接口
③ 在web.xml配置url-pattern
④ 部署web项目
⑤ 启动测试

编写java类

package com.lg.servlet;

import javax.servlet.*;
import java.io.IOException;

/**
 * @author CH
 * @date 2020/11/19 10:51
 */
public class QuickServlet implements Servlet {


    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /*
        对外提供服务的方法, tomcat会调用servlet中的service方法, 执行具体的业务逻辑
        servletRequest: 请求对象, 借助该对象获取请求参数
        servletResponse: 响应对象, 借助该对象向浏览器响应一些数据
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("servlet入门成功了...");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

编写XML配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!--配置QuickSerlvet
           servlet-name : 当前配置的servlet起一个别名(名称)
           servlet-class: 编写的就是配置的servlet的全限定类名
      -->
    <servlet>
        <servlet-name>QuickServlet</servlet-name>
        <servlet-class>com.lg.servlet.QuickServlet</servlet-class>
    </servlet>


    <!--
        servlet-mapping:给servlet设置一个映射地址
            servlet-name:给指定名称的servlet来配置映射地址
            url-pattern:具体该serlvet的映射地址(访问路径) *必须以/开头
    -->
    <servlet-mapping>
        <servlet-name>QuickServlet</servlet-name>
        <url-pattern>/quickServlet</url-pattern>
    </servlet-mapping>

</web-app>


项目部署后访问网址idea的tomcat控制台会打印

 

2.2 servlet执行原理

三 Servlet生命周期

3.1 生命周期相关

3.1.1 思想介绍

生命周期:指的是 一个对象从生(创建)到死(销毁)的一个过程

// 1. servlet对象创建时,调用此方法
public void init(ServletConfig servletConfig);
// 2. 用户访问servlet时,调用此方法
public void service(ServletRequest servletRequest, ServletResponse
servletResponse);
// 3. servlet对象销毁时,调用此方法
public void destroy();

 

3.1.2 代码演示

① LifeServlet

package com.lg.life;

import javax.servlet.*;
import java.io.IOException;

/**
 * @author CH
 * @date 2020/11/19 12:46
 */
public class LifeServlet implements Servlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("LifeServlet的init方法执行了,该对象被创建完成了...");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("LifeServlet的service方法执行了,执行了具体的业务逻辑...");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("LifeServlet的destroy方法执行了,该对象被销毁了...");
    }
}

② 配置web.xml

<!--LifeSerlvet-->
    <servlet>
        <servlet-name>LifeSerlvet</servlet-name>
        <servlet-class>com.lg.life.LifeServlet</servlet-class>

        <!--配置上该标签,serlvet就会在启动服务器的时候去完成实例化,并进行初始化操作
            标签内部需要写数值  正整数 1-3在tomcat的web.xml被使用了,所以建议从4开始使用
        -->
        <load-on-startup>4</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>LifeSerlvet</servlet-name>
        <url-pattern>/LifeSerlvet</url-pattern>
    </servlet-mapping>

 <!--配置上该标签,serlvet就会在启动服务器的时候去完成实例化,并进行初始化操作
            标签内部需要写数值  正整数 1-3在tomcat的web.xml被使用了,所以建议从4开始使用
        -->
        <load-on-startup>4</load-on-startup>

* 创建
1)默认情况下

        用户第一次访问时,创建servlet,执行init方法

2)修改创建时机
        <load-on-startup></load-onstartup>
        正数:4-N 【服务器启动时,创建】
                补充:Tomcat的web.xml里有1,3 所以推荐4-n
        负数(默认值):-1 【用户第一次访问时,创建】

* 运行(提供服务)
        用户每次访问时,都执行service方法

* 销毁
        服务器正常关闭时,销毁servlet,执行destroy方法
```

笔试题:请描述下servlet的生命周期:
        答案:servlet是一个单实例多线程的,默认情况下,第一次请求来的时候,才会对该servlet进行实例化,并执行初始化init方法,随后再执行service方法完成业务处理,当每一次请求发送过来,都会重新开启一个线程,来执行servlet中的service方法,当服务器关闭或者servlet被移除的时候,会执行destory方法

 

四 Servlet体系结构

 

4.1 GenericServlet

① 编写普通java类,继承GenericServlet抽象类

package com.lagou.servlet;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;

public class ServletDemo1 extends GenericServlet {

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("ServletDemo1的初始化方法执行了..");
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("ServletDemo1 extends GenericServlet...");
    }


    @Override
    public void destroy() {
        super.destroy();
        System.out.println("ServletDemo1的销毁方法执行了");
    }
}

② 配置web.xml

<!--ServletDemo1-->
    <servlet>
        <servlet-name>ServletDemo1</servlet-name>
        <servlet-class>com.lagou.servlet.ServletDemo1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ServletDemo1</servlet-name>
        <url-pattern>/servletDemo1</url-pattern>
    </servlet-mapping>

 

 

4.2 HttpServlet

① 编写前端html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>login</title>
</head>
<body>
<h3>用户登录</h3>
<form action="http://localhost:8080/servlet_demo/servletDemo2" method="get">
  <input type="submit" value="提交表单..">
</form>
</body>
</html>

② 编写普通java类,继承HttpServlet抽象类, 重写doGet和doPost

package com.lagou.servlet;

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 ServletDemo2 extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("ServletDemo2中的doGet方法执行了...");

    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("ServletDemo2中的doPost方法执行了...");
    }
}

③ 配置web.xml

<!--ServletDemo2-->
    <servlet>
        <servlet-name>ServletDemo2</servlet-name>
        <servlet-class>com.lagou.servlet.ServletDemo2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ServletDemo2</servlet-name>
        <url-pattern>/servletDemo2</url-pattern>
    </servlet-mapping>

 

五 url-pattern的配置方式

 

5.1 Servlet映射多个url

 

5.2 url映射模式

配置 url地址取值可以是:

1. 精确匹配(掌握)
         /servletDemo3         如:   localhost:8080/项目路径/servletDemo3

2. 目录匹配
         /aa/*        只要是aa目录下的都可以访问

3. 后缀匹配
         *.xxx 例如:*.do          是要后缀名是 .do 都可以访问

<!--
    只要浏览器符合目录匹配规则,都可以访问到这个servlet:
      /aa/abc
      /aa/asadfasdf
-->
<servlet>
  <servlet-name>ServletDemo4</servlet-name>
  <servlet-class>com.lagou.servlet.QuickServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>ServletDemo4</servlet-name>
  <url-pattern>/aa/*</url-pattern>
</servlet-mapping>
<!--
      只要浏览器符合后缀匹配规则,都可以访问到这个servlet
        aa.do
        bb.do
        xx.do
-->
<servlet>
  <servlet-name>ServletDemo5</servlet-name>
  <servlet-class>com.lagou.servlet.QuickServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>ServletDemo5</servlet-name>
  <url-pattern>*.do</url-pattern>
</servlet-mapping>

 

六 Request对象

6.1 request对象概述

  • 用户通过浏览器访问服务器时,Tomcat将HTTP请求中所有的信息都封装在Request对象中
  • 作用:开发人员可以通过request对象方法,来获取浏览器发送的所有信息.

 

6.2 获取请求行信息

* 例如:
        GET /servlet_demo/requestDemo1 HTTP/1.1
* 相关API:
1. 获取请求方式    GET【掌握】
        String    getMethod() 

2. 获取项目虚拟路径(项目名)   /servlet_demo【掌握】
        String    getContextPath() 

3. 获取URL      http://localhost:8080/servlet_demo/requestDemo1
        统一资源定位符(确定某一个地址) 中华人民共和国
        StringBuffer    getRequestURL() 

4. 获取协议和版本号 HTTP/1.1
        String    getProtocol()

5. 获取客户端ip
        String    getRemoteAddr()

package com.lagou.request;


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 RequestDemo1 extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 演示request对象获取请求行信息
        System.out.println("请求方式:" + request.getMethod());
        System.out.println("虚拟路径:" + request.getContextPath());
        System.out.println("URL:" + request.getRequestURL());
        System.out.println("协议和版本:" + request.getProtocol());
        System.out.println("客户端IP地址:"+ request.getRemoteAddr());
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req,resp);
    }
}

 

6.3 获取请求头信息

* 例如:
        Host: 127.0.0.1:8080
* 相关API:
1. 获取知道请求头名称对应的值,注:名称不区分大小写

        String    getHeader(String name) 
2. 获取所有请求头的名称
        Enumeration<String>    getHeaderNames() 
        注:是Iterator前身

package com.lagou.request;

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.Enumeration;

public class RequestDemo2 extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
          // 获取请求头信息
        // 获取指定的头信息 Host
        String host = request.getHeader("Host");
        System.out.println("指定的请求头信息Host是: " + host);

        // 先获取到所有的请求头名称
        Enumeration<String> headerNames = request.getHeaderNames();
        //遍历
        while (headerNames.hasMoreElements()){
            // 请求头名称
            String name = headerNames.nextElement();
            // 根据名称获取值
            String value = request.getHeader(name);

            System.out.println("请求头" + name + "的信息是: " + value);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

 

6.4 获取请求体信息(请求参数)【重点....】

不论get还是post请求方式,都可以使用下列方法来获取请求参数

* 参数
username=jack&password=123&hobby=drink&hobby=perm

* API
1. 获取指定参数名的值 username=jack

String     getParameter(String name)

2. 获取指定参数名的值数组 hobby=drink&hobby=perm
String[]     getParameterValues(String name)

3. 获取所有参数名和对应值数组,参数名 name(key),值数组 value,封装map集合
Map<String,String[]>    getParameterMap()

* 中文乱码【重点】
        get:在tomcat8及以上版本,内部URL编码(UTF-8)
        post:编码解码不一致,造成乱码现象
                客户端(浏览器)编码:UTF-8
                服务器默认   解码:ISO-8859-1 拉丁文

                指定解码:void setCharacterEncoding(String env)
                       注:这哥们必须在方法内,行首

 ①创建一个表单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<h3>get方式提交表单:</h3>
  <form action="/servlet_demo/requestDemo3" method="get">
      用户:<input type="text" name="username"><br>
      密码:<input type="password" name="password"><br>
      爱好:
        <input type="checkbox" name="hobby" value="smoking"/> 抽烟
        <input type="checkbox" name="hobby" value="drink"/> 喝酒
        <input type="checkbox" name="hobby" value="perm"/> 烫头

      <input type="submit" value="get提交">
  </form>

<h3>post方式提交表单:</h3>
  <form action="/servlet_demo/requestDemo3" method="post">
      用户:<input type="text" name="username"><br>
      密码:<input type="password" name="password"><br>
      爱好:
      <input type="checkbox" name="hobby" value="smoking"/> 抽烟
      <input type="checkbox" name="hobby" value="drink"/> 喝酒
      <input type="checkbox" name="hobby" value="perm"/> 烫头

      <input type="submit" value="post提交">
  </form>

</body>
</html>

② 编写java 的HttpServlet, 重写doGet doPost

package com.lagou.request;

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.Arrays;
import java.util.Map;

public class RequestDemo3 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
        
        // 获取表单提交的请求参数
        String username = request.getParameter("username");

        System.out.println("用户名:" + username);

        // 获取爱好这样的多个value的数组类型
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println( Arrays.toString(hobbies));

        // 获取所有的请求参数的key和value  String:表单中的name属性值   String[]:请求参数的value值
        Map<String, String[]> parameterMap = request.getParameterMap();
        parameterMap.forEach((k,v)->{
            System.out.println(k + "=" + Arrays.toString(v));
        });
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
        // 设置解码为UTF-8 ,解决post中文乱码问题
        // 下面的语句必须放在首行
        request.setCharacterEncoding("UTF-8");   //可以放到get中
        doGet(request, resp);                   //让doGet方法中业务逻辑执行
    }
}

 

6.5 请求转发

一种在服务器内部的资源跳转方式

* API
1. 通过reqeust对象,获得转发器对象

        RequestDispatcher getRequestDispatcher(String path)      //要跳转到的z

2. 通过转发器对象,实现转发功能
        void forward(ServletRequest request, ServletResponse response) 

* 请求转发特点
        浏览器:发了一次请求
        地址栏:没有发生改变
        只能转发到服务器内部资源....

* 链式编程
        request.getRequestDispatcher("/bServlet").forward(reqeust,response)

① 编写AServlet转发信息给BServlet ,  getRequestDispatcher, 

package com.lagou.request;

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 AServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("AServlet中功能上执行了");

        // 请求转发到Bservelt String path: 写的就是要跳转的资源路径
    /*    // 1.获取到转发器对象
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("https://www.baidu.com/");

        // 2.借助转发器对象进行真正的请求转发
        requestDispatcher.forward(request,resp);*/

        // 链式编程
        request.getRequestDispatcher("/bServlet").forward(request,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

② 编写BServlet接收AServlet转发的信息  

package com.lagou.request;

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 BServlet extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 从request域中取出数据
        String hanbao = (String) req.getAttribute("hanbao");
        System.out.println(hanbao);
       
        // 向request域中设置数据
        request.setAttribute("hanbao","香辣鸡腿堡");

        System.out.println("BServlet中功能下执行了");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

③ 配置xml文件 

    <!--ASerlvet-->
    <servlet>
        <servlet-name>ASerlvet</servlet-name>
        <servlet-class>com.lagou.request.AServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ASerlvet</servlet-name>
        <url-pattern>/aServlet</url-pattern>
    </servlet-mapping>

    <!--BSerlvet-->
    <servlet>
        <servlet-name>BSerlvet</servlet-name>
        <servlet-class>com.lagou.request.BServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>BSerlvet</servlet-name>
        <url-pattern>/bServlet</url-pattern>
    </servlet-mapping>

 

6.6 域对象(共享数据)

域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于一次请求中转发的多个资源中共享数据

package com.lagou.request;

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 AServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("AServlet中功能上执行了");

        // 向request域中设置数据
        request.setAttribute("hanbao","香辣鸡腿堡");

        // 链式编程
        request.getRequestDispatcher("/bServlet").forward(request,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}
package com.lagou.request;

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 BServlet extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 从request域中取出数据
        String hanbao = (String) req.getAttribute("hanbao");
        System.out.println(hanbao);

        System.out.println("BServlet中功能下执行了");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }
}

 

七 Response对象

7.1 概述

response对象表示web服务器给浏览器返回的响应信息
作用:开发人员可以使用response对象的方法,设置要返回给浏览器的响应信息

Response体系结构

ServletResponse 接口
        |
HttpServletResponse 接口
        |
org.apache.catalina.connector.ResponseFacade 实现类(由tomcat提供的)

 

7.2 设置Http响应消息

响应行

响应头

响应体【重点】

 

7.3 响应重定向

需求:用户访问AServlet后,服务器告诉浏览器重定向到BServlet

步骤分析

* 方式一
        // 1.设置状态码

                response.setStatus(302);
        // 2.设置响应头 Location
                response.setHeader("Location","重定向网络地址");
* 方式二
        // 1.response这哥们封装专门处理重定向的方法

                response.sendRedirect("重定向网络地址");

重定向特点

1. 地址栏会发生改变
2. 重定向是二次请求, 每次请求都会创建request对象
3. 重定向是客户端(浏览器)行为,可以跳转到服务器外部资源...
4. 不能使用request域共享数据

package com.lagou.response;

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 CServlet extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("访问到了CSerlvet,接下来重定向到DServlet");

        // 设置重定向
      /*  resp.setStatus(302);
        resp.setHeader("Location","dServlet");*/

        // 设置重定向 方式二:常用, 重点掌握
        resp.sendRedirect("https://www.lagou.com/");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
package com.lagou.response;

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 DServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("DServlet执行了.....");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--CSerlvet-->
    <servlet>
        <servlet-name>CServlet</servlet-name>
        <servlet-class>com.lagou.response.CServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CServlet</servlet-name>
        <url-pattern>/cServlet</url-pattern>
    </servlet-mapping>


    <!--DSerlvet-->
    <servlet>
        <servlet-name>DSerlvet</servlet-name>
        <servlet-class>com.lagou.response.DServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DSerlvet</servlet-name>
        <url-pattern>/dServlet</url-pattern>
    </servlet-mapping>

请求转发与重定向的区别

1. 哪个对象
        转发(request对象的方法)

                request. getRequestDispatcher("/bServlet"). forward(request,response);

        重定向(response对象的方法)
                response. sendRedirect("/day10_response/bServlet ");

2. 几次请求
        转发

                地址栏: 没有改变
                浏览器: 发了一次请求
                服务器: 只有一对请求和响应对象
                发生的位置: 服务器

        重定向
                地址栏: 发生了改变
                浏览器: 发了两次请求
                服务器: 有两对请求和响应对象
                发生的位置: 浏览器
3. 小结
        写法

                转发("/servlet资源路径") 服务器内部行为
                重定向 ("/虚拟路径(项目名)/servlet资源路径") 浏览器外部行为

        使用场景(重点掌握)
                如果需要传递数据(request域),使用转发
                如果不需要传递数据(request域),使用重定向

 

7.4 响应中文


需求

向页面输出中文数据没有乱码

步骤分析

1. 通过response获取字符输出流
        PrintWriter pw = response.getWriter();

2. 通过字符输出输出文本
        pw.write("中文....");

 解决中文乱码

1. 指定服务器响应编码方式
       response.setCharacterEncoding("GBK");

2. 统一浏览器和服务器编码
       response.setContentType("text/html;charset=utf-8");

package com.lagou.response;

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.io.PrintWriter;

public class EncodeServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 设置编码时,一定要写在首行
        //resp.setCharacterEncoding("GBK");

        // 统一浏览器和服务器编码
        resp.setContentType("text/html;charset=utf-8");

        // 向页面输出中文
        PrintWriter writer = resp.getWriter();
        writer.write("中文..");
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--EncodeServlet-->
    <servlet>
        <servlet-name>EncodeServlet</servlet-name>
        <servlet-class>com.lagou.response.EncodeServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>EncodeServlet</servlet-name>
        <url-pattern>/encodeServlet</url-pattern>
    </servlet-mapping>

八 ServletContext

8.1 概述

web容器(tomcat)在启动时,它会为每个web项目承建一个对应的ServletContext对象
它代表:当前web项目

 

主要作用

1. 域对象(共享数据)
2. 获取资源在服务器的真实地址
3. 获取全局的配置参数
4. 获取文件MIME类型

获取ServletContext对象

1. 通过request对象获得
        ServletContext sc = request.getServletContext();
2. 继承HttpServlet后,可以直接调用
        ServletContext sc = this.getServletContext();

 

8.2 域对象(共享数据)

在当前项目范围内,共享数据(多个servlet都可以获取)

1. 存储数据
        void setAttribute(String name,Object value)
2. 获取数据
        Object getAttribute(String name)
3. 删除数据
        void removeAttribute(String name)

package com.lagou.servletContext;

import javax.servlet.ServletContext;
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 OneServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 向servletContext域对象中存入数据
        //  ServletContext servletContext1 = this.getServletContext(); 因为继承了HttpServlet, 所以下面的也可
        ServletContext servletContext = req.getServletContext();

        servletContext.setAttribute("user","jack");     // 如果two比one先执行, 那么two中获取user时结果为null
        System.out.println("OneServlet中存入了数据....");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
package com.lagou.servletContext;

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 TwoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 从servletContext域中取出数据
        String user = (String) req.getServletContext().getAttribute("user");

        System.out.println("TwoServlet中取出的数据为" + user); // 如果two比one先执行, 那么two中获取user时结果为null

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--OneSerlvet-->
    <servlet>
        <servlet-name>OneServlet</servlet-name>
        <servlet-class>com.lagou.servletContext.OneServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>OneServlet</servlet-name>
        <url-pattern>/oneServlet</url-pattern>
    </servlet-mapping>

    <!--TwoSerlvet-->
    <servlet>
        <servlet-name>TwoServlet</servlet-name>
        <servlet-class>com.lagou.servletContext.TwoServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TwoServlet</servlet-name>
        <url-pattern>/twoServlet</url-pattern>
    </servlet-mapping>

生命周期

1. 何时创建?
         项目加载时,创建

2. 何时销毁?
         项目卸载时,销毁

3. 作用范围?
         与项目共存亡(多个servlet都可以操作它)

 

8.3 获取资源在服务器的真实地址

可以实现web项目的移植性...动态获取文件真实路径

package com.lagou.servletContext;

import javax.servlet.ServletContext;
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 RealpathServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 获取lagou.jpg文件的真实路径
        ServletContext servletContext = req.getServletContext();
        // 使用getRealPath方法
        String realPath = servletContext.getRealPath("/img/lagou.jpg");
        System.out.println(realPath);
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--RealpathServlet-->
    <servlet>
        <servlet-name>RealpathServlet</servlet-name>
        <servlet-class>com.lagou.servletContext.RealpathServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RealpathServlet</servlet-name>
        <url-pattern>/realpathServlet</url-pattern>
    </servlet-mapping>

 

8.4 获取全局的配置参数

读取web.xml配置文件中标签信息,实现参数和代码的解耦(多个servlet都可以获取)

<!--全局配置参数:所有的servlet都可以读取...-->
    <context-param>
        <param-name>encode</param-name>
        <param-value>UTF-8</param-value>
    </context-param>
package com.lagou.servletContext;

import javax.servlet.ServletContext;
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 OneServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // servletContext获取到全局配置参数
        String encode = req.getServletContext().getInitParameter("encode");
        System.out.println("获取到的全局配置参数-"+ encode);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
package com.lagou.servletContext;

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 TwoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String encode = req.getServletContext().getInitParameter("encode");
        System.out.println("获取到的全局配置参数-"+ encode);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

 

8.5 获取文件MIME类型

在互联网通信过程中定义的一种文件数据类型格式
格式: 大类型/小类型 例如: text/html image/jpeg

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

  <a href="/servlet_demo/mimeServlet?fileName=a.jpg">获取文件的mime类型</a>

</body>
</html>
package com.lagou.servletContext;

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 MimeServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 获取指定文件的mime类型
        // servlet_demo/mimeServlet?fileName=a.jpg
        // 获取请求参数
        String fileName = req.getParameter("fileName");

        // 获取文件的mime类型
        String mimeType = req.getServletContext().getMimeType(fileName);
        resp.getWriter().write(fileName + "----" + mimeType);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--MimeServlet-->
    <servlet>
        <servlet-name>MimeServlet</servlet-name>
        <servlet-class>com.lagou.servletContext.MimeServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MimeServlet</servlet-name>
        <url-pattern>/mimeServlet</url-pattern>
    </servlet-mapping>

8.6 案例:统计网站的访问次数

需求  显示你是第几位访问此网站..

package com.lagou.servletContext;

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 CountServlet extends HttpServlet {


    @Override
    public void init() throws ServletException {
        // 向servletContext域中存入变量count,并且初始值为0
        // 必须在web.xml中设置启动服务器就自动实例化的 load-on-startup 标签
        this.getServletContext().setAttribute("count",0);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

       //1. 设置响应编码
        resp.setContentType("text/html;charset=utf-8");

       //2. 向页面响应信息
        resp.getWriter().write("<h1>拉勾博客</h1>");

        //3.进行servletContext域中的取值   取  加  存    0
        // 取
        Integer count = (Integer) this.getServletContext().getAttribute("count");
        // 加
        count++;
        resp.getWriter().write("<dev>你是,第"+ count + "位访问此网站的人....</dev>");
        // 存
        this.getServletContext().setAttribute("count",count);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
<!--CountServlet-->
    <servlet>
        <servlet-name>CountServlet</servlet-name>
        <servlet-class>com.lagou.servletContext.CountServlet</servlet-class>
        <load-on-startup>4</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>CountServlet</servlet-name>
        <url-pattern>/countServlet</url-pattern>
    </servlet-mapping>

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

2.3.3 Servlet, 生命周期, 体系结构, xml配置, 请求和响应对象, 转发与重定向, ServletContext共享数据 的相关文章

  • 将 >100K 页面链接在一起而不会受到 SEO 惩罚

    我正在创建一个网站 该网站将审查互联网上数十万个其他网站的隐私政策 它的最初内容是基于我的运行普通爬行 http commoncrawl org 50 亿页网络转储和分析所有隐私政策 https stackoverflow com ques
  • Spring MVC Web 应用程序 - 从属性启用/禁用控制器

    我有一个在 Tomcat 中运行的 Web 应用程序 并使用 Spring MVC 来定义控制器和映射 我有以下课程 Controller api test public class TestController RequestMappin
  • 在 Foundation 中动态设置 Sass 变量

    如何在 Foundation 中动态设置 Sass 变量 根据他们的文档 http foundation zurb com docs components tables html 您可以借助一些 Sass 变量来自定义表格 settings
  • 使用 ruby​​ on Rails 向静态网站添加功能

    我是 ruby on Rails 的新手 我有一个包含很多静态页面的网站 我想向网站添加一些动态页面 我将在 ruby on Rails 中开发这些页面 当用户单击静态页面之一上的按钮之一时 将触发这些页面提供的功能 我想我将把动态页面放在
  • 在 Google Cloud 中设置网站? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我完全迷失在这之中 我习惯于使用带有 cpanel 的简单 Web 主机来制作网站 只需使用 filezilla 登录并上传我的 ht
  • 允许获取请求但仅在我的域中?

    在我的网站上 我可以使用 GET 请求触发某些操作 例如隐藏或删除评论的功能 我不是很担心 但如果有人使用 img src url 设计攻击来删除评论或电子邮件 那会很烦人 有办法防止这种情况吗 我使用 httponlycookies 作为
  • VM1550 installHook.js:1860 在控制台中记录为双行

    我正在使用反应应用程序并构建一个简单的应用程序 当我使用 console log 方法在控制台上记录某些内容时 控制台上会出现第二条日志 它似乎来自第 1860 行的文件名 installHook js 我已经尝试过寻找它 但我没有找到 我
  • 引导程序中导航和巨型屏幕之间的差距

    对于我的一生 我无法确定我的导航和大屏幕之间的空白来自哪里 我已经玩过很多变量 但无法让它消失 我在这里做了一个cssdeckhttp cssdeck com labs u6ws0ozl http cssdeck com labs u6ws
  • 将网页中的表格导入 Excel

    我只有中高级的Excel水平和中级的VBA与Excel背景 我想要做的是从链接中显示的网页导入表格 http www admission unmsm edu pe res20130914 A 011 0 html http www admi
  • 构建网站翻译文件

    我在建立网站时多次遇到这个问题 我将以使用 PHP 和 Laravel 为例进行解释 但这个问题在多个平台中都很常见 这已经在几个问题中得到了解决 post1 https stackoverflow com questions 317854
  • 网页编码,设置矛盾[重复]

    这个问题在这里已经有答案了 如果一个网页有 但http标头有 Content Type text html charset UTF 8 那么假设什么编码呢 在 HTML5 中 优先级定义为 用户浏览器设置 字节顺序标记 HTTP 标头 or
  • 创建默认应用程序时 FirebaseOptions 不能为 null

    我正在尝试在 Flutter 集成电子邮件和基于 google 的登录中尝试一个示例项目 并计划使用 firebase 初始化来执行此操作 同时我已按照教程中提到的所有步骤进行操作 一旦尝试使用 firebase 我就会收到此错误已初始化
  • 电话链接在 iframe 中不起作用,但在 iOS 9 Web 中的 div 中起作用。如何使电话链接在 iOS 9 safari 中正常工作?

    您好 我正在尝试 iOS9 中 iframe 内的电话链接 iOS9 中的 safari 中无法打开手机应用程序 当我在里面尝试相同的链接时 它就在那里工作 我正在尝试下面的锚标记 将此代码放入 div 中时会打开手机应用程序 但同样的代码
  • 使用节点http代理转发http代理

    我正在使用 node http proxy 库来创建转发代理服务器 我最终计划使用一些中间件来动态修改 html 代码 这就是我的代理服务器代码的样子 var httpProxy require http proxy httpProxy c
  • 如何在odoo中重写js函数

    我想加载 shop checkout url 函数是 odoo define change info order website sale change info order function require use strict oe w
  • Django - 缺少 1 个必需的位置参数:'request'

    我收到错误 get indiceComercioVarejista 缺少 1 个必需的位置参数 要求 当尝试访问 get indiceComercioVarejista 方法时 我不知道这是怎么回事 views from django ht
  • 在 Tomcat 上部署 Java Web 项目,无需 WAR 或 EAR

    我有一个 Java Web 项目 Struts Spring 在我的本地主机上完美运行 我必须将其部署在我的网站上 但虚拟主机提供的 Tomcat Manager 界面显示 由于安全原因 它无法上传 WAR 文件 当联系技术支持时 我被告知
  • Java selenium - 如何在 TimeoutException 之后正确刷新网页?

    ChromeOptions options new ChromeOptions options addExtensions new File extension 6 2 5 0 crx ZenMate options addExtensio
  • php 中的 stackoverflow 上有这样的成就系统吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 从概念上讲 如何使用 PHP 和 MySQL 为网站编写一个成就系统 唯一真正的方法是不断执行 MySQL 查询来测试成绩等吗 您有两
  • 诸如用于测试 HTTP 请求的虚拟 REST 服务器之类的东西? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我一直在四处寻找 但找不到任何这样的网站 我想知道是否有一些虚拟服务器可以响应测试 GET 请求并返回

随机推荐

  • 框架的注解

    文章目录 一 mybatis 1 MyBatis的常用注解 2 MyBatis的注解实现复杂映射开发 二 Spring 1 Spring原始注解 2 Spring新注解 3 注解配置 AOP 详解 三 springMVC 1 Request
  • 爬山算法启发

    爬山算法 是一种局部择优的方法 采用启发式方法 是对深度优先探索的一种改进 它利用反馈信息帮助生成解的决策 属于人工智能算法的一种 相关术词解释 1 启发式方法 简化虚拟机和简化行为判断引擎的结合 简单讲就是提前对某项行为进行检测和判断 拥
  • win10系统安装Nginx

    Nginx是一款自由的 开源的 高性能的HTTP服务器和反向代理服务器 同时也提供了IMAP POP3 SMTP服务 Nginx可以进行反向代理 负载均衡 HTTP服务器 动静分离 正向代理等操作 因为最近在公司使用到了Nginx 第一步
  • nginx目录结构和配置文件详解

    nginx目录结构和配置文件详解 0x00 Nginx 目录结构 Nginx 文件结构比较简洁 主要包括配置文件和二进制可执行程序 通过安装包形式安装的 nginx 文件结构跟各 Linux 发行版目录规则存放配置文件和二进制文件的位置 目
  • 3 Minute Thesis (3MT)

    1 定义 资料来源 https zhuanlan zhihu com p 63325983 utm id 0 3MT原则 要把博士课题介绍给一个受过高等教育但没有专业背景的人并阐述它的重要性 定义 三分钟论文 3MT 是一个学术比赛 帮助当
  • k8s问题 CrashLoopBackOff

    我们创建资源发现资源出现CrashLoopBackOff解决 CrashLoopBackOff 告诉我们 Kubernetes 正在尽力启动这个 Pod 但是一个或多个容器已经挂了 或者正被删除 root localhost kubectl
  • R语言09-单变量绘图(频数分布直方图/折线图)

    使用ggplot绘图系统 运用qplot ggplot两种方式进行单变量绘图示例 直方图 qplot 系统默认柱状图 library ggplot2 qplot x dob day data users 传入参数x和数据集 ggplot 与
  • MIPI CSI-2学习

    CSI Camera Serial Interface 定义了摄像头外设与主机控制器之间的接口 旨在确定摄像头与主机控制器在移动应用中的标准 关键词描述 缩写 解释 CCI Camera Control Interface 物理层组件 通常
  • 1-Axure

    Axure学习 一 原型图 1 原型图作用 描述互联网产品设计的文档 项目中 与相关部门沟通需求的工具 研发 设计 敏捷开发中 简化版的需求文档 PRD MRD 2 原型图种类 线框图 制作快速 低成本描述方案 给设计更多空间 高保真原型图
  • 2.4.2QT之comboBox下拉框

    2 4 2QT之comboBox下拉框 文章目录 2 4 2QT之comboBox下拉框 前言 2 4 2 1 QComboBo 常用的成员函数 2 4 2 2QComboBox 常用的槽函数 2 4 2 3QComboBox 常用的信号
  • 批量上传文件到服务器中,如何批量上传文件到云服务器

    如何批量上传文件到云服务器 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 将文件上传至Linux服务器一般会采用WinS
  • JAVA: quakus程序运行

    mvnw compile quarkus dev
  • Select type&partitions (2)—mysql执行计划(四十八)

    前面说了explain的table是表名 显示在前面的代表驱动表 正常select会出现不同的id 但如果子查询本来是两个select 但被优化成连接查询 就会导致是相同的id union查询会出现临时表 id为null 这个临时表作用于去
  • 连杆坐标系的规定

    z0是沿着关节轴1的方向 一般l0的坐标轴与l1的坐标轴相同 故 两个关节轴间的距离为0 角度为0 即初始 a 和 为0 建立连杆坐标系的步骤 1 找出各关节轴 并标出 或画出 这些轴线的延长线 在下面的步骤2至步骤5中 仅考虑两个相邻的轴
  • 【uni-app报错】选择地址:fail the api need to be declared in the requiredPrivateInfos field in app/ext.json

    uni app报错 errMsg chooseAddress fail the api need to be declared in the requiredPrivateInfos field in app json ext json 笔
  • 多个C语言代码文件编译示例

    多个C语言代码文件编译示例 多个C语言文件的编译在实际项目中会遇到 是模块化编程的重要体现 是必须要学习的 我们先学习一个简单的例子 我们要实现一个加法和减法操作 将加法和减法看成两个独立的功能 头文件和源文件是分离的 方便给其他开发人员使
  • jquery-ui sortable详解

    该插件的用途 使用鼠标重新排列列表或网格中的元素 helper 这个小伙子 总结的不错 Note In order to sort table rows the tbody must be made sortable not the tab
  • Log4j2自定义插件实现自定义日志打印功能(脱敏/加密)

    文章目录 1 自定义appender插件 2 log4j2 xml配置 3 参数说明 1 定义标签 Plugin 2 定义标签参数或子元素 PluginFactory 4 获取容器中对象 5 Mybatis 设置日志打印实现为Log4j2I
  • RuoYi-spring-boot修改项目名称

    前言 若依是个不错的框架 想用若依框架来做项目 需要修改下项目名称为自定义的名称 比如school 1 找到硬盘对应的位置把名称改成我自定义的名称school 同时把路径也换成school 2 修改所有pom xml文件 1 总pom xm
  • 2.3.3 Servlet, 生命周期, 体系结构, xml配置, 请求和响应对象, 转发与重定向, ServletContext共享数据

    目录 一 Servlet概述 二 Servlet快速入门 2 1 案例需求 编写一个普通的java类 通过浏览器可以访问 2 2 servlet执行原理 三 Servlet生命周期 3 1 生命周期相关 3 1 1 思想介绍 3 1 2 代