Servlet

Servlet servlet的由来 自从计算机软件开发进入网络时代,就开始涉及到通讯问题。在客户/服务器 (C/S) 时期,每个软件都有自己的客户端和服务器端软件。并且客户端和服务器端之间的通讯协议差别也很大。后来随着互联网的发展,基于浏览器/服务器(B/S)的应用逐渐成为主流,通讯协议也统一到HTTP协议。但是,在HTTP协议之上,如何处理来自客户端的请求信息,以及如何对请求进行回应,则经历了很长时间也没有统一下来。目前,对于这个问题的解决方案主要有两种,一个是CGI,另一个是Servlet。 servlet是在服务器上运行的小程序。这个词是在Java applet的环境中创造的,Java applet是一种当作单独文件跟网页一起发送的小程序,它通常用于在客户端运行,结果得到为用户进行运算或者根据用户互作用定位图形等服务。服务器上需要一些程序,常常是根据用户输入访问数据库的程序。这些通常是使用公共网关接口 (CGI(Common Gateway Interface)) 应用程序完成的。然而,在服务器上运行Java,这种程序可使用Java编程语言实现。在通信量大的服务器上,servlet的优点在于它们的执行速度更快于CGI程序。各个用户请求被激活成单个程序中的一个线程,而无需创建单独的进程,这意味着服务器端处理请求的系统开销将明显降低。最早支持Servlet技术的是JavaSoft的Java Web Server。此后,一些其它的基于Java的WebServer开始支持标准的ServletAPI。 Servlet最初是在1995年由James Gosling 提出的,因为使用该技术需要复杂的Web服务器支持,所以当时并没有得到重视,也就放弃了。后来随着Web应用复杂度的提升,并要求提供更高的并发处理能力,Servlet被重新捡起,并在Java平台上得到实现,现在提起Servlet,指的都是Java Servlet。Java Servlet要求必须运行在Web服务器当中,与Web服务器之间属于分工和互补关系。确切的说,在实际运行的时候Java Servlet与Web服务器会融为一体,如同一个程序一样运行在同一个Java虚拟机 (JVM) 当中。与CGI不同的是,Servlet对每个请求都是单独启动一个线程,而不是进程。这种处理方式大幅度地降低了系统里的进程数量,提高了系统的并发处理能力。另外因为Java Servlet是运行在虚拟机之上的,也就解决了跨平台问题。 在Servlet出现之后,随着使用范围的扩大,人们发现了它的一个很大的一个弊端。那就是为了能够输出HTML格式内容,需要编写大量重复代码,造成不必要的重复劳动。为了解决这个问题,基于Servlet技术产生了Java Server Pages (JSP) 。 Servlet和JSP两者分工协作,Servlet侧重于解决运算和业务逻辑问题,JSP则侧重于解决展示问题。Servlet与JSP一起为Web应用开发带来了巨大的贡献,后来出现的众多Java Web应用开发框架都是基于这两种技术的,更确切的说,都是基于Servlet技术的。 Servlet与Web容器之间的关系 Java是一种动态加载和运行的语言。也就是说当应用程序持有一个类的地址 (CLASSPATH) 和名称 (包名和类名) 的情况下,可以在程序运行期间任何时候加载这个类,并创建和使用该类的对象。Servlet就是基于这个机制与Web容器融合在一起的。目前已知的所有支持Java Servlet的Web容器都是采用Java开发的。当Web容器接收到来自客户端的请求信息之后,会根据URL中的Web元件地址信息到Servlet队列中查找对应的Servlet对象,如果找到则直接使用,如果没有找到则加载对应的类,并创建对象。也就是说,Servlet对象是在第一次被使用的时候才创建的,并且一旦创建就会被反复使用,不再创建新的对象。所有创建出的Servlet对象会在Web服务器停止运行的时候统一进行垃圾回收。 为了解决客户端请求地址与 Servlet之间对应关系问题,Web容器需要一个用来描述这种对应关系的文件,一般是web.xml文件。如果一个Web应用程序中存在很多个Servlet,那么web.xml会变得非常庞大。在Servlet 3.0规范推出之后,允许在Servlet代码中使用声明式语法(annotation)来代替web.xml中的描述信息,这才让web.xml瘦身下来. Servlet是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面。 它担当客户请求 (Web浏览器或其他HTTP客户程序) 与服务器响应 (HTTP服务器上的数据库或应用程序) 的中间层。 Servlet是位于Web 服务器内部的服务器端的Java应用程序,与传统的从命令行启动的Java应用程序不同,Servlet由Web服务器进行加载,该Web服务器必须包含支持Servlet的Java虚拟机。 Servlet的主要功能在于交互式地浏览和修改数据,生成动态Web内容。这个过程为: 客户端发送请求至服务器端; 服务器将请求信息发送至Servlet ; Servlet生成响应内容并将其传给Server。响应内容动态生成,通常取决于客户端的请求; 服务器将响应返回给客户端; Servlet看起来像是通常的Java程序。Servlet导入特定的属于Java ServletAPI的包。因为是对象字节码,可动态地从网络加载,可以说Servlet对Server就如同Applet对Client一样,但是,由于Servlet运行于Server中,它们并不需要一个图形用户界面。从这个角度讲,Servlet也被称为FacelessObject。 一个servlet就是Java编程语言中的一个类,它被用来扩展服务器的性能,服务器上驻留着可以通过"请求-响应"编程模型来访问的应用程序。虽然servlet可以对任何类型的请求产生响应,但通常只用来扩展Web服务器的应用程序。 目前最新版本为3.0草案命名: Server + Applet =Servlet 意为服务器端的小程序 Servlet生命周期 装载Servlet。这项操作一般是动态执行的。然而,Server通常会提供一个管理的选项,用于在Server启动时强制装载和初始化特定的Servlet。 Server创建一个Servlet的实例 Server调用Servlet的init()方法 一个客户端的请求到达Server Server创建一个请求对象 Server创建一个响应对象 Server激活Servlet的service()方法,传递请求和响应对象作为参数 service()方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息 service()方法使用响应对象的方法,将响应传回Server,最终到达客户端。service()方法可能激活其它方法以处理请求,如doGet()或doPost()或程序员自己开发的新的方法。 对于更多的客户端请求,Server创建新的请求和响应对象,仍然激活此Servlet的service()方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用init()方法。一般Servlet只初始化一次(只有一个对象),当Server不再需要Servlet时(一般当Server关闭时),Server调用Servlet的Destroy()方法。 ...

Created 16166-10-16 · Updated 9096-10-09 · 3 min · 519 words · -

web.xml

web.xml web.xml template servlet 2.5 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> web.xml 3.0: http://www.wiloon.com/?p=3484 <?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="false"> <display-name>Servlet 3.x Demo</display-name> <description>A demo for servlet 3.x</description> <servlet> <servlet-name>HelloWorld</servlet-name> <servlet-class>com.wiloon.test.servlet.HelloWorld</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorld</servlet-name> <url-pattern>/servlet/HelloWorld</url-pattern> </servlet-mapping> </web-app> web.xml是传统的部署描述文件。 servlet 3.x 中web.xml 变为可选配置. ...

Created 10106-06-10 · Updated 9096-10-09 · 6 min · 1226 words · -

web.xml mime-mapping

web.xml – mime-mapping 关联文件与MIME类型 服务器一般都具有一种让Web站点管理员将文件扩展名与媒体相关联的方法。例如,将会自动给予名为mom.jpg的文件一个image/jpeg的MIME 类型。但是,假如你的Web应用具有几个不寻常的文件,你希望保证它们在发送到客户机时分配为某种MIME类型。mime-mapping元素 (具有 extension和mime-type子元素) 可提供这种保证。例如,下面的代码指示服务器将application/x-fubar的MIME类型分配给所有以.foo结尾的文件。 <mime-mapping> <extension>foo</extension> <mime-type>application/x-fubar</mime-type> </mime-mapping> 或许,你的Web应用希望重载 (override) 标准的映射。例如,下面的代码将告诉服务器在发送到客户机时指定.ps文件作为纯文本 (text/plain) 而不是作为PostScript (application/postscript) 。 <mime-mapping> <extension>ps</extension> <mime-type>application/postscript</mime-type> </mime-mapping> TOMCAT在默认情况下下载.rar的文件是把文件当作text打开,以至于IE打开RAR文件为乱码,如果遇到这种情况时不必认为是浏览器的问题,大多数浏览器应该不会死皮赖脸地把二进制文件当作文本打开,一般都是服务器给什么浏览器就开什么.解决方法: 打开conf/web.xml,加入下面的代码. <mime-mapping> <extension>doc</extension> <mime-type>application/msword</mime-type> </mime-mapping> <mime-mapping> <extension>xls</extension> <mime-type>application/msexcel</mime-type> </mime-mapping> <mime-mapping> <extension>pdf</extension> <mime-type>application/pdf</mime-type> </mime-mapping> <mime-mapping> <extension>zip</extension> <mime-type>application/zip</mime-type> </mime-mapping> <mime-mapping> <extension>rar</extension> <mime-type>application/rar</mime-type> </mime-mapping> <mime-mapping> <extension>txt</extension> <mime-type>application/txt</mime-type> </mime-mapping> <mime-mapping> <extension>chm</extension> <mime-type>application/mshelp</mime-type> </mime-mapping> <mime-mapping> <extension>mp3</extension> <mime-type>audio/x-mpeg</mime-type> </mime-mapping> 重启TOMCAT,清除IE缓存,再打开RAR的文件时就可以正常下载了. 常见的MIME类型 超文本标记语言文本 .htm,.html text/html 普通文本 .txt text/plain RTF文本 .rtf application/rtf GIF图形 .gif image/gif ...

Created 10106-06-10 · Updated 9096-10-09 · 1 min · 115 words · -

servlet3.0

