JavaWeb:Servlet、ServletContext、HttpServletResponse、HttpServletRequest 的详细内容

JavaWeb - 02

一、Servlet

1. 简介

Servlet 是 Sun 公司开发动态 Web 的一门技术,在这些 API 中提供了一个接口就是:Servlet,开发一个 Servlet 程序需要两个步骤

  • 编写一个类,实现 Servlet 接口;
  • 把开发好的 java 类部署到 Web 服务器中。

把实现了 Servlet 接口的 Java 程序叫做 Servlet

2. HelloServlet

  • 创建一个普通的 Maven 项目,注意在 Settings 中修改 Maven 地址,并删除 src 文件夹。

  • 在 pom 文件中导入用到的 jar 包
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.1</version>
</dependency>

注意:在 Maven 仓库中下载,groupId路径artifactIdjar 包名version版本

  • 建立 Module 模块(子项目)

注意:父项目中的 jar 包,子项目可以直接使用。

  • Maven 环境优化(2 步)

第一步:修改子项目中 webapp.WEB-INF 中的 web.xml 配置文件(可以用 apache-tomcat-8.5.85\webapps\ROOT\WEB-INF 中的 web.xml 配置文件替换),修改原因:因为是直接用 Maven 模板,版本太低,用新版本

<?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_3_1.xsd"
         version="3.1"
         metadata-complete="true">
</web-app>

第二步:将 Maven 的结构搭建完整:在子项目的 main 中建立 java 以及 resources 文件夹,并标记功能

  • 编写一个 Servlet 程序(3 步)

第一步:刷新子项目的 pom.xml 文件,可以创建一个新的 Servlet,并重写 doPost 和 doGet 方法。

public class HelloServlet extends HttpServlet {

    // 由于 get 或者 post 都是请求实现的不同方式,可以相互调用,业务逻辑都一样
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter writer = response.getWriter();  // 响应流
        writer.println("Hello, Servlet!");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

}

注意:由于 get 或者 post 都是请求实现的不同方式,可以相互调用,业务逻辑都一样。

第二步:在 web.xml 中编写 Servlet 的映射,因为我们写的是 Java 程序,但是要通过浏览器访问,而浏览器需要连接 Web 服务器,所以我们需要在 Web 服务器中注册我们写的 Servlet,给一个浏览器能够访问的路径。

<!-- 注册 Servlet -->
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.Sun3285.servlet.HelloServlet</servlet-class>
</servlet>

<!-- Servlet 的请求路径 -->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

注意

  • servlet-name 可以随便起,但上下要一致
  • servlet-class 是在 Web 服务器中注册我们写的 Servlet(Web 服务器 – Java 程序);
  • url-pattern 是 Servlet 的请求路径,浏览器连接 Web 服务器(Web 服务器 – 浏览器)。

第三步:配置 Tomcat:注意配置项目发布的路径。

  • 启动测试

注意:请求 s1 进入主页 index.jsp,再请求 /hello 进入 web.xml 中找 url-pattern > servlet-name > servlet-class,然后进入自己编写的 Java 程序 HelloServlet.java

3. Servlet 原理

Servlet 原理(Web 服务器 – Java 程序实现的过程)

Web 服务器在收到浏览器请求之后,会进行如图所示过程。

注意:自己的实现类重写方法作用

  • 接受并处理请求
  • 给出响应的信息。

4. Mapping 原理

  1. 一个 Servlet 的请求可以指定一个或多个映射路径
<!-- 映射路径 hello1 和 hello2 都对应同一个 Servlet 的请求 -->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello1</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>
  1. 一个 Servlet 的请求可以指定通用映射路径
<!-- 用通配符 * -->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello/*</url-pattern>
</servlet-mapping>

注意:指定了固有的映射路径优先级最高,如果找不到就会走通用的映射路径。

  1. 可以自定义后缀实现请求映射。
<!-- 用通配符 * -->
<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>*.Sun3285</url-pattern>
</servlet-mapping>

注意:此时在 mapping 中 * 前面不能加项目映射的路径 /,如:/hello/*.Sun3285,而 /hello.Sun3285正确的


二、ServletContext

Web 在启动时,会为每个 Web 程序都创建一个对应的 ServletContext 对象,代表了当前的 Web 应用

注意:每个 Web 工程只有一个 ServletContext 对象,可以有多个 Servlet。

1. 共享数据

在 Servlet 中保存的数据,可以在另外一个 Servlet 中拿到。

方法名说明
void setAttribute(String var1, Object var2)键值对的形式保存数据
Object getAttribute(String var1)根据键获取数据
  • 放置数据的类
ServletContext context = this.getServletContext();

String name = "Sun3285";  // 数据
context.setAttribute("username", name);  // 将数据保存在 ServletContext 中
  • 读取数据的类
ServletContext context = this.getServletContext();
String name = (String) context.getAttribute("username");

response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
response.getWriter().println("用户名为:" + name);

注意:放置数据和读取数据中得到的 ServletContext 对象为同一个

  • 映射
<servlet>
    <servlet-name>setu</servlet-name>
    <servlet-class>com.Sun3285.servlet.OneServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>setu</servlet-name>
    <url-pattern>/setu</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>getu</servlet-name>
    <servlet-class>com.Sun3285.servlet.TwoServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>getu</servlet-name>
    <url-pattern>/getu</url-pattern>
</servlet-mapping>
  • 测试访问结果:先进行 setu,再进行 getu

2. 获取初始化参数

方法名说明
String getInitParameter(String var1)获取初始化参数

注意:方法由 ServletContext 对象调用。

3. 请求转发

方法名说明
RequestDispatcher getRequestDispatcher(String var1)请求转发,参数为转发的请求路径,如 /hello

例如

// 请求转发
RequestDispatcher requestDispatcher = context.getRequestDispatcher("/hello");
requestDispatcher.forward(request, response);  // 调用 forward 实现请求转发,最后结果为获取了 /hello 路径的内容

注意请求转发重定向区别。

  • 相同点:页面都会实现跳转。
  • 不同点请求转发时,URL 不会产生变化,状态码为 307;重定向时,URL 会发生改变,状态码为 302。

4. 读取资源文件

方法名说明
InputStream getResourceAsStream(String var1)产生一个资源流
  • 先准备一个 Properties 类型的文件
username = Sun3285
password = 123456

注意

  • Properties 文件最好放在 resources 目录下,最后生成在 target 文件的 classes 文件下;
  • main 文件下的 javaresources 运行后都被打包到了同一路径下,即 classes ,俗称类路径 classpath
  • 读取资源文件
ServletContext context = this.getServletContext();

InputStream is = context.getResourceAsStream("/WEB-INF/classes/aa.properties");

Properties prop = new Properties();
// 把要读取的属性文件以流的形式加载进去
prop.load(is);
String username = prop.getProperty("username");  // 获取属性
String password = prop.getProperty("password");

response.getWriter().println(username + " : " + password);

注意:读取资源文件需要一个文件流,用 ServletContext 对象来产生,其中路径是相对路径,从当前 Web 应用开始。


三、HttpServletResponse

Web 服务器接收到客户端的 Http 请求,针对这个请求,会分别创建一个代表客户端请求的 HttpServletRequest 对象和一个代表响应的 HttpServletResponse 对象。

  • HttpServletRequest :获取客户端请求过来的参数;
  • HttpServletResponse :给客户端响应的一些信息。

1. 方法介绍

HttpServletResponse 继承了 ServletResponse。

  • 负责向浏览器发送数据的方法
ServletOutputStream getOutputStream() throws IOException;
PrintWriter getWriter() throws IOException;
  • 负责向浏览器发送响应头的方法
void setCharacterEncoding(String var1);
void setContentLength(int var1);
void setContentLengthLong(long var1);
void setContentType(String var1);
void setDateHeader(String var1, long var2);
void addDateHeader(String var1, long var2);
void setHeader(String var1, String var2);
void addHeader(String var1, String var2);
void setIntHeader(String var1, int var2);
void addIntHeader(String var1, int var2);
  • 设置响应的状态码
int SC_OK = 200;
int SC_NOT_FOUND = 404;
int SC_INTERNAL_SERVER_ERROR = 500;
int SC_BAD_GATEWAY = 502;
void setStatus(int var1);

HttpServletResponse 对象除了可以向浏览器输出消息外,还可以下载文件创建验证码以及重定向

2. 应用:下载文件

下载文件的步骤

  • 获取下载文件的路径和文件名;
  • 设置让浏览器能够支持下载;
  • 获取下载文件的输入流,创建缓冲区,文件拷贝。
// - 获取下载文件的路径和文件名
String realPath = "F:\\studying\\javastudy\\javaweb\\javaweb-03-servlet\\response\\src\\main\\resources\\涛涛.txt";
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);

System.out.println("下载文件的路径为:" + realPath);
System.out.println("下载文件的名称为:" + fileName);

// - 设置让浏览器能够支持下载
response.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
// response.setCharacterEncoding("utf-8");
// response.setContentType("text/html");

// - 获取下载文件的输入流,创建缓冲区,文件拷贝
InputStream is = new FileInputStream(realPath);
OutputStream os = response.getOutputStream();

InputStream bis = new BufferedInputStream(is);
OutputStream bos = new BufferedOutputStream(os);

byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
    bos.write(buffer, 0, len);
    bos.flush();
}

bos.close();
bis.close();

注意

  • realPath.substring(realPath.lastIndexOf("\\") + 1);获取文件名的常用方法;
  • response.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));设置浏览器能够支持下载,后面的 URLEncoder.encode(fileName, "utf-8") 可以使下载的文件名为 UTF-8 格式不乱码,如果没有这行代码,浏览器会直接显示文件内容,而不会下载;
  • 文件拷贝用字节缓冲输入流 + 字节缓冲输出流 + 以字节数组读取的组合;
  • 这里的输出流是 response 得到的输出流。

3. 应用:创建验证码

创建验证码步骤

  • 在内存中创建一个图片;
  • 告诉浏览器,这个请求用图片的方式打开;
  • 把图片写给浏览器。
response.setHeader("refresh", "3");  // 刷新

// 在内存中创建一个图片
BufferedImage image = new BufferedImage(110, 30, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) image.getGraphics();  // 得到图片,g 相当于画笔
g.setColor(Color.green);  // 设置图片的背景颜色
g.fillRect(0, 0, 110, 30);
g.setColor(Color.red);  // 给图片写数字
g.setFont(new Font(null, Font.BOLD, 20));  // 粗体,字号 20
g.drawString(makeNum(),10,20);  // 写入随机数

// 告诉浏览器,这个请求用图片的方式打开
response.setContentType("image/jpg");
response.setHeader("Cache-Control", "no-cache");  // 去除网站的缓存
response.setHeader("Pragma", "no-cache");

// 把图片写给浏览器
ImageIO.write(image, "jpg", response.getOutputStream());

生成 8 位随机数

// 生成 8 位的随机数
public String makeNum() {
    Random r = new Random();
    String num = String.valueOf(r.nextInt(99999999));  // 生成随机数
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < 8-num.length(); i++) {
        sb.append(r.nextInt(9));
    }
    String num1 = sb.toString();  // 补齐 8 位
    return num + num1;
}

4. 应用:重定向

// 重定向
response.sendRedirect("/r/image");

注意:重定向的时候一定要注意路径问题,否则 404。

相当于

response.setHeader("Location", "/r/image");  // 设置跳转地址
response.setStatus(302);  // 设置状态码

5. 总结

response 对象的方法使用

方法说明
response.getWriter()字符的形式向浏览器输出消息
response.getOutputStream()字节的形式向浏览器输出消息
response.setContentType(“text/html”)告诉浏览器用什么方式打开,如文本(text/html)、图片(image/jpg) 等
response.setCharacterEncoding(“utf-8”)设置编码格式
response.setHeader(“Content-Disposition”,“attachment;filename=” + URLEncoder.encode(fileName, “utf-8”))浏览器下载文件
response.setHeader(“refresh”, “x”)浏览器 x 秒刷新一次
response.setHeader(“Cache-Control”, “no-cache”)浏览器去缓存
response.setHeader(“Pragma”, “no-cache”)浏览器去缓存
response.sendRedirect(“跳转地址”)重定向,跳转地址需要从项目名开始
response.setHeader(“Location”, “跳转地址”)设置跳转地址
response.setStatus(302)设置状态码

四、HttpServletRequest

HttpServletRequest 代表客户端的请求,用户通过 Http 协议访问服务器,Http 请求中的所有信息会被封装到 HttpServletRequest 中,通过这个 HttpServletRequest 的方法,获得客户端的所有信息。

1. 获取前端传递的参数

调用方法说明
request.getParameter()获得一个参数的值
request.getParameterValues()获得多个参数的值
  • 删除原来的 index.jsp 文件,重新建立,并写前端内容。

注意${pageContext.request.contextPath}/login 表示 当前路径/login

  • 通过调用方法获取前端传递的参数
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");

String username = request.getParameter("username");
String password = request.getParameter("password");
String[] hobbies = request.getParameterValues("hobbies");
System.out.println("=============================");
System.out.println("username : " + username);
System.out.println("password : " + password);
System.out.println(Arrays.toString(hobbies));
System.out.println("=============================");
  • 效果

2. 请求转发

调用方法说明
request.getRequestDispatcher(“/转发路径”).forward(request, response)请求转发

注意:这里的 / 代表当前的 Web 应用,转发路径中不用再写项目名,因为转发是项目内部资源跳转。而重定向需要写项目名。

  • 建立跳转的页面 success.jsp

  • 请求转发
request.getRequestDispatcher("/success.jsp").forward(request, response);
  • 效果


注意:

  1. this 指当前类的对象

  2. 点击 clean 可以清除生成的 target 文件。

  1. random.nextInt(max) 表示生成 [0,max] 之间的随机数
  2. 请求转发和重定向的地址都是浏览器导航栏的路径
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sun 3285

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值