SERVLET

来源:互联网 发布:电影剧照 知乎 编辑:程序博客网 时间:2024/06/02 02:14

 

关于Servlet的话题

    Servlet是基于HTTP协议的运行在WEB服务器上的程序。它主要是接受来自网络的请求,并针对不同的请求作出不同的响应。

在这里要提到WEB容器的概念,我们常用的WEB容器有TOMCATJBOSS,其中TOMCAT是一个用JAVA语言编写的开源的WEB服务器,由她来控制 Servlet的生命周期.

    Servlet的生命周期分为四个阶段:

 1 创建Servlet对象:通过服务器反射机制来创建对象,默认情况下服务器接到第一次请求时才创建。

2调用Servlet对象的init()方法初始化Servlet的信息,init()方法只会在对象创建后调用一次

  3响应请求,Servlet接口的实现类HttpServlet及其子类通过调用service方法来实现对请求的处理。

    4Servlet对象的销毁,如果该对象长时间没有被调用或服务器关闭,调用destory()方法销毁Servlet对象。

    Servlet是单实例多线程的,即每个ServletWEB容器中只对应一个实例,当多个请求到达时服务器会为每一个请求启动一个线程,每个线程都会调用该对象的service方法,service方法依据HTTP的请求类型相应的调用doGet,doPost,doPut,doDlete对请求进行处理。

    Servlet处理表单提交数据的问题:

     1单个值的读取:读取表单的请求参数时只用调用HttpRequestgetParameter方法,不论是GET还是 POST发送的数据,都用同样的方式, Servlet都会自动使用恰当的方法读取。

     2多个值的读取:如果同一参数名在表单中出现多次(即对于多选框)则应调用getParametervalues方法返回字符串数组。

     3 参数名的查找:调用getParameterMap方法返回一个Map可以同时得到参数名和参数值,键是参数名,Map的值是参数值。

     4多字符集输入的读取:默认情况下request.getParameter方法使用服务器当前的编码方式输入,要改变服务器默认的编码,则要在访问任何请求参数之前调用HttpRequestsetCharacterEncoding或者先读取参数,在通过getBytes得到原始字节数据,通过

new String(“得到的字节数据”,“编码方式”)变成自己想要的编码方式:

     第一种方式的用法:

     request.setCharacterEncoding(“UTF-8”);

     String username=request.getParameter(“username”);

     第二种方式的用法:

     String usernameStr=request.getParameter(“username”);

     String  username=new String(“usernameStr”,”utf-8”);

    重定向(forward)和转发的区别(redirect):

    forward是服务器请求资源,服务器直接访问目标地址的URL,读取其中的响应内容,然后把这些内容再发给浏览器,地址栏中还是原来的地址,简单的说就是一个事物完成以后自动开始下一个事物。

    redirect是服务器告诉浏览器重新去请求访问过的那个地址,一般浏览器会用刚才请求的所有参数重新请求,可以从中获取Session,request参数。

注意的问题:如果应用重定向的用了转发,则可能用户一刷新页面,便回到上一个页面,而应该用转发的用了重定向,则无法通过Session,request获取参数。

面试题 - Servlet方面

75、说一说Servlet的生命周期?

:servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,servicedestroy方法表达。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGetdoPost)等,当服务器决定将实例销毁的时候调用其destroy方法。

cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet

76JAVA SERVLET APIforward() redirect()的区别?

:前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址;后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,前者更加高效,在前者可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用sendRedirect()方法。

77Servlet的基本架构

答:

public class ServletName extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response) throws

ServletException, IOException {

}

public void doGet(HttpServletRequest request, HttpServletResponse response) throws

ServletException, IOException {

}

}

78、什么情况下调用doGet()doPost()

答:Jsp页面中的form标签里的method属性为get时调用doGet(),为post时调用doPost()

79servlet的生命周期

答:web容器加载servlet,生命周期开始。通过调用servletinit()方法进行servlet的初始化。通过调用service()方法实现,根据请求的不同调用不同的do***()方法。结束服务,web容器调用servletdestroy()方法。

80、如何现实servlet的单线程模式

答:<%@ page isThreadSafe="false"%>

81、页面间对象传递的方法

答:requestsessionapplicationcookie

82JSPServlet有哪些相同点和不同点,他们之间的联系是什么?

答:JSPServlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"servlet"ServletJSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是JavaHTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,Servlet主要用于控制逻辑。

83、四种会话跟踪技术

答:会话作用域ServletsJSP 页面描述

