Servlet编程专题4之Servlet核心
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Servlet编程专题4之Servlet核心相关的知识,希望对你有一定的参考价值。
1、javax.servlet.GenericServlet类:
- 该类定义一般的,与协议无关的servlet。在Web应用中用于写入servlet,HttpServlet继承自它。
- 该类实现了Servlet接口和ServletConfig接口,GenericServlet类可以被servlet类继承,但一般具体的子类是HttpServlet。
- 需要注意的是,如果继承自GeniricServlet抽象类的自定义Servlet类,则需要实现GeniricServlet抽象类的service()方法;如果需要重写Servlet接口中的初始化init方法,则需要重写GeniricServlet类的init()方法。(不能够重写init(ServletConfig config)方法,因为重写后会导致ServletConfig类对象无法被注册,当调用Servlet类对象对应的ServletConfig类对象的方法时会出现空指针异常。)
2、javax.servlet.http.HttpServlet类:提供一个抽象类用于创建适合网站HTTP Servlet的实例,HttpServlet的子类至少得重写以下一个方法:
- HttpServlet类继承自GenericServlet抽象类,重写了其service(ServletRequest req, ServletResponse res)方法:(将ServletRequest类对象向下转型为HttpServletRequest类对象,并将ServletResponse类对象向下转型为HttpServletResponse类对象。)。以下为类中的service方法的源码:
- HttpServlet类中的doGet()或者doPost()方法:由服务器调用(通过service()方法),允许servlet处理一个GET请求或者POST请求:
3、javax.servlet.http.HttpServletRequest接口:SUN制定的Servlet规范,是一个接口,表示请求,其父接口是javax.servlet.ServletRequest。“Http请求协议”的完整内容都被封装到request对象中。
- Apache软件基金会开发的“Tomcat容器”对java.serlvlet.http.HttpServletRequest接口进行了实现,其实现类完整类名是org.apache.catallina.connector.RequestFacade,但是程序员不需要关心具体的请求对象的实现类,不需要关心是哪个容器,只需要向HttpServletRequest接口调用方法即可。(面向接口编程,面向抽象编码)
a、关于请求的生命周期问题:HttpServletRequest实例对象是什么时候创建和销毁的呢?
- 当客户端浏览器将请求(字符序列)发送到服务器后,服务器会根据HTTP请求协议的格式对请求进行解析。同时,服务器会创建HttpServletRequest的实现类RequestFacade的对象,即请求对象。然后再调用相应的set方法,将解析出来的数据封装到请求对象中。此时HttpServletRequest实例就创建并初始化完毕。也就是说,请求对象是由服务器创建。
- 当服务器向客户端发送响应结束后,HttpServletRequest实例对象被服务器销毁。
- 一次请求对应一个请求对象,另外一次请求对应另外一个请求对象,与之前的请求对象没有任何关系。HttpServletRequest实例的生命周期很短暂。
b、关于请求参数问题:HttpServletRequest对于请求中所携带的参数是以Map的形式接收的,并且该Map的key为String,value为String数组。
- 为什么是String数组而不是String呢?因为Http请求协议允许一个请求参数具有多个值的情况出现。如表单中复选框值就可以是多个。
c、javax.servlet.http.HttpServletRequest接口中的方法:
- getMethod()方法获取用户请求的方式:
- 获取请求参数的方式:(javax.servlet.ServletRequest接口中的方法,HttpServletRequest接口继承自ServletRequest接口)
- getParameter(String name)方法根据提供的字符串序列参数获取用户请求中的对应参数值。
- getParameterMap()方法返回用户请求中的请求参数和请求参数值组成的键值对序列。(返回的是Map<String, String[]>对象)
- getParameterNames()方法返回用户请求中的请求参数序列。
- getParameterValues(String name)方法返回指定请求参数对应的参数值序列(用于复选框)。
- 域属性:在request中也存在域属性,用于存放有名称的数据。该数据只在当前的Request请求中才能够访问。
- 常用方法:(域属性的生命周期与request对象的生命周期相同。)(javax.servlet.ServletRequest接口中的方法,HttpServletRequest接口继承自ServletRequest接口)
- 从请求中获取服务端相关信息:(javax.servlet.http.HttpServletRequest接口中的方法,getRemoteAddr()方法除外。)
- 获取客户端访问服务器时请求的url路径(即浏览器地址栏中的路径)
- 获取客户端访问服务器时请求的uri路径(即请求行中第一个空格后,第二个空格前的内容,即浏览器地址栏上端口号后的内容【包含斜杠/】)
- 获取当前Web应用的根路径:(即:/ +项目名)
- 获取客户端IP:
- getServletPath()方法返回的是<url-pattern>路径的精确部分(如果没有非精确部分(通配符部分),则是<url-pattern>中的全部内容);getPathInfo()方法会的是非精确部分,即地址栏上与<url-pattern>匹配之外的额外的部分(如果不存在,则为null)。
- 请求提交时中文乱码问题:(需要注意的是,Tomcat9.0解决了get请求提交时的中文乱码问题。)
- POST请求提交时中文乱码问题解决:(javax.servlet.ServletRequest接口中的方法)
- 设置请求体中的字符编码方式:
- GET请求时中文乱码问题:在Tomcat安装根目录的conf目录下的server.xml文件的<Connector>标签中添加URIEncoding="UTF-8"属性(我的路径为:D:\apache-tomcat-7.0.72\conf。)
- 需要注意的是,如果在Eclipse中使用的Tomcat服务器,则需要修改当前工作空间上的server.xml文件。
- 既可以解决POST请求又可以解决GET请求提交时中文乱码问题:在自定义的servlet类中,将请求参数值字符串使用getBytes(String charsetName)方法(传入参数“ISO8859-1”字符串)方式进行解码,以byte[]类型的引用接收,再使用String类的构造器String(byte[] bytes, String charsetName)将byte[]类型的数据编码成字符串类型。(需要注意的是,Tomcat服务器从浏览器中接收的字符串参数值统一编码为“ISO8859-1”)
- java.lang.String类的getBytes(String charsetName)方法:
- java.lang.String类的构造器String(byte[] bytes, String charsetName):
- 以下为示例代码:
4、javax.servlet.ServletRequest接口:请求的转发
- 获取ServletRequest接口的实现类对象:(javax.servlet.ServletRequest接口中的方法,HttpServletRequest接口继承自ServletRequest接口)传递的参数为给定的当前web的路径,返回RequestDispatcher接口的实现类对象。需要注意的是,请求的转发,request对象没有被销毁,域属性还可以继续使用。
- javax.servlet.RequestDispatcher接口中的方法:
- 请求转发的forward(ServletRequest request, ServletResponse response)方法:转发一个请求从一个servlet到服务器中的另外一个资源(包括servlet,JSP文件或者html文件)
- 注:javax.servlet.http.HttpServletResponse接口中sendRedirect(String location)方法为请求的重定向方法。
5、javax.servlet.http.HttpServletResponse接口:Web服务器收到一个Http请求后,会针对每个请求创建一个HttpServletRequest对象和HttpServletResponse对象。若需要获取客户端提交请求的相关信息,则需要从HttpServletRequest对象中获取;若需要向客户端发送数据,则需要通过HttpSerlvetResponse对象来完成。
- javax.servlet.ServletResponse接口中的方法:(javax.servlet.http.HttpServletResponse接口的父接口)
- getWriter()方法返回一个标准输出流对象,用于向客户端中输出字符数据:
java.io.PrintWriter类中的print(String s)方法和write(String s)方法都可以向标准输出流中写入数据:(客户端浏览器可以直接看到这些数据)
- response的中文乱码解决方案:(例如在HttpServletResponse接口类对象使用getWriter()方法返回标准输出流对象,向标准输入流中写入中文)
- 设置响应的MIME类型:(可以设置为文本中的HTML,即“text/html;charset=UTF-8
”)(javax.servlet.ServletResponse接口中的方法)
- 设置响应的字符编码(MIME字符集),即“text/html;charset=UTF-8
”中的“charset=”后的字符串的设置:(javax.servlet.ServletResponse接口中的方法)
- 请求的重定向:使用指定url路径为客户端发送一个临时的重定向响应(以此清空缓存)(javax.servlet.http.HttpServletResponse接口中的方法)
6、附加说明:
a、关于请求转发和重定向问题:
- 请求转发和重定向均是指的是请求的跳转方式。但请求转发是指服务器内跳转,重定向是指服务器外部跳转。(可以使用重定向由一个项目跳转到另外一个项目。)
- 转发是一次请求,重定向是两次请求。请求转发只会发出一次请求,收到一次响应,所转发到的资源可以直接获取到请求中所携带的数据,浏览器中的地址栏显示的为用户所提交的请求路径,不会发生改变【只能跳转到当前应用的资源中】。重定向无法获取到用户请求提交的数据,也无法获取HttpServletRequest接口的实现类对象中设置的域属性的值。【同时重定向发送的请求方式为get请求,会导致浏览器中地址栏发生变化】(重定向可以防止表单重复提交)
- 关于重定向中数据传递问题解决:可以在使用HttpServletResponse接口中的方法sendRedirect(String locaction)重定向传递参数时传递相关的数据。(以“?username=xxx&password=ooo”的方式)
b、请求转发和重定向的选择问题:
- 若需要跳转到其他应用,则使用重定向。
- 若是处理表单数据的Servlet,需要跳转到其他Servlet,则需要选择重定向。以此防止表单重复提交。
- 若对某一请求进行处理的Servlet的执行需要消耗大量的服务器资源(CPU、内存),此时这个Servlet执行完毕后,需要重定向。
- 其他情况下,一般使用请求转发。
c、访问路径问题:
- URL和URI的认识:
- 统一资源定位符,用于定位资源的一种方式。通常的URL资源访问路径由两部分构成:资源路径和资源名称。资源名称指的是要访问资源的直接名称。如show.html,或与要访问资源存在映射关系的间接名称,如show.do。而资源路径,则是通过该路径则可以定位到指定的资源。即资源路径是指在URL资源访问路径中除了资源名称以外的其他部分。
- 根据以上规则,URI,统一资源标识符,也可以分为资源路径和资源名称两部分。
- 一般情况下,在URL或者URI以外,最后一个斜杠后的部分为资源名称,而其他部分则为资源路径。
- 绝对路径和相对路径的区别:
- 根据“资源路径是否可以独立完成资源准确定位”的判别标准,可以将访问路径分为绝对路径和相对路径。
- 对于计算机中Web应用的绝对路径,则是指带访问协议的路径,即URL。例如下面的路径就是一个带有http访问协议的绝对路径:http://127.0.0.1:8080/primary/index.jsp。
- 相对路径,是指仅根据访问路径无法准确定位资源的路径。相对路径必须要结合其参照路径才能够组成准确定位资源的绝对路径。
- 需要注意的是,相对路径的写法有两种:一种是以斜杠开头的相对路径,一种是以路径名称开头的相对路径。根据相对路径是否以斜杠开头,且路径所在文件所处位置的不同,其默认的参照路径是不同的。
- 绝对路径和相对路径的关系为:绝对路径 = 参照路径 + 相对路径。
- 相对路径的区分:
i、以斜杠开头的相对路径,根据路径所在文件所处位置的不同,可以分为前台路径和后台路径两类。
- 所谓前台路径是指,由浏览器解析执行的代码中所包含的路径。前台路径的的参照路径是Web服务器的根路径,即http://127.0.01:8080。(将前台路径转换成绝对路径的工作,是由浏览器自动完成的)
- 所谓后台路径是指,由服务器解析执行的代码以及文件中所包含的路径。例如,java代码中的路径、jsp文件动态部分(java代码块)中的路径、xml等配置文件中的路径(配置文件是要被java代码解析后加载到内存的,其中的路径会出现在java代码中)。后台路径的参照路径是Web应用的根路径。如http:127.0.0.1:8080/primary。(将后台路径转换成绝对路径的工作,是由服务器自动完成的。)
- 后台路径中的特例:当代码中使用response的sendRedirect()方法进行重定向的时候,若其参照路径是以斜杠开头,则其参照路径不是web路径的根路径,而是web服务器的根路径。例如,执行reponse.sendRedirect("show.jsp")将会报404错误。因为其参照路径是Tomcat的根,而非当前项目的根。所以若是使用重定向,就需要在路径上添加其项目名称:(为什么是特例?因为sendRedirect()方法可以重定向到其他应用,若不指定要跳转的应用,将无法确定跳转方向。)
response.sendRedirect(request.getContextPath + "/show.jsp");
ii、以路径名称开头的相对路径:
- 以路径名称开头的相对路径,无论是出现在前台页面,还是出现在后台java代码或者配置文件中,其参照路径都是“当前访问路径的资源路径”。即使是response的sendRedirect()方法的参照路径,若是不以斜杠开头,其也属于“以路径名称开头的相对路径”类,参照路径为当前访问路径的资源路径。
本文出自 “12392717” 博客,请务必保留此出处http://12402717.blog.51cto.com/12392717/1973984
以上是关于Servlet编程专题4之Servlet核心的主要内容,如果未能解决你的问题,请参考以下文章
Servlet编程专题2之获取ServletConfig对象