SERVLETJSP学习(二)—— Servlet工作原理

1. Servlet核心(I)

1.1. 请求方式

1.1.1. 请求方式的种类

请求数据包中的请求行的第一个参数就是请求方式,是客户端向Web服务器发送请求时的意向说明,以此告知服务器该如何处理及解析提交的这些数据,而客户端提交的数据也会因为采用的提交方式不同来处理。后续的一切解析都是基于请求方式的不同而不同。在RFC标准文档中有详细的规定来说明请求方式的种类及作用。

区分请求种类也会为浏览器采用不同的缓存方式处理后续请求提供一个依据,从而提升响应速度。所以对于编程人员来讲,使用正确的请求方式是Web应用的一个重要方面。

根据RFC文档的说明,请求的种类包括如 表 – 1 所示内容。

表 – 1 请求方式的种类

HTTP协议中定义了的这些方法(有时也叫“动作”)用来表示对指定数据的操作。有些方法(比如HEAD, GET, OPTIONS, and TRACE) 被定义为安全方法,这些方法针对的只是信息的返回,并不会改变服务器的状态(换句话说就是这些方法不会产生副作用)。不安全的方法(例如POST, PUT and DELETE) 应该用特殊的方式向用户展示,通常是按钮而不是链接,这样就可以使用户意识到可能要负的责任(例如一个按钮带来的资金交易。)

1.1.2. GET请求方式的特点

使用GET提交数据时,form中的数据将编码到URL中。在使用上,当且仅当请求幂等(字面意思是请求任意次返回同样的结果,本质是请求本身不会改变服务器数据和状态)时使用GET。重复访问时使用GET方法请求的页面,浏览器会使用缓存处理后续请求。当编程人员正确的使用GET后,浏览器会给出很好的缓存配合,响应速度更快。

原则上,服务器端处理GET和POST请求是没有分别的。但由于数据通过不同的方法编码,需要有不同的解码机制。所以,方法变化将导致处理请求的代码变化。比如对于CGI,处理GET时通过环境变量获得参数,处理POST请求时则通过标准输入(stdin) 获得数据。

从使用经验上有如下总结:

  • GET是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。
  • GET传送的数据量较小,不能大于2KB。
  • GET安全性非常低
  • <form method="get" action="xxx?b=b">跟<form method="get" action="xxx">是一样的,也就是说,action页面后边带的参数列表会被忽视;而<form method="post" action="xxx?b=b">跟<form method="post" action="xxx">是不一样的。

如下情况中浏览器会发送GET类型的请求:

  • 在地址栏输入一个地址
  • 点击页面中的链接
  • 表单的默认提交方式

1.1.3. POST请求方式的特点

POST方式提交的数据是在HTTP协议的Hearder中进行传输的。在使用上,当请求会改变服务器数据或状态时(更新数据,上传文件)应该使用POST。使用POST方法的Form提交时,浏览器基于POST将产生永久改变的假设,将让用户进行提交确认。

提交数据时,Form提交的第一步是创建数据集,并根据ENCTYPE对数据集进行编码。ENCTYPE有两个值:multipart/form-data,application/x-www-form-urlencoded(默认值),前者可同时用于GET、POST,后者只用于POST。进行数据传输时,对于GET方法,数据集使用content type application/x-www-form-urlencoded编码并附在URL后面,在这种模式下,数据严格限制为ASCII码;对于POST,使用content-type编码字符集并将其构造成消息发送

服务器端处理数据时,处理POST请求时则通过标准输入(stdin) 获得数据。

从使用经验上有如下总结:

  • POST是将表单内各个字段与其内容放置在实体内容中内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
  • POST传送的数据量较大,一般被默认为不受限制
  • POST安全性较高

将表单的Method属性设置为POST时,浏览器会发送POST请求。

1.2. Servlet如何运行

1.2.1. Servlet运行的步骤

Servlet作为Web服务器的补充功能在运行时需要受到Servlet容器的管理,其运行的流程如下:

  1. 浏览器依据IP建立与容器的连接
  2. 浏览器将请求数据打包
  3. 容器解析请求数据包,封装request和response对象
  4. 容器依据请求资源路径找到Servlet创建对象
  5. 容器将request和response对象作为参数传入service方法,并调用
  6. 容器将响应数据打包发给浏览器
  7. 浏览器取出结果,生成页面

1.3. Servlet如何输出中文

1.3.1. 为什么返回的页面会有乱码

Java语言在内存当中保存的每一个字符使用的都是Unicode字符集。一个中文字在内存中使用2个字节来表示。