page否是代表与一个页面相关的对象和属性。一个页面由一个编译好的 Java servlet 类(可以带有任何的 include 指令,但是没有 include 动作)表示。这既包括 servlet 又包括被编译成 servlet JSP 页面

request是是代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件(由于 forward 指令和 include 动作的关系)

session是是代表与用于某个 Web 客户机的一个用户体验相关的对象和属性。一个 Web 会话可以也经常会跨越多个客户机请求

application是是代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域

84Request对象的主要方法

答:

setAttribute(String name,Object):设置名字为namerequest的参数值

getAttribute(String name):返回由name指定的属性值

getAttributeNames():返回request对象所有属性的名字集合,结果是一个枚举的实例

getCookies():返回客户端的所有Cookie对象,结果是一个Cookie数组

getCharacterEncoding():返回请求中的字符编码方式

getContentLength():返回请求的Body的长度

getHeader(String name):获得HTTP协议定义的文件头信息

getHeaders(String name):返回指定名字的request Header的所有值,结果是一个枚举的实例

getHeaderNames():返回所以request Header的名字,结果是一个枚举的实例

getInputStream():返回请求的输入流,用于获得请求中的数据

getMethod():获得客户端向服务器端传送数据的方法

getParameter(String name):获得客户端传送给服务器端的有name指定的参数值

getParameterNames():获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例

getParameterValues(String name):获得有name指定的参数的所有值

getProtocol():获取客户端向服务器端传送数据所依据的协议名称

getQueryString():获得查询字符串

getRequestURI():获取发出请求字符串的客户端地址

getRemoteAddr():获取客户端的IP地址

getRemoteHost():获取客户端的名字

getSession([Boolean create]):返回和请求相关Session

getServerName():获取服务器的名字

getServletPath():获取客户端所请求的脚本文件的路径

getServerPort():获取服务器的端口号

removeAttribute(String name):删除请求中的一个属性

85、我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?

答:

Public String translate (String str) {

String tempStr = "";

try {

tempStr = new String(str.getBytes("ISO-8859-1"), "GBK");

tempStr = tempStr.trim();

}

catch (Exception e) {

System.err.println(e.getMessage());

}

return tempStr;

}

86Servlet执行时一般实现哪几个方法?

答:

public void init(ServletConfig config)

public ServletConfig getServletConfig()

public String getServletInfo()

public void service(ServletRequest request,ServletResponse response)

public void destroy()

cookie

9.1 Cookie概述

  Cookie是服务器发送给浏览器的体积很小的纯文本信息,用户以后访问同一个Web服务器时浏览器会把它们原样发送给服务器。通过让服务器读取它原先保存到客户端的信息,网站能够为浏览者提供一系列的方便,例如在线交易过程中标识用户身份、安全要求不高的场合避免用户重复输入名字和密码、门户网站的主页定制、有针对性地投放广告,等等。

  Cookie的目的就是为用户带来方便,为网站带来增值。虽然有着许多误传,事实上Cookie并不会造成严重的安全威胁。Cookie永远不会以任何方式执行,因此也不会带来病毒或攻击你的系统。另外,由于浏览器一般只允许存放300Cookie,每个站点最多存放20Cookie,每个Cookie的大小限制为4 KB,因此Cookie不会塞满你的硬盘,更不会被用作“拒绝服务”攻击手段。

   9.2 ServletCookie API

   要把Cookie发送到客户端,Servlet先要调用newCookie(name,value)用合适的名字和值创建一个或多个Cookie2.1节),通过cookie.setXXX设置各种属性(2.2节),通过response.addCookie(cookie)cookie加入应答头(2.3节)。

  要从客户端读入CookieServlet应该调用request.getCookies()getCookies()方法返回一个Cookie对象的数组。在大多数情况下,你只需要用循环访问该数组的各个元素寻找指定名字的Cookie,然后对该Cookie调用getValue方法取得与指定名字关联的值,这部分内容将在2.4节讨论。

   9.2.1 创建Cookie

   调用Cookie对象的构造函数可以创建CookieCookie对象的构造函数有两个字符串参数:Cookie名字和Cookie值。名字和值都不能包含空白字符以及下列字符:

[ ] ( ) = , " / ? @ : ;

   9.2.2 读取和设置Cookie属性

   Cookie加入待发送的应答头之前,你可以查看或设置Cookie的各种属性。下面摘要介绍这些方法:

getComment/setComment

获取/设置Cookie的注释。

getDomain/setDomain

