零、HttpServletRequest

  • 上一篇已经介绍了这个接口,现在补充些内容

    首先介绍一下作用域:
  • jakarta.servlet.jsp.PageContext pageContext 页面作用域
  • jakarta.servlet.http.HttpServletRequest request 请求域
  • jakarta.servlet.http.HttpSession session 会话域
  • jakarta.servlet.ServletContext application 应用域
  • 作用域从小到大 pageContext-> request -> session -> application
  • 声明一下这里的jakarta是Tomcat10的说法,已经被收购了。

如何获取前端传来的数据:

String getParameter(String name) // 获取value中第一个元素(最常用)
Map<String,String[]> getParameterMap() // 获取键值对的整个集合
Enumeration<String> getParameterNames() // 获取所有键key
String[] getParameterValues(java.lang.String name) // 通过key获取值

转发和重定向:

  • 转发

    • //转发都是一次请求
      //因为他们用的都是当前的Servlet
      //转发以后它的地址仍然不变
      //我们每次转发也可以把页面的数据带过去放到作用域里
      request.setAttribute("user",user);
      //这样我们在另外一个页面中,也可以获得这个user对象的信息
      request.getAttribute("user"); request.getRequestDispatcher("/list").forward(request,response); //这里再介绍一个方法
      //这个方法也是转发,只不过是我们转发到list这个页面以后,拿到这个页面的数据,然后再返回到当前页面
      req.getRequestDispatcher("/list").include(req,resp);
  • 重定向

    • 重定向以后地址栏会改变
    • 重定向一次,两次请求
    • 是浏览器完成的
    • //重定向要写绝对路径
      resp.sendRedirect("req.getContextPath() + /list");
  • 选择哪个

    • 如果在上一个Servlet当中向request域当中绑定了数据,希望从下一个Servlet当中把request域里的数据取出来,用转发
    • 其余的都用重定向

一、HttpServletResponse



通过观察HttpServletResponse这个接口,我们可以发现它里面定义了很多状态码。

一般 200 就是 ok了

以 4xx这种 一般都是路径写错了,没有找到资源

以 5xx 这种都是后端代码有问题,或者写错了。

状态 类别 原因
1xx Informational(信息性状态码) 接受的请求正在处理
2xx Success(成功状态码) 请求正常处理完毕
3xx Redirection(重定向) 需要进行附加操作以完成请求
4xx Client error(客户端错误) 客户端请求出错,服务器无法处理请求
5xx Server Error(服务器错误) 服务器处理请求出错

这里演示一个利用ajax从服务器拿到json数据进行解析的小案例:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
//3.响应一段JSON数据
out.println("[{\"name\":\"lx\"},{\"age\":123}]");
<script type="text/javascript">
function onJson() {
//1.发送ajax请求获取JSON数据
var xhr = new XMLHttpRequest();
xhr.open("GET","/outServlet");//绝对路径
xhr.send();
xhr.onload = function () {
//JSON.stringify()是将一个对象格式化成JSON数据
//JSON.parse()是用来解析JSON数据
var arr = JSON.parse(xhr.responseText);
arr.forEach((k,v) => {
console.log(k,v);
});
//这样我们就能拿到服务器返回的json数据,可以利用ajax进行页面的渲染。
}
}
</script>

二、文件的上传下载

2.1 文件的下载

multipart/form-data 可用于HTML 表单从浏览器发送信息给服务器。作为多部分文档格式,它由边界线(一个由'--'开始的字符串)划分出的不同部分组成。每一部分有自己的实体,以及自己的 HTTP 请求头,Content-Disposition和 Content-Type 用于文件上传领域,最常用的 (Content-Length 因为边界线作为分隔符而被忽略)。

1.首先了解response.setContentType("application/force-download");这个方法是强制下载。当我们的浏览器一旦接收到这个请求就会问我们是否进行文件的下载。