编码:将Unicode字符集对应的字节数组转换成某种本地字符集(比如UTF-8,GBK)对应的字节数组的过程叫做编码

解码:将某种本地字符集对应的字节数组转换成Unicode字符集对应的字节数组的过程。

如果想输出就涉及到编码问题。编码和解码使用的字符集不一致就产生了乱码问题。

out.println(“”)这行代码是编码过程。现在这个out要输出的内容使用的是Unicode字符集,于是转换为默认的iso-8859-1。之所以使用这个格式是因为tomcat默认是英文的。所以调用out.println时,容器采用默认情况下的ISO-8859-1字符集去编码带有中文的输出内容时就产生了乱码。

1.3.2. 如何解决输出内容的乱码问题

在service()方法中第一行的位置上添加如下代码:

  1. response.setContentType(“text/html;charset=UTF-8”);

其中charset可以使用其他支持中文的字符集,如GBK。setContentType()有两个作用:

  1. 通知容器,在调用out.println方法输出时,使用指定的字符集
  2. 生成一个消息头(content-type),通知浏览器,服务器返回的数据类型和字符集

使用该段代码修改默认的编码方式时,一定要保证在调用print之前编写,所以该段代码尽量放在service方法的第一行的位置。在charset之前使用的是分号隔开,如果写错,则会出现保存文件的界面,原因是浏览器不能识别消息头的值,于是让用户来处理。

能够输出带有中文内容页面的完整代码如下:

  1. import java.io.IOException;
  2. import java.io.PrintWriter;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. public class HelloServlet extends HttpServlet{
  8. public void service(HttpServletRequest request,
  9. HttpServletResponse response)throws ServletException,
  10. IOException{
  11. response.setContentType("text/html;charset=utf-8");
  12. //获得输出流
  13. PrintWriter out = response.getWriter();
  14. out.println(“达内科技欢迎你”);
  15. //关闭流
  16. out.close();
  17. }
  18. }

1.4. Servlet如何处理表单

1.4.1. 如何获得请求参数值

对于表单提交的数据,Servlet可以从容器构建的request对象中获取,如下两个方法可以在不同情况下获取表单数据:

  • String getParameter(String paramName)
  • String[] getParameterValues(String paramName)

1.4.2. getParameter方法

主要用于获取表单中控件的数据。其中参数名一定要与客户端表单中的控件name属性相一致。所以在构建表单各元素时,name属性一定要有。而name属性和id属性的区别就在于,id属性一般是作为客户端区分控件的标识,name属性是服务器端区分各控件的标识。如果参数名写错,则该方法会返回null。

用于提供用户输入的HTML页面代码如下:

  1. <html>
  2. <head>
  3. </head>
  4. <body>
  5. <form action="hello" method="post">
  6. 用户名:<input name="username"/><br/>
  7. <input type="submit" value="提交"/>
  8. </form>
  9. </body>
  10. </html>

使用该方法获取表单数据的完整代码如下:

  1. package web;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. public class HelloServlet extends HttpServlet{
  9. public void service(HttpServletRequest
  10. request,HttpServletResponse response)
  11. throws ServletException,IOException{
  12. /*
  13. * request.getParameter方法:
  14. *     1.作用:依据请求参数名获取请求参数值。
  15. */
  16. String username = request.getParameter("username");
  17. //处理请求
  18. String msg = "<div style=‘font-size:80px‘>" +
  19. "你好 " + username + "</div>";
  20. response.setContentType("text/html;charset=utf-8");
  21. //获得输出流
  22. PrintWriter out = response.getWriter();
  23. out.println(msg);
  24. //关闭流
  25. out.close();
  26. }
  27. }

1.4.3. getParameterValues方法

用于获取表单中一组参数名相同的控件提交的数据组,如复选框,所以该方法返回的是字符串数组。如果用户没有选择这一组同名控件的任何一个,则该方法返回null。

用于提供用户输入用户名和爱好选项的HTML页面完整代码如下:

  1. <html>
  2. <head>
  3. </head>
  4. <body>
  5. <form action="hello" method="post">
  6. 用户名:<input name="username"/><br/>
  7. 爱好:
  8. 吃饭<input type="checkbox" name="hobby" value="eating" checked="checked"/>
  9. 睡觉<input type="checkbox" name="hobby" value="sleeping"/>
  10. 打豆豆<input type="checkbox" name="hobby" value="fighting"/>
  11. <br/>
  12. <input type="submit" value="提交"/>
  13. </form>
  14. </body>
  15. </html>