获取/设置Cookie适用的域。一般地,Cookie只返回给与发送它的服务器名字完全相同的服务器。使用这里的方法可以指示浏览器把Cookie返回给同一域内的其他服务器。注意域必须以点开始(例如.sitename.com),非国家类的域(如.com.edu.gov)必须包含两个点,国家类的域(如.com.cn.edu.uk)必须包含三个点。

getMaxAge/setMaxAge

获取/设置Cookie过期之前的时间,以秒计。如果不设置该值,则Cookie只在当前会话内有效,即在用户关闭浏览器之前有效,而且这些Cookie不会保存到磁盘上。参见下面有关LongLivedCookie的说明。

getName/setName

获取/设置Cookie的名字。本质上,名字和值是我们始终关心的两个部分。由于HttpServletRequestgetCookies方法返回的是一个Cookie对象的数组,因此通常要用循环来访问这个数组查找特定名字,然后用getValue检查它的值。

getPath/setPath

获取/设置Cookie适用的路径。如果不指定路径,Cookie将返回给当前页面所在目录及其子目录下的所有页面。这里的方法可以用来设定一些更一般的条件。例如,someCookie.setPath("/"),此时服务器上的所有页面都可以接收到该Cookie

getSecure/setSecure

获取/设置一个boolean值,该值表示是否Cookie只能通过加密的连接(即SSL)发送。

getValue/setValue

获取/设置Cookie的值。如前所述,名字和值实际上是我们始终关心的两个方面。不过也有一些例外情况,比如把名字作为逻辑标记(也就是说,如果名字存在,则表示true)。

getVersion/setVersion

获取/设置Cookie所遵从的协议版本。默认版本0(遵从原先的Netscape规范);版本1遵从RFC 2109 但尚未得到广泛的支持。

   9.2.3 在应答头中设置Cookie

   Cookie可以通过HttpServletResponseaddCookie方法加入到Set-Cookie应答头。下面是一个例子:

Cookie userCookie = new Cookie("user", "uid1234");

response.addCookie(userCookie);

   9.2.4 读取保存到客户端的Cookie

   要把Cookie发送到客户端,先要创建Cookie,然后用addCookie发送一个Set-CookieHTTP应答头。这些内容已经在上面的2.1节介绍。从客户端读取Cookie时调用的是HttpServletRequestgetCookies方法。该方法返回一个与HTTP请求头中的内容对应的Cookie对象数组。得到这个数组之后,一般是用循环访问其中的各个元素,调用getName检查各个Cookie的名字,直至找到目标Cookie。然后对这个目标Cookie调用getValue,根据获得的结果进行其他处理。

  上述处理过程经常会遇到,为方便计下面我们提供一个getCookieValue方法。只要给出Cookie对象数组、Cookie名字和默认值,getCookieValue方法就会返回匹配指定名字的Cookie值,如果找不到指定Cookie,则返回默认值。

   9.3 几个Cookie工具函数

   下面是几个工具函数。这些函数虽然简单,但是,在和Cookie打交道的时候很有用。

   9.3.1 获取指定名字的Cookie

  该函数是ServletUtilities.java的一部分。getCookieValue通过循环依次访问Cookie对象数组的各个元素,寻找是否有指定名字的Cookie,如找到,则返回该Cookie的值;否则,返回参数中给出的默认值。getCookieValue能够在一定程度上简化Cookie值的提取。

public static String getCookieValue(Cookie[] cookies,

String cookieName,

String defaultValue) {

for(int i=0; icookies.length; i++) {

Cookie cookie = cookies;

if (cookieName.equals(cookie.getName()))

return(cookie.getValue());

}

return(defaultValue);

}

 

   9.3.2自动保存的Cookie

   下面是LongLivedCookie类的代码。如果你希望Cookie能够在浏览器退出的时候自动保存下来,则可以用这个LongLivedCookie类来取代标准的Cookie类。

package hall;

import javax.servlet.http.*;