2.我们可以通过response.setHeader("Content-Length","文件大小");的方法来设置我们的文件下载大小。

3.根据规范,我们进行设置response.setHeader("Content-Disposition","attachment;filename=test.txt");

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//响应文件
String str = "我靠怎么回事I'm lx,Hello!~~哈哈哈";
//设置强制提示下载
response.setContentType("application/force-download");
//设置文件的大小
response.setHeader("Content-Length","" + str.length());
//根据multipart/form-data规范
response.setHeader("Content-Disposition","attachment;filename=test.txt");
ServletOutputStream out = response.getOutputStream();
//getBytes()默认使用utf-8
//我们这里的getBytes方法已经默认使用了utf-8编码格式,大家可以去看一下源码
out.write(str.getBytes());
}

2.2 文件的上传

<form action="http://localhost:8000/" method="post" enctype="multipart/form-data">
<!-- 这个enctype="multipart/form-data" 一定要设置!-->
<!--与此同时我们也一定要在web.xml中的<Servlet>中配置<multipart-config>来告诉它
因为Servlet是一种懒加载机制,非常的懒,如果我们不去配置,它是不会自己拥有这个功能的,也是为了节省资源吧
-->
<input type="text" name="myTextField">
<input type="checkbox" name="myCheckBox">Check</input>
<input type="file" name="myFile">
<button>Send the file</button>
</form>
POST / HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=---------------------------8721656041911415653955004498
Content-Length: 465
//这个请求头也声明了使用boundary边界:-- + 字符串的形式,同时也声明了文件的大小,下面是请求体的内容 -----------------------------8721656041911415653955004498
Content-Disposition: form-data; name="myTextField"
//你会发现这是四个边界,分成了三个模块
//三个模块当中介绍了三部分信息,分别对应着我们的form表单
//myTextField信息 Test
-----------------------------8721656041911415653955004498
Content-Disposition: form-data; name="myCheckBox"
//myCheckBox的信息 on
-----------------------------8721656041911415653955004498
Content-Disposition: form-data; name="myFile"; filename="test.txt"
Content-Type: text/plain
//myFile 我们的文件 Simple file.
-----------------------------8721656041911415653955004498--
  • 如果说我们想要实现文件的上传这个功能,那么我们从前端获取到的数据大家也看到了,就是上面这些,很显然我们需要自己去解析:那么解析也有两种办法,一种就是我们自己去造轮子,另一种就是用现成的轮子
  • 为了显示我们的工匠精神,我们必须自己造一个轮子,用原生的Servlet来解析一下
public interface Part {
//我们首先来了解一下Part这个接口
InputStream getInputStream() throws IOException; //获取请求类型
String getContentType(); //获取请求的名字
String getName(); //获取我们提交的文件名字
String getSubmittedFileName(); long getSize(); //将我们的文件信息,写入到我们传进来的路径中的文件里。
void write(String var1) throws IOException; void delete() throws IOException; //获得请求头信息
String getHeader(String var1); //遍历拿到所有请求头的信息
Collection<String> getHeaders(String var1); Collection<String> getHeaderNames();
}

第一种实现方式:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
for(Part part:request.getParts()) {
String name = part.getName();
System.out.println("name = " + name);
String value = request.getParameter(name);
System.out.println(value);
//文件处理
if(part.getContentType() != null) {
String path = "D:/uploads/" + part.getSubmittedFileName();
File file = new File(path);
//如果我们直接使用 file.createNewFile() 那么如果此时父目录不存在,则也会报错。所以我们要通过父目录是否存在进行判断
File parentFile = file.getParentFile();
if(!parentFile.exists()) {
//将所有的父级目录都创建出来
parentFile.mkdirs();
}
//将我们拿到的文件信息,写入到这个路径中的文件里
part.write("path");
}
}
}

第二种实现方式:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String myTextField = request.getParameter("myTextField");
String myCheckBox = request.getParameter("myCheckBox"); //拿到文件信息
Part myFile = request.getPart("myFile");
//拿到我们的文件名称
String fileName = myFile.getSubmittedFileName();
//这里就是为了容错处理。我们将文件以 . 分割成两部分
String[] fs = fileName.split("[.]");
//我们随机生成一串字符
String uuid = UUID.randomUUID().toString();
//我们的文件路径以 父目录/文件名.前缀/当前时间戳/uuid随机字符串/ .后缀构成
String filePath = "D:/uploads/"+ fs[0] + "/" + System.currentTimeMillis() + "/" + uuid + fs[1]; File file = new File(filePath);
//如果我们直接使用 file.createNewFile() 那么如果此时父目录不存在,则也会报错。所以我们要通过父目录是否存在进行判断
File parentFile = file.getParentFile();
if(!parentFile.exists()) {
//将所有的父级目录都创建出来
parentFile.mkdirs();
}
//将我们拿到的文件信息,写入到这个路径中的文件里
myFile.write("path");
}

三、Servlet注解开发

  • 谈到注解,如果做过项目必然不会陌生,因为我们基本上都是注解式开发了,为了使代码更加简洁高效,减少配置文件的内容。
//这是在我们的Servlet中用的注解,就不过多的解释了。
jakarta.servlet.annotation.WebServlet
@WebServlet({"/list" , "/add" , "/detail" , "/del"}) @WebFilter({"/a.do","/b.do"})
public class MyFilter implements Filter {

这里提到一个解决Servlet类爆炸的问题:

  • 如果我们用JavaWeb这块技术做项目,必然会用到很多个Servlet,但是如果我们创建很多个Servlet会使业务看起来很复杂,难以维护。
  • 我们可以用下面的设计模式,这样我们就可以将一个业务放到一个Servlet类中
//模板类
//目录链接
@WebServlet({"/list" , "/add" , "/detail" , "/del"})
public class ServletFinally extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String servletPath = req.getServletPath();
if(servletPath.equals("/list")) {
//根据请求进入相应的方法当中
doList(req,resp);
} else if(servletPath.equals("/add")) {
doAdd(req,resp);
}
}
private void doList(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//然后将我们的业务代码放里面
}
private void doAdd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//然后将我们的业务代码放里面
}
}

四、结尾

  • 对于Tomcat的Servlet内容就总结这么多,若想深入学习等待后续更新。
  • 我将会继续更新关于Java方向的学习知识,感兴趣的小伙伴可以关注一下。
  • 文章写得比较走心,用了很长时间,绝对不是copy过来的!
  • 尊重每一位学习知识的人,同时也尊重每一位分享知识的人。
  • 你的点赞与关注,是我努力前行的无限动力。

Tomcat深入浅出——Servlet(三)的更多相关文章

  1. Tomcat深入浅出——Servlet(二)

    一.Servlet简介 Servlet类最终开发步骤: 第一步:编写一个Servlet类,直接继承HttpServlet 第二步:重写doGet方法或者doPost方法,重写哪个我说的算! 第三步:将 ...

  2. Tomcat剖析(三):连接器(2)

    Tomcat剖析(三):连接器(2) 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器(1) 4 ...

  3. Tomcat剖析(三):连接器(1)

    Tomcat剖析(三):连接器(1) 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器(1) 4 ...

  4. Cookie&Seesion会话 共享数据 工作流程 持久化 Servlet三个作用域 会话机制

    Day37 Cookie&Seesion会话 1.1.1 什么是cookie 当用户通过浏览器访问Web服务器时,服务器会给客户端发送一些信息,这些信息都保存在Cookie中.这样,当该浏览器 ...

  5. 浅谈Tomcat和Servlet

    本文浅谈下对Tomcat和Servlet总体的理解,初学时有用过一段时间,但当时疲于应对如何xml配置和使用,对他们的理解就像是一个黑匣子.现在回顾一下帮助自己加深网络的理解.开始还是先推荐我看的文章 ...

  6. 将Java web应用部署到Tomcat 及部署到Tomcat根目录 的三种方式

    Tomcat作为Servlet/JSP容器(服务器)挺不错的,开源免费,需要知道的是Tomcat是一个Web服务器,其符合Servlet/JSP规范,但是却没有实现所有JavaEE规范,所以我们还是应 ...

  7. tomcat和servlet的关系

    一.什么是servlet? 处理请求和发送响应的过程是由一种叫做Servlet的程序来完成的,并且Servlet是为了解决实现动态页面而衍生的东西.理解这个的前提是了解一些http协议的东西,并且知道 ...

  8. Servlet 三种创建方式

    servlet 是运行在 Web 服务器(tomcat)中的小型 Java 程序(即:服务器端的小应用程序) (其实就是一个java类,只不过不用再new了).servlet 通常通过 HTTP(超文 ...

  9. Tomcat深入浅出(一)

    一.Tomcat简介 我们下载好Tomcat后需要配置一下Java环境:如果打开出现闪退得情况,首先是jdk 同时配置JRE_HOME Tomcat的一些关键目录: /bin:存放用于启动及关闭的文件 ...

随机推荐

  1. 基于全志A40i开发板——Linux-RT内核应用开发教程(1)

    目录 1 Linux-RT内核简介 3 2 Linux系统实时性测试 3 3 rt_gpio_ctrl案例 10 4 rt_input案例 15 本文为Linux-RT内核应用开发教程的第一章节--L ...

  2. JMeter配置Oauth2.0授权接口访问

    本文主要介绍如何使用JMeter配置客户端凭证(client credentials)模式下的请求 OAuth2.0介绍 OAuth 2.0 是一种授权机制,主要用来颁发令牌(token) 客户端凭证 ...

  3. Java指令重排序在多线程环境下的应对策略

    一.序言 指令重排在单线程环境下有利于提高程序的执行效率,不会对程序产生负面影响:在多线程环境下,指令重排会给程序带来意想不到的错误. 本文对多线程指令重排问题进行复原,并针对指令重排给出相应的解决方 ...

  4. Python 工匠:使用数字与字符串的技巧

    序言 这是 "Python 工匠"系列的第 3 篇文章. 数字是几乎所有编程语言里最基本的数据类型,它是我们通过代码连接现实世界的基础.在 Python 里有三种数值类型:整型(i ...

  5. DDT数据驱动性能测试(一)

    DDT数据驱动性能测试(一) 一.csv数据文件设置 1.使用场景:测试过程中需要使用手机号码等大量数据时,用random函数随机生成数字:也可以使用Excel拖动生成一批手机号,也有可以从数据库中导 ...

  6. Qt(QtWebEngine)加载本地网页跨域问题的总结

    目录 1. 概述 2. 详论 2.1. 传参 2.2. JS module 3. 建议 4. 参考 1. 概述 浏览器直接加载本地网页的时候,如果网页涉及到加载本地资源(如图片),会出现跨域的问题.Q ...

  7. Nacos源码系列—服务端那些事儿

    点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 nacos,即可免费获取源码 前言 在上节课中,我们讲解了客户端注册服 ...

  8. Java学习笔记-基础语法Ⅷ-泛型、Map

    泛型 泛型本质上是参数化类型,也就是说所操作的数据类型被指定为一个参数,即将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型,这种参数类型可以用在类.方法和接口中,分别为泛型类.泛型方法 ...

  9. REST APIs

    REST APIs 旨在通过HTTP 的动作语义METHOD, 以替代各种传统CRUD 操作所带来的命名问题,例如 "/userAdd"."/userDelete&quo ...

  10. 设计模式---单例模式,pickle模块

    设计模式---单例模式 简介 单例模式(Singleton Pattern) 是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实 例存在.当你希望在整个系统中,某个类只能出现一个实例时 ...