使用该方法获取复选框值的完整代码如下:

  1. import java.io.IOException;
  2. import java.io.PrintWriter;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. public class HelloServlet extends HttpServlet{
  8. public void service(HttpServletRequest
  9. request,HttpServletResponse response)     throws ServletException,IOException{
  10. String username =     request.getParameter("username");
  11. String[] hobby= request.getParameterValues("hobby");
  12. //处理请求
  13. String msg = "<div style=‘font-size:80px‘>" +
  14. "你好 " + username + "</div>";
  15. response.setContentType("text/html;charset=utf-8");
  16. PrintWriter out = response.getWriter();
  17. out.println(msg);
  18. for(int i=0;i<hobby.length;i++){
  19. out.println("<h1>" + hobby[i] +"</h1>");
  20. }
  21. //关闭流
  22. out.close();
  23. }
  24. }

1.4.4. 为什么表单提交中文会出现乱码

当表单提交时,浏览器会对表单中的中文参数值进行编码,而使用的编码是打开页面时所使用的字符集,如当前页面使用的UTF-8的字符集进行显示的,那么表单提交的数据就会以UTF-8的方式进行编码后传输,而Web服务器在默认情况下对提交的表单数据会使用ISO-8859-1的字符集来解码,编码与解码的方式不一致就产生了表单提交时的中文乱码问题。

1.4.5. 如何解决表单提交时的中文乱码问题

步骤一、确保表单所在的页面按照指定的字符集打开

在HTML页面中使用meta标记可以确保浏览器按照指定的字符集进行解码页面,并限定表单提交时的数据编码方式

  1. <meta http-equiv="content-type" content="text/html;charset=utf-8">

在服务器端需要在调用getParameter方法读取参数之前,告诉浏览器如何解码,使用如下代码即可完成该设置:

  1. request.setCharacterEncoding("utf-8");

注意该方法一定要要放在所有request.getParameter方法之前。

这种方式只针对POST请求有效。

1.4.6. 解决GET方式提交时的中文乱码问题

步骤一、确保表单所在的页面按照指定的字符集打开

在HTML页面中使用meta标记可以确保浏览器按照指定的字符集进行解码页面,并限定表单提交时的数据编码方式

  1. <meta http-equiv="content-type" content="text/html;charset=utf-8">

步骤二、完成ISO-8859-1到UTF-8格式的转换

  1. String username = request.getParameter(“username”);
  2. username = new String(username.getBytes(“iso-8859-1”),“UTF-8”);

由于GET方式提交的任何数据在服务器端一定会以ISO-8859-1的方式进行解码,所以服务器端可以先按ISO-8859-1的方式获取字节数组,在将该数组转变成UTF-8对应的字符串形式。

解决表单提交时的中文乱码问题的完整代码如下:

  1. import java.io.IOException;
  2. import java.io.PrintWriter;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. public class HelloServlet extends HttpServlet{
  8. public void service(HttpServletRequest     request,
  9. HttpServletResponse response)throws
  10. ServletException,IOException{
  11. request.setCharacterEncoding("utf-8");
  12. String username =     request.getParameter("username");
  13. username=new String(username.getBytes("iso-8859-1"),"utf-8");
  14. String msg = "<div style=‘font-size:80px‘>" +
  15. "你好 " + username + "</div>";
  16. response.setContentType("text/html;charset=utf-8");
  17. PrintWriter out = response.getWriter();
  18. out.println(msg);
  19. out.close();
  20. }
  21. }

1.5. Servlet如何访问数据库

1.5.1. 使用JDBC技术访问数据库

步骤一、将JDBC驱动(.jar文件)放到WEB-INF\lib下

原因:ClassLoader找到字节码文件,然后加载到JVM的方法区中,变成一个对象。Tomcat都有自己的类加载器,会去WEB-INF下面lib中找字节码文件。毕竟jar包中都是字节码文件。

步骤二、编写JDBC代码,需要注意异常的处理

时间: 2024-08-26 06:06:00

SERVLETJSP学习(二)—— Servlet工作原理的相关文章

走进JavaWeb技术世界4:Servlet 工作原理详解

本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下Star哈 文章首发于我的个人博客: www.how2playlife.com 本文是微信公众号[Java技术江湖]的<走进JavaWeb技术世界>其中一篇,本文部分内容来源于网络,为了把本文主题讲得清晰透彻,也整合了很多我认为不错的技术博客内容,引用其中了一些比较好的博客文章,如有侵权,请联系作