public class LongLivedCookie extends Cookie {

public static final int SECONDS_PER_YEAR = 60*60*24*365;

public LongLivedCookie(String name, String value) {

super(name, value);

setMaxAge(SECONDS_PER_YEAR);

}

}

   9.4.实例:定制的搜索引擎界面

  下面也是一个搜索引擎界面的例子,通过修改前面HTTP状态代码的例子得到。在这个Servlet中,用户界面是动态生成而不是由静态HTML文件提供的。Servlet除了负责读取表单数据并把它们发送给搜索引擎之外,还要把包含表单数据的Cookie发送给客户端。以后客户再次访问同一表单时,这些Cookie的值将用来预先填充表单,使表单自动显示最近使用过的数据。

   SearchEnginesFrontEnd.java

  该Servlet构造一个主要由表单构成的用户界面。第一次显示的时候,它和前面用静态HTML页面提供的界面差不多。然而,用户选择的值将被保存到Cookie(本页面将数据发送到CustomizedSearchEnginesServlet,由后者设置Cookie)。用户以后再访问同一页面时,即使浏览器是退出之后再启动,表单中也会自动填好上一次搜索所填写的内容。

  注意该Servlet用到了ServletUtilities.java,其中getCookieValue前面已经介绍过,headWithTitle用于生成HTML页面的一部分。另外,这里也用到了前面已经说明的LongLiveCookie类,我们用它来创建作废期限很长的Cookie

package hall;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import java.net.*;

 

public class SearchEnginesFrontEnd extends HttpServlet {

public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

Cookie[] cookies = request.getCookies();

String searchString =

ServletUtilities.getCookieValue(cookies,

"searchString",

"Java Programming");

String numResults =

ServletUtilities.getCookieValue(cookies,

"numResults",

"10");

String searchEngine =

ServletUtilities.getCookieValue(cookies,

"searchEngine",

"google");

response.setContentType("text/html");

PrintWriter out = response.getWriter();

String title = "Searching the Web";

out.println(ServletUtilities.headWithTitle(title) +

"BODY BGCOLOR="#FDF5E6">\n" +

"H1 ALIGN="CENTER"Searching the Web/H1>\n" +

"n" +

"FORM ACTION="/servlet/hall.CustomizedSearchEngines">\n" +

"CENTER>\n" +

"Search String:n" +

"INPUT TYPE="TEXT" NAME="searchString"n" +

" VALUE="" + searchString + ""><BR>\n" +

"Results to Show Per Page:n" +

"INPUT TYPE="TEXT" NAME="numResults"n" +

" VALUE=" + numResults + " SIZE=3><BR>\n" +

"INPUT TYPE="RADIO" NAME="searchEngine"n" +

" VALUE="google"" +

checked("google", searchEngine) + ">\n" +

"Google |n" +

"INPUT TYPE="RADIO" NAME="searchEngine"n" +

" VALUE="infoseek"" +

checked("infoseek", searchEngine) + ">\n" +

"Infoseek |n" +

"INPUT TYPE="RADIO" NAME="searchEngine"n" +

" VALUE="lycos"" +

checked("lycos", searchEngine) + ">\n" +

"Lycos |n" +

"INPUT TYPE="RADIO" NAME="searchEngine"n" +

" VALUE="hotbot"" +

checked("hotbot", searchEngine) + ">\n" +

"HotBotn" +

"BR>\n" +

"INPUT TYPE="SUBMIT" VALUE="Search">\n" +

"/CENTER>\n" +

"/FORM>\n" +

"n" +

"/BODY>\n" +

"/HTML>\n");

}

 

private String checked(String name1, String name2) {

if (name1.equals(name2))

return(" CHECKED");

else

return("");

}

}

 

CustomizedSearchEngines.java

前面的SearchEnginesFrontEnd Servlet把数据发送到CustomizedSearchEnginesServlet。本例在许多方面与前面介绍HTTP状态代码时的例子相似,区别在于,本例除了要构造一个针对搜索引擎的URL并向用户发送一个重定向应答之外,还要发送保存用户数据的Cookies

package hall;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import java.net.*;

public class CustomizedSearchEngines extends HttpServlet {

public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

String searchString = request.getParameter("searchString");

Cookie searchStringCookie =

new LongLivedCookie("searchString", searchString);

response.addCookie(searchStringCookie);

searchString = URLEncoder.encode(searchString);

String numResults = request.getParameter("numResults");

Cookie numResultsCookie =

new LongLivedCookie("numResults", numResults);

response.addCookie(numResultsCookie);

String searchEngine = request.getParameter("searchEngine");

Cookie searchEngineCookie =

new LongLivedCookie("searchEngine", searchEngine);

response.addCookie(searchEngineCookie);

SearchSpec[] commonSpecs = SearchSpec.getCommonSpecs();

for(int i=0; icommonSpecs.length; i++) {

SearchSpec searchSpec = commonSpecs;

if (searchSpec.getName().equals(searchEngine)) {

String url =

searchSpec.makeURL(searchString, numResults);

response.sendRedirect(url);

return;

}

}

response.sendError(response.SC_NOT_FOUND,

"No recognized search engine specified.");

}

 

public void doPost(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

}

 

原创粉丝点击