servlet3.0 http://www.ibm.com/developerworks/cn/java/j-lo-servlet30/ Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布。该版本在前一版本 (Servlet 2.5) 的基础上提供了若干新特性用于简化 Web 应用的开发和部署。其中有几项特性的引入让开发者感到非常兴奋,同时也获得了 Java 社区的一片赞誉之声: 异步处理支持: 有了该特性,Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。在接收到请求之后,Servlet 线程可以将耗时的操作委派给另一个线程来完成,自己在不生成响应的情况下返回至容器。针对业务处理较耗时的情况,这将大大减少服务器资源的占用,并且提高并发处理速度。 新增的注解支持: 该版本新增了若干注解,用于简化 Servlet、过滤器 (Filter) 和监听器 (Listener) 的声明,这使得 web.xml 部署描述文件从该版本开始不再是必选的了。 可插性支持: 熟悉 Struts2 的开发者一定会对其通过插件的方式与包括 Spring 在内的各种常用框架的整合特性记忆犹新。将相应的插件封装成 JAR 包并放在类路径下,Struts2 运行时便能自动加载这些插件。现在 Servlet 3.0 提供了类似的特性,开发者可以通过插件的方式很方便的扩充已有 Web 应用的功能,而不需要修改原有的应用。 新增的注解支持 Servlet 3.0 的部署描述文件 web.xml 的顶层标签 <web-app> 有一个 metadata-complete 属性,该属性指定当前的部署描述文件是否是完全的。如果设置为 true,则容器在部署时将只依赖部署描述文件,忽略所有的注解 (同时也会跳过 web-fragment.xml 的扫描,亦即禁用可插性支持,具体请看后文关于 可插性支持的讲解) ;如果不配置该属性,或者将其设置为 false,则表示启用注解支持 (和可插性支持) 。 @WebServlet @WebServlet 用于将一个类声明为 Servlet,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为 Servlet。该注解具有下表给出的一些常用属性 (以下所有属性均为可选属性,但是 vlaue 或者 urlPatterns 通常是必需的,且二者不能共存,如果同时指定,通常是忽略 value 的取值) : ...

Created 10106-06-10 · Updated 9096-10-09 · 2 min · 405 words · -

context-param 与 init-param

‘context-param&init-param’ <context-param>的作用: web.xml的配置中<context-param>配置作用 1. 启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: </listener> 和 <context-param></context-param> 2.紧接着,容器创建一个ServletContext(上下文),这个WEB项目所有部分都将共享这个上下文. 3.容器将<context-param></context-param>转化为键值对,并交给ServletContext. 4.容器创建</listener>中的类实例,即创建监听. 5.在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得ServletContext = ServletContextEvent.getServletContext(); context-param的值 = ServletContext.getInitParameter(“context-param的键”); 6.得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早. 换句话说,这个时候,你对<context-param>中的键值做的操作,将在你的WEB项目完全启动之前被执行. 7.举例.你可能想在项目启动之前就打开数据库. 那么这里就可以在<context-param>中设置数据库的连接方式,在监听类中初始化数据库的连接. 8.这个监听是自己写的一个类,除了初始化方法,它还有销毁方法.用于关闭应用前释放资源.比如说数据库连接的关闭. web.xml里面可以定义两种参数: (1)application范围内的参数,存放在servletcontext中,在web.xml中配置如下: <context-param> <param-name>context/param</param-name> <param-value>avalible during application</param-value> </context-param> <context-param> <param-name>cpn</param-name> <param-value>cpv</param-value> </context-param> (2)servlet范围内的参数,只能在servlet的init()方法中取得,在web.xml中配置如下: <servlet> <servlet-name>MainServlet</servlet-name> <servlet-class>com.wes.controller.MainServlet</servlet-class> <init-param> <param-name>param1</param-name> <param-value>avalible in servlet init()</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> 在servlet中可以通过代码分别取用: package com.wes.controller; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; public class MainServlet extends HttpServlet { public MainServlet() { super(); } public void init() throws ServletException { System.out.println("下面的两个参数param1是在servlet中存放的"); System.out.println(this.getInitParameter("param1")); System.out.println("下面的参数是存放在servletcontext中的"); System.out.println(getServletContext().getInitParameter("context/param")); } } 第一种参数在servlet里面可以通过getServletContext().getInitParameter(“context/param”)得到 ...

Created 10106-06-10 · Updated 9096-10-09 · 1 min · 101 words · -

Servlet Filter

Servlet Filter @Servlet里的过滤器的主要作用 1,判断用户是否登录。 2,网络聊天系统或论坛,功能是过滤非法文字 3,统一解决编码 @Servlet3.0之前怎么创建一个过滤器 1,生成一个普通的class类,实现Filter接口(javax.servlet.Filter)。 2,重写接口里面的三个方法: init,doFilter,destroy。 其中的doFilter方法的第一个参数为ServletRequest对象。此对象给过滤器提供了对进入的信息 (包括表单数据、cookie和HTTP请求头) 的完全访问。第二个参数为ServletResponse,通常在简单的过滤器中忽略此参数。最后一个参数为FilterChain,此参数用来调用servlet或JSP页。 3,然后在web.xml配置过滤器。 具体例子:1.首先写一个权限过滤filter类,实现Filter接口 import javax.servlet.Filter; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.FilterChain; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpServletResponse; public class RightFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; //如果处理HTTP请求,并且需要访问诸如getHeader或getCookies等在ServletRequest中无法得到的方法 //就要把此request对象构造成HttpServletRequest HttpServletResponse res = (HttpServletResponse) response; HttpSession session = req.getSession(true); //从session里取的用户名信息 String username = (String) session.getAttribute("username"); //判断如果没有取到用户信息,就跳转到登陆页面 if (username == null || "".equals(username)) { //跳转到登陆页面 res.sendRedirect("http://"+req.getHeader("Host")+"/login.jsp"); } else { //已经登陆,继续此次请求 chain.doFilter(request,response); //调用FilterChain对象的doFilter方法 //Filter接口的doFilter方法取一个FilterChain对象作为它的一个参数 //在调用此对象的doFilter方法时,激活下一个相关的过滤器 //如果没有另一个过滤器与servlet或JSP页面关联,则servlet或JSP页面被激活 } } public void destroy() { } } 2.然后在web.xml里配置需要登陆权限验证的JSP文件: ...

Created 10106-06-10 · Updated 9096-10-09 · 5 min · 1056 words · -

ServletContextListener

ServletContextListener http://www.cnblogs.com/kentyshang/archive/2007/06/26/795878.html ServletContextListener处理Web应用的 servlet上下文(context)的变化的通知。这可以解释为,好像有个人在服务器旁不断地通知我们服务器在发生什么事件。那当然需要监听者了。因 此,在通知上下文(context)初始化和销毁的时候,ServletContextListner非常有用。 import javax.servlet.ServletContextListener; import javax.servlet.ServletContextEvent; import javax.servlet.*; public class MyListener implements ServletContextListener { private ServletContext context = null; /* 这个方法在Web应用服务被移除,没有能力再接受请求的时候被调用。 */ public void contextDestroyed(ServletContextEvent event){ //Output a simple message to the server's console System.out.println("The Simple Web App. Has Been Removed"); this.context = null; } // 这个方法在Web应用服务做好接受请求的时候被调用。 public void contextInitialized(ServletContextEvent event){ this.context = event.getServletContext(); //Output a simple message to the server's console System.out.println("The Simple Web App. Is Ready"); } } <web-app> <listener> <listener-class> com.listeners.MyContextListener </listener-class> </listener> <servlet/> <servlet-mapping/> </web-app> —————————————-转载http://blog.csdn.net/ezerg/archive/2004/09/24/115894.aspx ...

Created 22226-06-22 · Updated 9096-10-09 · 1 min · 210 words · -

Filter FilterChain

Filter FilterChain **[http://blog.csdn.net/zhaozheng7758/article/details/6105749](http://blog.csdn.net/zhaozheng7758/article/details/6105749)** 一、Filter的介绍及使用**** 什么是过滤器? 与Servlet相似,过滤器是一些web应用程序组件,可以绑定到一个web应用程序中。但是与其他web应用程序组件不同的是,过滤器是"链"在容器的处理过程中的。这就意味着它们会在servlet处理器之前访问一个进入的请求,并且在外发响应信息返回到客户前访问这些响应信息。这种访问使得过滤器可以检查并修改请求和响应的内容。 过滤器适用于那些地方? l 为一个web应用程序的新功能建立模型(可被添加到web应用程序中或者从web应用程序中删除而不需要重写基层应用程序代码); l 向过去的代码添加新功能。 过滤器放在容器结构的什么位置? 过滤器放在web资源之前,可以在请求抵达它所应用的web资源(可以是一个Servlet、一个Jsp页面,甚至是一个HTML页面)之前截获进入的请求,并且在它返回到客户之前截获输出请求。Filter: 用来拦截请求,处于客户端与被请求资源之间,目的是重用代码。Filter链,在web.xml中哪个先配置,哪个就先调用。在filter中也可以配置一些初始化参数。 Java中的Filter 并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应。 主要用于对HttpServletRequest 进行预处理,也可以对HttpServletResponse 进行后处理,是个典型的处理链。 Filter 有如下几个用处: l 在HttpServletRequest 到达Servlet 之前,拦截客户的HttpServletRequest 。 l 根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。 l 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。 l 根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。 Filter 有如下几个种类: l 用户授权的Filter: Filter 负责检查用户请求,根据请求过滤用户非法请求。 l 日志Filter: 详细记录某些特殊的用户请求。 l 负责解码的Filter: 包括对非标准编码的请求解码。 l 能改变XML 内容的XSLTFilter 等。 一个Filter 可负责拦截多个请求或响应:一个请求或响应也可被多个请求拦截。 创建一个Filter 只需两个步骤: (1)创建Filter 处理类: (2)在web.xml 文件中配置Filter 。 创建Filter 必须实现javax.servlet.Filter 接口,在该接口中定义了三个方法。 • void init(FilterConfig config): 用于完成Filter 的初始化。 ...

Created 18186-11-18 · Updated 9096-10-09 · 3 min · 602 words · -

resource-ref

resource-ref resource-ref元素用于指定对外部资源的servlet引用的声明。 <!ELEMENT resource-ref (description?, res-ref-name, res-type, res-auth, res-sharing-scope?)> <!ELEMENT description (#PCDATA)> <!ELEMENT res-ref-name (#PCDATA)> <!ELEMENT res-type (#PCDATA)> <!ELEMENT res-auth (#PCDATA)> <!ELEMENT res-sharing-scope (#PCDATA)> resource-ref子元素的描述如下: ● res-ref-name是资源工厂引用名的名称。该名称是一个与java:comp/env上下文相对应的JNDI名称,并且在整个Web应用中必须是惟一的。 ● res-auth表明: servlet代码通过编程注册到资源管理器,或者是容器将代表servlet注册到资源管理器。该元素的值必须为Application或Container。 ● res-sharing-scope表明: 是否可以共享通过给定资源管理器连接工厂引用获得的连接。该元素的值必须为Shareable(默认值)或Unshareable。 维护记录 时间 修改内容 原因 2026-10-09 修复本地 Hugo 构建的 Raw HTML 警告:代码/配置放入代码块,正文中的尖括号占位符改为行内代码 正文中的 HTML/XML 片段被当作原始 HTML 丢弃;文件名/URL/标题按规范调整

Created 5056-01-05 · Updated 9096-10-09 · 1 min · 49 words · -

Java 获取客户端真实 IP 地址的两种方法

Java获取客户端真实IP地址的两种方法 http://dpn525.iteye.com/blog/1132318 在JSP里,获取客户端的IP地址的方法是: request.getRemoteAddr () ,这种方法在大部分情况下都是有效的。但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。 在JSP里,获取客户端的IP地址的方法是: request.getRemoteAddr () ,这种方法在大部分情况下都是有效的。但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。 如果使用了反向代理软件,将http://192.168.1.110: 2046/ 的URL反向代理为 http://www.javapeixun.com.cn / 的URL时,用request.getRemoteAddr () 方法获取的IP地址是: 127.0.0.1或192.168.1.110,而并不是客户端的真实IP。 经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息。用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址。当我们访问http://www.javapeixun.com.cn/index.jsp/ 时,其实并不是我们浏览器真正访问到了服务器上的index.jsp文件,而是先由代理服务器去访问http://192.168.1.110: 2046/index.jsp ,代理服务器再将访问到的结果返回给我们的浏览器,因为是代理服务器去访问index.jsp的,所以index.jsp中通过request.getRemoteAddr () 的方法获取的IP实际上是代理服务器的地址,并不是客户端的IP地址。 于是可得出获得客户端真实IP地址的方法一: public String getRemortIP(HttpServletRequest request) { if (request.getHeader("x-forwarded-for") == null) { return request.getRemoteAddr(); } return request.getHeader("x-forwarded-for"); } 可是当我访问http://www.5a520.cn /index.jsp/ 时,返回的IP地址始终是unknown,也并不是如上所示的127.0.0.1或192.168.1.110了,而我访问http://192.168.1.110: 2046/index.jsp 时,则能返回客户端的真实IP地址,写了个方法去验证。原因出在了Squid上。squid.conf 的配制文件forwarded_for 项默认是为on,如果 forwarded_for 设成了 off 则: X-Forwarded-For: unknown 于是可得出获得客户端真实IP地址的方法二: public String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,究竟哪个才是真正的用户端的真实IP呢? ...

Created 13136-03-13 · Updated 9096-10-09 · 2 min · 340 words · -

Servlet Filter

Servlet Filter Filter 是 Servlet 规范里的一种组件,位于容器和目标资源(Servlet/JSP)之间,可以在请求到达目标资源之前、响应离开目标资源之后做统一处理。Filter 本身不产生响应内容,只负责预处理和后处理,典型用途包括: 身份校验、权限校验 请求/响应日志记录 请求头、响应头改写 内容压缩、编码转换 多个 Filter 可以按声明顺序串成一条链(Filter Chain),这也是 责任链模式(Chain of Responsibility) 在 Servlet 规范里的经典实现;Spring Security 的 SecurityFilterChain 就是在这套机制上封装出来的应用。 Filter 接口 public interface Filter { default void init(FilterConfig filterConfig) throws ServletException { } void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; default void destroy() { } } init(FilterConfig):容器创建 Filter 实例后调用一次,用于读取初始化参数、保存 FilterConfig。 doFilter(request, response, chain):每次请求都会调用,是 Filter 的核心方法。 destroy():容器销毁 Filter 前调用一次,用于释放资源。 FilterConfig 提供访问 Filter 名称、初始化参数、ServletContext 的方法。 ...

Created 10106-06-10 · Updated 1016-07-01 · 2 min · 293 words · -

Forward 与 Redirect

forward vs redirect forward(请求转发):服务器收到请求后,在服务器内部把请求转交给另一个资源处理,再把结果返回客户端;浏览器地址栏不变,客户端不知道发生了转发。 redirect(重定向):服务器返回 3xx 状态码,浏览器再次发起新请求访问目标 URL,地址栏变为新地址;因此有两次往返,通常比 forward 开销大。 数据与作用域 forward:同一 HttpServletRequest 继续传递,request 属性、request 参数可带到目标资源;常用 request.getAttribute() 读取上一环节放入的数据。 redirect:浏览器发的是新请求,上一请求的 request 属性不会保留;URL 查询参数会随新请求带上。HttpSession 仍可通过 cookie 关联(session 级数据一般可用),但不要把「上一 request 的 attribute」误当成 redirect 后还能直接读。 效率:forward 仅在服务端处理,对客户端透明;redirect 多一次客户端往返,通常更慢。 范围:因 request.setAttribute() 的生命周期限于当前 request,redirect 会导致 attribute 丢失;需要跨 redirect 传值时,常用 session、URL 参数或 flash 等机制。 前后端分离下的表现 典型架构为 React 前端 + Spring Boot REST API。页面路由与组件组合由前端负责,后端主要返回 JSON;因此早年 JSP 时代「forward 到另一个 JSP 拼页面」的用法在业务层已基本消失,但两种机制仍以不同形式存在。 redirect:仍然常见 redirect 是 HTTP 层行为,与是否使用 JSP 无关。前后端分离项目中常见场景: OAuth / 第三方登录:授权服务器回调后,后端或网关返回 302 跳转到前端路由(如 /auth/callback) PRG(Post-Redirect-Get):表单或写操作后 return "redirect:/...",避免刷新重复提交(多见于仍保留 @Controller 的服务端表单) 文件下载、外链跳转:API 或网关返回 302 指向实际资源地址 网关 / 反向代理:未登录时重定向到登录页(也可由前端根据 401 自行跳转) 前端日常路由切换由 React Router 完成,不经过 Servlet redirect;但跨域认证、登录回调、下载等仍会碰到 HTTP 重定向。 ...

Created 21216-09-21 · Updated 21216-06-21 · 1 min · 206 words · -

Servlet 生命周期

Servlet 运行在 Servlet 容器中,生命周期由容器管理。规范通过 Servlet 接口的 init()、service()、destroy() 描述这一过程;Java EE 8 及以前包名为 javax.servlet.*,Spring Boot 3 起对应 Jakarta Servlet(jakarta.servlet.*),语义不变。 四个阶段 加载和实例化 Servlet 容器负责加载和实例化 Servlet。容器启动时,或在首次需要该 Servlet 处理请求时,创建实例。容器通过类加载器找到 Servlet 类,再用反射调用无参构造方法实例化,因此业务 Servlet 一般不应定义带参构造方法。 初始化 实例化后,容器调用 init() 做一次性初始化(如读取配置、建立连接)。每个 Servlet 实例的 init() 只执行一次。初始化期间可通过 ServletConfig 读取配置(传统项目多在 web.xml,Spring Boot 中常由框架代劳)。失败时可抛出 ServletException 或 UnavailableException 通知容器。 请求处理 请求到达后,容器调用 service();HttpServlet 会按 HTTP 方法分派到 doGet()、doPost() 等。service() 执行前 init() 必须已成功完成。处理中通过 ServletRequest / ServletResponse(或 HttpServletRequest / HttpServletResponse)读写请求与响应。若抛出表示永久不可用的 UnavailableException,容器会调用 destroy() 并返回 404;暂时不可用则返回 503。 服务终止 容器卸载 Servlet 或关闭时调用 destroy(),释放资源。之后实例被回收;若再次需要,容器会创建新实例。 ...

Created 30306-10-30 · Updated 21216-06-21 · 2 min · 227 words · -

Jetty

Jetty Jetty 是一个开源的 servlet 容器,它为基于 Java 的 web 内容(例如 JSP 和 servlet)提供运行环境。Jetty 使用 Java 编写,API 以一组 JAR 包的形式发布。开发人员可以将 Jetty 容器实例化成一个对象,为一些独立运行(stand-alone)的 Java 应用提供网络和 web 连接。 易用性 易用性是 Jetty 设计的基本原则,主要体现在: 通过 XML 或 API 配置 Jetty 默认配置可满足大部分需求 将 Jetty 嵌入应用程序只需很少的代码 可扩展性 在使用了 Ajax 的 Web 2.0 应用中,每个连接需要保持更长时间,线程和内存消耗会明显增加。Jetty 在这方面有优势: 即使在大量服务请求下,系统性能仍可保持可接受水平 利用 Continuation 机制处理大量用户请求及长连接 接口设计良好,当某种实现无法满足需求时,可方便地修改 Jetty 的特定实现 易嵌入性 Jetty 设计之初就是作为优秀组件来设计的,可非常容易地嵌入应用程序,无需为使用 Jetty 而大幅修改程序。某种程度上,也可以把 Jetty 理解为一个嵌入式 Web 服务器。 Jetty 可作为嵌入式服务器使用,运行速度较快且轻量,可在 Java 测试用例中控制其运行,使自动化测试不再依赖外部环境。 Jetty vs Tomcat 参考:Jetty 与 Tomcat 的比较(IBM developerWorks) ...

Created 16166-12-16 · Updated 20206-05-20 · 1 min · 173 words · -

getRequestDispatcher(), sendRedirect()

getRequestDispatcher(), sendRedirect() 1.getRequestDispatcher(url)是请求转发,前后页面共享一个request。 RequestDispatcher 对象从客户端获取请求request,并把它们传递给服务器上的servlet,html或jsp。 它有两个方法: forward()和include()具体如下 void forward(ServletRequest request,ServletResponse response) 用来传递request的,可以一个Servlet接收request请求,另一个Servlet用这个request请求来产生response。request传递的请求,response是客户端返回的信息。forward要在response到达客户端之前调用,也就是 before response body output has been flushed。如果不是的话,它会报出异常。 void include(ServletRequest request,ServletResponse response) 用来记录保留request和 response,以后不能再修改response里表示状态的信息。 request.getRequestDispatcher(url).forward(request,response)是直接将请求转发到指定URL,所以该请求能够直接获得上一个请求的数据,request对象始终存在,不会重新创建。 forward 发生在服务器内部, 在浏览器完全不知情的情况下发给了浏览器另外一个页面的response. 这时页面收到的request不是从浏览器直接发来了,可能己经放了数据。 请求转发时如果要传递参数可以这样用: request.setAttribute(“name”,“Michael”); request.getAttribute(“name”); 2.sendRedirect(url)重定向到指定URL,会新建request对象。 这是因为 redirect 会首先发一个response给浏览器, 然后浏览器收到这个response后再发一个requeset给服务器, 然后服务器发新的response给浏览器,这时页面收到的request是从浏览器新发来的,所以上一个request的数据会丢失。 如果要传递参数只有在url后加参数的方式,比如url?type=test才能实现。 3.ServletContext.sendRedirect(String url)中的url只能使用绝对路径; 而ServletRequest.getRequestDispatcher(String url)中的url可以使用相对路径。h这是因为ServletRequest具有相对路径的概念;而ServletContext对象无此概念。 PS:如果需要把请求转移到另外一个WebApp中的某个地址,可以按下面的步骤做法: 获得另外一个WebApp的ServletConext对象(currentServletContext.getContext(uripath)). 调用ServletContext.getRequestDispatcher(String url)方法。

Created 31316-10-31 · Updated 31316-10-31 · 1 min · 48 words · -

servlet listener

servlet listener Listener是一种观察者模式的实现: 我们在web.xml中配置listener的时候就是把一个被观察者放入的观察者的观察对象队列中,当被观察者触发了注册事件时观察者作出相应的反应。在jsp/servlet中具体的实现是在web.xml中注册Listener,由Container在特定事件发生时呼叫特定的实现Listener的类。 总体上说servlet中有主要有3类事件既: Servlet上下文事件、 会话事件与请求事件总共有8个listener接口,我们在web.xml中注册时对应上自己对相应接口的实现类即可: Servlet中的Listener和Event: 在JSP 2.0/Servlet 2.4中,共有八个Listener接口,六个Event类别。 Listener接口 Event类 ServletContextListener ServletContextEvent ServletContextAttributeListener ServletContextAttributeEvent HttpSessionListener HttpSessionEvent HttpSessionActivationListener HttpSessionAttributeListener HttpSessionBindingEvent HttpSessionBindingListener ServletRequestListener ServletRequestEvent ServletRequestAttributeListener ServletRequestAttributeEvent 分别介绍: 1.ServletContextListener [接口方法] contextInitialized(), contextDestroyed() [接收事件] ServletContextEvent [触发场景] 在Container加载Web应用程序时 (例如启动 Container之后) ,会呼叫contextInitialized(),而当容器移除Web应用程序时,会呼叫contextDestroyed()方法。 2. ServletContextAttributeListener [接口方法] attributeAdded()、 attributeReplaced()、attributeRemoved() [接收事件] ServletContextAttributeEvent [触发场景] 若有对象加入为application (ServletContext) 对象的属性,则会呼叫attributeAdded(),同理在置换属性与移除属性时,会分别呼叫attributeReplaced()、attributeRemoved()。 3. HttpSessionListener [接口方法] sessionCreated(), sessionDestroyed () [接收事件] HttpSessionEvent [触发场景] 在session (HttpSession) 对象被创建或被消毁时,会分别调用这两个方法。 4. HttpSessionAttributeListener [接口方法] attributeAdded()、 attributeReplaced()、attributeRemoved() [接收事件] HttpSessionBindingEvent ...

Created 10106-06-10 · Updated 10106-06-10 · 1 min · 162 words · -

template for web.xml Servlet3.0

template for web.xml Servlet3.0 <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> </web-app> http://dominikdorn.com/2010/03/web-xml-web-fragment-xml-2-3-2-4-2-5-3-0/

Created 10106-06-10 · Updated 10106-06-10 · 1 min · 15 words · -

welcome-file-list

welcome-file-list 当用户在浏览器中输入的URL不包含某个servlet名或JSP页面时,welcome-file-list元素可指定显示的默认文件。 <!ELEMENT welcome-file-list (welcome-file+)> <!ELEMENT welcome-file (#PCDATA)> 举个例子说明,假设用户在浏览器的地址框中输入http://www.mycompany.com/appName/等地址。如果在Web应用的部署描述符中指定welcome-file-list元素,用户就会看到一个权限错误消息,或者是应用目录下的文件和目录列表。如果定义了welcome-file-list元素,用户就能看到由该元素指定的具体文件。 welcome-file子元素用于指定默认文件的名称。welcome-file-list元素可以包含一个或多个welcome-file子元素。如果在第一个welcome-file元素中没有找到指定的文件,Web容器就会尝试显示第二个,以此类推。 下面是一个包含welcome-file-list元素的部署描述符。该元素包含两个welcome-file元素: 第一个指定应用目录中的main.html文件,第二个定义jsp目录下的welcom.jsp文件,jsp目录也在应用目录下。 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <welcome-file-list> <welcome-file>main.html</welcome-file> <welcome-file>jsp/welcome.jsp</welcome-file> </welcome-file-list> </web-app> 如果用户键入的URL不包含servlet名称、JSP页面或其他资源,则不会在应用目录中找到main.html文件,这时就会显示jsp目录下的welcome.jsp文件。

Created 10106-06-10 · Updated 10106-06-10 · 1 min · 32 words · -

servlet init()

servlet init() init方法是在Servlet实例化之后执行的,并且只执行一次。 一.先说init(ServletConfig)中参数ServletConfig,代表的是配置信息。即在web.xml中配置的信息,比如: <servlet> <servlet-name>myfirstservlet</servlet-name> <servlet-class>as</servlet-class> <init-param> <param-name>name</param-name> <param-value>小明</param-value> </init-param> <init-param> <param-name>age</param-name> <param-value>25</param-value> </init-param> </servlet> 在程序中可以用this.getServletConfig()方法得到ServletConfig的实例,然后用ServletConfig的相应方法 可以得到ServletConfig的名字(getServletName)和配置参数的名字(getInitParameter(“name”))或者 名字枚举(getInitParameterNames()),并且通过参数名字得到相应的参数值。具体方法参见API。 二.再说说init方法,从源码中我们不难发现: Servlet接口里面只有init(ServletConfig),这是供tomcat调用的。GenericServlet类里面有成员变量ServletConfig,init(ServletConfig)方法和init()方法: private transient ServletConfig config; public void init(ServletConfig config) throws ServletException{ this.config=config; this.init(); } public void init() throws ServletException{ } 现在一切都很明了了,当容器(tomcat)帮忙调用init(ServletConfig config)并且给传过来一个参数config,这个方法把参数对象的引用指向类的成员变量this.config,并且调用类的 this.init()方法。有人问了,我们在写Servlet类时只要重写init(ServletConfig config)就可以了,init()不就成了多余的了吗?实际上init()方法是为了防止程序员在写Servlet类重写 init(ServletConfig config)时忘记写super.init(ServletConfig config),这样就容易造成出现空指针异常。而这就要求我们最好不要重写init(ServletConfig config),而要重写init()方法,就可以不写super。Servlet,你真是绕死人不偿命!

Created 30306-10-30 · Updated 30306-10-30 · 1 min · 48 words · -

servlet中init()和service()方法的区别

servlet中init()和service()方法的区别 首先要明确servlet的生命周期和HTTP协议. Serlvet接口只定义了一个服务方法就是service,而HttpServlet类实现了该方法并且要求调用下列的方法之一: doGet: 处理GET请求 doPost: 处理POST请求 当发出客户端请求的时候,调用service 方法并传递一个请求和响应对象。Servlet首先判断该请求是GET 操作还是POST 操作。然后它调用下面的一个方法: doGet 或 doPost。如果请求是GET就调用doGet方法,如果请求是POST就调用doPost方法。doGet和doPost都接受请求 (HttpServletRequest)和响应(HttpServletResponse)。 get和post这是http协议的两种方法,另外还有head, delete等 这两种方法有本质的区别,get只有一个流,参数附加在url后,大小个数有严格限制且只能是字符串。post的参数是通过另外的流传递的,不通过url,所以可以很大,也可以传递二进制数据,如文件的上传。 在servlet开发中,以doGet()和doPost()分别处理get和post方法。 另外还有一个doService(), 它是一个调度方法,当一个请求发生时,首先执行doService(),不管是get还是post。在HttpServlet这个基类中实现了一个角度, 首先判断是请求时get还是post,如果是get就调用doGet(), 如果是post就调用doPost()。你也可以直接过载doService()方法,这样你可以不管是get还是post。都会执行这个方法。 service()是在javax.servlet.Servlet接口中定义的, 在 javax.servlet.GenericServlet 中实现了这个接口, 而 doGet/doPost 则是在 javax.servlet.http.HttpServlet 中实现的, javax.servlet.http.HttpServlet 是 javax.servlet.GenericServlet 的子类. 所有可以这样理解, 其实所有的请求均首先由 service() 进行处理, 而在 javax.servlet.http.HttpServlet 的 service() 方法中, 主要做的事情就是判断请求类型是 Get 还是 Post, 然后调用对应的 doGet/doPost 执行. doGet: 处理GET请求 doPost: 处理POST请求 doPut: 处理PUT请求 doDelete: 处理DELETE请求 doHead: 处理HEAD请求 doOptions: 处理OPTIONS请求 doTrace: 处理TRACE请求 通常情况下,在开发基于HTTP的servlet时,开发者只需要关心doGet和doPost方法,其它的方法需要开发者非常的熟悉HTTP编程,因此 这些方法被认为是高级方法。 而通常情况下,我们实现的servlet都是从HttpServlet扩展而来。 doPut和doDelete方法允许开发者支持HTTP/1.1的对应特性; doHead是一个已经实现的方法,它将执行doGet但是仅仅向客户端返回doGet应该向客户端返回的头部的内容; doOptions方法自动的返回servlet所直接支持的HTTP方法信息; doTrace方法返回TRACE请求中的所有头部信息。 对于那些仅仅支持HTTP/1.0的容器而言,只有doGet, doHead 和 doPost方法被使用,因为HTTP/1 ...

Created 23236-10-23 · Updated 23236-10-23 · 2 min · 286 words · -