JSP/Servlet 工作原理

JSP/Servlet 工作原理(转载) 2014-03-08 23:20 1829人阅读 评论(0) 收藏 举报 Servlet Servlet 没有 main 方法,不能够独立的运行,它的运行需要容器的支持,Tomcat 是最常用的 JSP/Servlet 容器. Servlet 运行在 Servlet 容器中,并由容器管理从创建到销毁的整个过程. 对于用户到达Servlet的请求,Servlet容器会创建特定于这个请求的ServletRequest对象和 ServletResponse对象

Servlet 工作原理解析

-----转自许令波老师Servlet 工作原理解析  感觉写的很不错,保存下来,留着以后温习 从 Servlet 容器说起 要介绍 Servlet 必须要先把 Servlet 容器说清楚,Servlet 与 Servlet 容器的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力.虽然它们是彼此依存的,但是又相互独立发展,这一切都是为了适应工业化生产的结果.从技术角度来说是为了解耦,通过标准化接口来相互协作.既然接口是连接 Servlet 与 Servlet 容器的关键,那我们就

Servlet工作原理

Servlet生命周期分为三个阶段: 1,初始化阶段  调用init()方法 2,响应客户请求阶段 调用service()方法 3,终止阶段 调用destroy()方法 Servlet初始化阶段: 在下列时刻Servlet容器装载Servlet: 1,Servlet容器启动时自动装载某些Servlet,实现它只需要在web.XML文件中的<Servlet></Servlet>之间添加如下代码: <loadon-startup>1</loadon-startup&g

【Java】Servlet 工作原理解析

Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 Java Web 技术的核心基础.因而掌握 Servlet 的工作原理是成为一名合格的 Java Web 技术开发人员的基本要求.本文将带你认识 Java Web 技术是如何基于 Servlet 工作,你将知道:以 Tomcat 为例了解 Servlet 容器是如何工作的?一个 Web 工程在 Servlet 容器中是如何启动的? Servlet 容器如何解析你在 web.xml 中定义的 Servlet ?用户的请

Servlet工作原理分析

最近在看<Java Web技术内幕>的Servlet工作原理,有点深奥和难以理解,于是乎,想通过一个简单的Demo将书上的思路理一遍,对Servlet有个更透彻更深的了解. Servlet类:HelloWorld.java package com.cqupt; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletReq

Struts2(二):工作原理

struts可查看源码:https://github.com/apache/struts 在学习struts2之前,我先看了一些比较早版本对struts2的工作原理相关的介绍,顺便抄写过来,用来帮助自己要弄清这个框架的工作原理. struts2.1.3之前使用的FilterDispatcher,之后的版本使用StrutsPrepareAndExecuteFilter,而我这里还是以Dispatcher为例来记录的. 依据: Since Struts 2.1.3, use org.apache.s

【Tomcat】Servlet 工作原理解析

Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 Java Web 技术的核心基础.因而掌握 Servlet 的工作原理是成为一名合格的 Java Web 技术开发人员的基本要求.本文将带你认识 Java Web 技术是如何基于 Servlet 工作,你将知道:以 Tomcat 为例了解 Servlet 容器是如何工作的?一个 Web 工程在 Servlet 容器中是如何启动的? Servlet 容器如何解析你在 web.xml 中定义的 Servlet ?用户的请

Java web每天学之Servlet工作原理详情解析

上篇文章中我们介绍了Servlet的实现方式以及Servlet的生命周期,我们这篇文章就来介绍一下常用对象. 点击回顾:<Java Web每天学之Servlet的工作原理解析>:<Java Web每天学之Servlet的工作原理解析(二)> 一.HttpServletRequest对象 1.介绍HttpServletRequest对象:主要作用是用来接收客户端发送过来的请求信息,例如:请求的参数,发送的头信息等都属于客户端发来的信息,service()方法中形参接收的是HttpSe

Servlet工作原理(转)

Servlet运行在Servlet容器中,由容器负责Servlet实例的查找及创建工作,并按照Servlet规范的规定调用Servlet的一组方法,这些方法也叫生命周期的方法.具体调用过程如下图所示: Servlet生命周期详解 如上图所示,Servlet的生命周期可以分为四个阶段,即装载类及创建实例阶段.初始化阶段.服务阶段和实例销毁阶段.下面针对每个阶段的编程任务及注意事项进行详细的说明. (1)装载类及创建实例 客户端向Web服务器发送一个请求,请求的协议及路径必须遵守如下的格式: