Servlet 之超详解【2023年最新版】(二)

简介: Servlet 之超详解【2023年最新版】(二)

5.2 ServletContext接口

注意:

  • 一个web项目只有一个ServletContext对象,代表当前Web应用
  • 所有的Servlet共享同一个ServletContext对象,所以ServletContext对象也被称为 application 对象(Web应用程序对象)
  • ServletContext对象是由服务器启动的时候,Tomcat去创建,在项目卸载时(服务器关机时)销毁。

如何获得到ServletContext对象?

  1. 通过ServletConfig去获得
//使用servletConfig获取全局上下文ServletContext对象
ServletContext servletContext = servletConfig.getServletContext();
System.out.println("servletContext:"+servletContext);
  1. 通过request去获得
//使用servletRequest获取servletcontext对象(全局上下文对象)
ServletContext servletContext = servletRequest.getServletContext();
System.out.println("servletContext:"+servletContext);

主要功能:

  • 获取项目的上下文路径(带"/"的项目名)
//1.获取项目的上下文路径(带/的项目名)
String contextPath = servletContext.getContextPath();
System.out.println("contextPath:"+contextPath);
  • 获取虚拟路径所映射的本地真实路径
    用途:上传或下载文件时需要使用
//2.获取虚拟路径所映射的本地真实路径(根据相对路径获得绝对路径)
String realPath = servletContext.getRealPath("/upload");
System.out.println("realPath:"+realPath);
  • 获取WEB应用程序的全局初始化参数

获取全局初始化参数的前提是你得有全局初始化参数,没有的话就得设置

  • 如何设置全局初始化参数?
    位置:web.xml 的根节点上

    web.xml上的相应代码如下所示:
<context-param>
    <param-name>context-key</param-name>
    <param-value>context-value</param-value>
</context-param>
 <context-param>
     <param-name>ccc</param-name>
     <param-value>ddd</param-value>
 </context-param>
//3.获取WEB应用程序的全局初始化参数
//获取全局初始化参数中<param-name>【 key】为ccc的value值
String ccc = servletContext.getInitParameter("ccc");
System.out.println("ccc="+ccc);
//获取全局初始化参数中<param-name>【 context-key】为ccc的value值
String context_key = servletContext.getInitParameter("context-key");
System.out.println("context_key="+context_key);
//获取全局初始化参数中所有的<param-name>【 key】值
Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
while (initParameterNames.hasMoreElements()){
    System.out.println("nextElement:"+initParameterNames.nextElement());
}
  • 作为域对象共享数据 ★
    域对象:在一定的作用域范围内共享数据的对象

ServletContext所用域范围是整个web项目

  • 测试:
    1.在一个Servlet内,往ServletContext对象中设置共享数据
    2.在另外一个Servlet内获取到共享的数据
    方法:
servletcontext.setAttribute(string key,object obj);
object msg servletcontext.getAttribute(string key);
//移除指定的共享数据(指定key,删除对应的value)
servletcontext.removeAttribute(Sstring key);

案例:尝试使用SecondServlet删除myFirstServlet新建的共享数据test,test的value值自定义

  • 代码演示如下:
//MyFirstServle新增共享数据test并显示
import javax.servlet.*;
import java.io.IOException;
public class MyFirstServlet extends GenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("触发了继承GenericServlet类的子类MyFirstServlet类的service方法......");
        //如何在servletContext作用域范围内添加共享数据
        ServletContext servletContext = servletRequest.getServletContext();
        servletContext.setAttribute("msg","这是MyFirstServlet设置的共享数据");
        //MyFirstServle新增共享数据test并显示
        servletContext.setAttribute("test","这是MyFirstServlet设置的test共享数据");
        System.out.println("test="+servletContext.getAttribute("test"));
    }
}
//SecondServlet尝试删除并显示MyFirstServlet设置的共享数据test
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 SecondServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("访问了SecondServlet里的doPost方法");
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("访问了SecondServlet里的doGet方法");
        //如何获取MyFirstServlet在servletContext作用域范围内设置的共享数据
        ServletContext servletContext = request.getServletContext();
        Object msg = servletContext.getAttribute("msg");
        System.out.println("msg="+msg);
        //删除MyFirstServlet设置的共享数据test
        servletContext.removeAttribute("test");
        System.out.println("SecondServlet已经删除了共享数据test");
        System.out.println("共享数据test="+servletContext.getAttribute("test"));
    }
}



六. 处理请求和响应的接口

6.1 HttpservletRequest接口

简介:

该接口是ServletRequest接口的子接口,封装了HTTP请求的相关信息(请求报文中的所有信息都被封装在里面)

主要功能:

  1. 获得请求头信息
request.getHeader(String key);
//获取请求头中客户端的产品信息
String header = request.getHeader("User-Agent");
System.out.println("客户端的产品信息如下");
System.out.println("header:"+header);
//获取请求头中请求来源
String referer = request.getHeader("Referer");
System.out.println("请求来源如下");
System.out.println("referer:"+referer);
  1. 获得url的路径信息
request.getContextPath()//获取上下文路径
request.getServerName()  //获取主机名
request.getServerPort()  //获取端口号
//获取url
String contextPath = request.getContextPath();//获取上下文路径
System.out.println("contextPath:"+contextPath);
//获取主机名
String serverName = request.getServerName();
System.out.println("serverName:"+serverName);
//获取端口号
int serverPort = request.getServerPort();
System.out.println("serverPort:"+serverPort);
  1. 获得请求参数
    请求参数是什么?
    请求参数就是浏览器向服务器提交的数据。
    浏览器向服务器如何发送数据?
    ① 附在url后面(和get请求一致,拼接的形式就行请求数据的绑定),如下下所示:
http://localhost:8989/MyServlet/MyHttpServlet?userId=20&username=jack
  1. ② 通过表单提交
<form action="MyHttpServlet" method="post">
      你喜欢的足球队<br /><br />
      巴西<input type="checkbox" name="soccerTeam" value="Brazil" />
      德国<input type="checkbox" name="soccerTeam" value="German" />
      荷兰<input type="checkbox" name="soccerTeam" value="Holland" />
      <input type="submit" value="提交" />
    </form>
  1. 使用HttpServletRequest对象获取请求参数
string request.getparameter(string key);
string[] request.getparametervalues("hobby");
//获取请求参数
//根据表单的name值获取它的value值
String username = request.getParameter("username");//获取表单中name为username的value值,下同
System.out.println("username="+username);
String password = request.getParameter("password");
System.out.println("password="+password);
String gender = request.getParameter("gender");
System.out.println("gender="+gender);
//如何根据一个name获取有多个并存的value值
String[] hobbies = request.getParameterValues("hobby");
System.out.println("hobbies:");
for (String hobby : hobbies) {
    System.out.println(hobby);
}
  1. 获取请求方式
request.getMethod()
//获取请求方式
String method = request.getMethod();
System.out.println("请求方式:");
System.out.println("method:"+method);
  1. 转发并共享数据

转发是进行页面跳转的主要手段之一

  1. 什么是转发?如下图所示

    应用场景如下:
    a. 转发到第二个servlet
//HttpServletRequest对象reg转发客户端请求至register_error的servlet中
req.getRequestDispatcher("register_error").forward(req,resp);
  1. b. 转发到一个网页
//HttpServletRequest对象reg转发客户端请求至网页register_error中
req.getRequestDispatcher("regist_error.html").forward(req,resp);
  1. 使用步骤:
    a.获得转发器对象
RequestDispatcher requestDispatcher=request.getRequestDispatcher(目标路径);
  1. b.进行转发操作(将request和response需要传递过去)
requestDispatcher.forward(request,response);
  1. 进行页面跳转的代码:
//跳转至root.html
request.getRequestDispatcher("root.html").forward(request,response);
  1. Secondservlet能否获得到请求中的请求参数?

可以的,因为转发将request对象传递过去了

  1. request可以作为域对象共享数据(请求域)
    应用域(ServletContext):数据共享范围是整个web应用
    请求域(HttpServletRequest):数据共享的范围是本次请求,当响应结束了,请求也结束
//添加共享数据
setAttribute(string key,object value);
//获取共享数据
getAttribute(string key)
//移除共享数据
removeAttribute(string kev)

6.2 HttpservletResponse接口

简介:

  • 该接口是ServletResponse接口的子接口,封装了服务器针对于HTTP响应的相关信息。(暂时只有服务器的配置信息,没有具体的和响应体相关的内容)
  • 由Servlet容器创建其实现类对象,并传入service(HttpServletRequest req, HttpServletResponse res)方法中。
  • HttpServletResponse对象指的是容器提供的HttpServletResponse实现类对象。

主要功能:

a.通过输出流将响应数据输出给客户端

Printwriter writer=response.getwriter();
writer.write("<h1>success</h1>");

b.可以设置响应的乱码(添加响应头的方式)

response.addHeader("Content-Type","text/html;charset=utf-8");
简写:response.setContentType("text/html;charset=utf-8");

c.重定向

页面跳转的主要手段之一

什么是重定向?如下图所示:

应用场景如下:

①重定向至另一个Servlet

response.sendRedirect("second");

②重定向至页面

response.sendRedirect("admin.html");

当发送到firstservlet请求中的请求参数,Secondservlet是否能获取到?

取不到;因为发送了第二次请求(第一次请求中的请求参数和第二次请求毫无关系)

重定向能否使用请求域共享数据?

不可以

转发和重定向的区别

转发 重定向
浏览器的感知 感知不到 感知到
网址栏里的网址 不变 会改变
请求的次数 一次请求 两次请求
请求域中的共享数据 可以访问 不可以访问
发起者 request response
WEB-INF 可以访问 不可以访问
目标资源 本服务器的资源 其他服务器的资源

ps:

WEB-INF下的资源有一个特性:客户端是访问不到的,但是服务器可以访问,可以把不想让客户端直接访问的资源,放在WEB-INF下


七. 请求和响应乱码的处理

7.1 请求乱码

get请求tomcat8已经处理好了

注意:

若你的Tomcat版本为7及以下,就需要修改tomcat的配置文件。在server.xml文件修改Connector标签,添加URIEncoding="utf-8"属性,如下图所示:

post请求中文乱码问题

解决方案:

在代码中获取请求参数之前,设置字符集

代码如下:

request.setcharacterEncoding("utf-8");

案例:form表单以post方式向FirstServlet提交数据,演示post乱码问题

代码演示如下:

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 FirstServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //请求
        //post方法的中文乱码问题
//        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        System.out.println("username="+username);
        String password = request.getParameter("password");
        System.out.println("password="+password);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("触发了FirstServlet的doGet方法.......");
       /* //设置请求域的共享数据
        //注意,设置的共享数据需要放在使用请求转发的代码之前,不然另一个servlet无法获取之前设的请求域共享数据
        request.setAttribute("requestMsg","这是requestMsg共享的数据");
        request.setAttribute("msg","这是msg");
        //实现转发跳转至secondservlet
//        request.getRequestDispatcher("second").forward(request,response);
        //实现重定向至secondservlet
        response.sendRedirect("second");
*/
    }
}

添加字符集后修改如下:

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 FirstServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //请求
        //post方法的中文乱码问题
        request.setCharacterEncoding("utf-8");
        String username = request.getParameter("username");
        System.out.println("username="+username);
        String password = request.getParameter("password");
        System.out.println("password="+password);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("触发了FirstServlet的doGet方法.......");
       /* //设置请求域的共享数据
        //注意,设置的共享数据需要放在使用请求转发的代码之前,不然另一个servlet无法获取之前设的请求域共享数据
        request.setAttribute("requestMsg","这是requestMsg共享的数据");
        request.setAttribute("msg","这是msg");
        //实现转发跳转至secondservlet
//        request.getRequestDispatcher("second").forward(request,response);
        //实现重定向至secondservlet
        response.sendRedirect("second");
*/
    }
}

相关文章
|
9月前
|
Java 关系型数据库 MySQL
Servlet 之超详解【2023年最新版】(三)
Servlet 之超详解【2023年最新版】(三)
|
9月前
|
Java 应用服务中间件 容器
Servlet 之超详解【2023年最新版】(一)
Servlet 之超详解【2023年最新版】(一)
|
存储 移动开发 安全
开心档开发入门网之C++ Web 编程
开心档开发入门网之C++ Web 编程
|
缓存 JavaScript 前端开发
webpack深入浅出(四)| 小册免费学
随着时间和业务量的累积,代码变得越来越臃肿,打包时间变得越来越长,这无疑是一件很头疼的事情(虽然现在大部分都是CI/CD构建),缩小搜索范围也可以减少构建时间
60 0
|
前端开发 JavaScript
webpack深入浅出(一)| 小册免费学
随着前端应用的日益复杂,通过直接编写 JavaScript、CSS、HTML 开发 Web 应用的方式已经无法应对当前 Web 应用的发展,前端工程化越来越受到了重视,许多前端构建工具脱颖而出,webpack就是目前最为流行的打包构建工具,因此每位前端er都需要掌握webpack技术。
47 0
|
JSON 前端开发 JavaScript
webpack深入浅出(二)| 小册免费学
这一节内容主要介绍详细的webpack配置信息,毕竟“webpack高级配置工程师”是每个前端er的目标
67 0
|
JSON 前端开发 JavaScript
webpack深入浅出(三)| 小册免费学
之前我们了解了webpack中的配置方式,下面我们来说一下实际生产中经常使用的loader以及plugin 以下说到的所有依赖都将省略安装过程,除非特别指明,否则都是直接npm安装依赖名
47 0
|
SQL 缓存 NoSQL
SpringBoot2.6 安全机制与实战开发(二)|学习笔记
快速学习 SpringBoot2.6 安全机制与实战开发(二)
76 0
|
安全 前端开发 Java
SpringBoot2.6 安全机制与实战开发(一)|学习笔记
快速学习 SpringBoot2.6 安全机制与实战开发(一)
245 0
SpringBoot2.6 安全机制与实战开发(一)|学习笔记
|
监控 NoSQL druid
2021最新版 SpringBoot 速记教程
2021最新版 SpringBoot 速记教程
171 0
2021最新版 SpringBoot 速记教程