面试二、Java Web 与 Web Service

二、Java Web  与  Web Service 
1、阐述 Servlet和 CGI的区别?  
 
答:Servlet 与CGI的区别在于Servlet 处于服务器进程中,它通过多线程方式运行其service()方
法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的
进程,服务完成后就销毁,所以效率上低于Servlet。 
补充:Sun Microsystems公司在1996年发布Servlet 技术就是为了和CGI进行竞争,Servlet 是一
个特殊的Java程序,一个基于Java 的 Web应用通常包含一个或多个Servlet 类。Servlet 不能够
自行创建并执行,它是在Servlet 容器中运行的,容器将用户的请求传递给Servlet 程序,并将
Servlet 的响应回传给用户。通常一个Servlet 会关联一个或多个JSP页面。以前CGI经常因为性
能开销上的问题被诟病,然而Fast CGI早就已经解决了CGI效率上的问题,所以面试的时候大
可不必信口开河的诟病CGI,事实上有很多你熟悉的网站都使用了CGI技术。  
2、Servlet接口中有哪些方法?  
 
答:Servlet 接口定义了5个方法,其中前三个方法与Servlet 生命周期相关:  
- void init(ServletConfig config) throws ServletException  
- void service(ServletRequest req, ServletResponse resp) throws ServletException, 
java.io.IOException  
- void destory()  
- java.lang.String getServletInfo()  
- ServletConfig getServletConfig() 
Web容器加载Servlet 并将其实例化后, Servlet 生命周期开始,容器运行其 init()方法进行Servlet
的初始化;请求到达时调用Servlet 的 service()方法,service()方法会根据需要调用与请求对应的
doGet 或doPost 等方法;当服务器关闭或项目被卸载时服务器会将Servlet 实例销毁,此时会调
用Servlet 的destroy()方法。 
3、转发(forward)和重定向(redirect)的区别?  
 
答:forward是容器中控制权的转向,是服务器请求资源,服务器直接访问目标地址的URL,把
那个URL  的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送
的内容是从哪儿来的,所以它的地址栏中还是原来的地址。redirect 就是服务器端根据逻辑,发
送一个状态码,告诉浏览器重新去请求那个地址,因此从浏览器的地址栏中可以看到跳转后的
链接地址,很明显redirect 无法访问到服务器保护起来资源,但是可以从一个网站redirect 到其
他网站。forward更加高效,所以在满足需要时尽量使用 forward(通过调用RequestDispatcher
对象的 forward()方法,该对象可以通过ServletRequest 对象的getRequestDispatcher()方法获得),
并且这样也有助于隐藏实际的链接;在有些情况下,比如需要访问一个其它服务器上的资源,
则必须使用重定向(通过HttpServletResponse 对象调用其sendRedirect()方法实现)。 
4、JSP有哪些内置对象?作用分别是什么?  
 
答:JSP有 9个内置对象:   
- request:封装客户端的请求,其中包含来自GET或POST请求的参数;  
- response:封装服务器对客户端的响应;  
- pageContext:通过该对象可以获取其他对象;  
- session:封装用户会话的对象;  
- application:封装服务器运行环境的对象;  
- out:输出服务器响应的输出流对象;  
- config:Web应用的配置对象;  
- page:JSP页面本身(相当于Java程序中的this);  
- exception:封装页面抛出异常的对象。 
补充:如果用Servlet 来生成网页中的动态内容无疑是非常繁琐的工作,另一方面,所有的文本
和HTML标签都是硬编码,即使做出微小的修改,都需要进行重新编译。JSP解决了Servlet 的
这些问题,它是Servlet 很好的补充,可以专门用作为用户呈现视图(View),而Servlet 作为控
制器(Controller)专门负责处理用户请求并转发或重定向到某个页面。基于Java的 Web开发很
多都同时使用了Servlet 和JSP。JSP页面其实是一个Servlet,能够运行Servlet 的服务器(Servlet
容器)通常也是JSP容器,可以提供 JSP页面的运行环境,Tomcat 就是一个Servlet/JSP容器。
第一次请求一个JSP页面时,Servlet/JSP容器首先将JSP页面转换成一个 JSP页面的实现类,
这是一个实现了JspPage接口或其子接口 HttpJspPage 的Java类。JspPage接口是Servlet 的子接
口,因此每个JSP页面都是一个Servlet。转换成功后,容器会编译Servlet 类,之后容器加载和
实例化Java字节码,并执行它通常对Servlet 所做的生命周期操作。对同一个JSP页面的后续请
求,容器会查看这个JSP页面是否被修改过,如果修改过就会重新转换并重新编译并执行。如
果没有则执行内存中已经存在的Servlet 实例。我们可以看一段JSP代码对应的 Java程序就知道
一切了,而且9个内置对象的神秘面纱也会被揭开。 
JSP页面: 
<%@ page pageEncoding="UTF-8"%> 
<% 
String path = request.getContextPath(); 
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.
getServerPort() + path + "/"; 
%> 
 
<!DOCTYPE html> 
<html> 
  <head> 
    <base href="<%=basePath%>"> 
    <title>首页</title> 
    <style type="text/css"> 
        * { font-family: "Arial"; }  
    </style> 
  </head> 
 
  <body> 
    <h1>Hello, World!</h1> 
    <hr/> 
    <h2>Current time is: <%= new java.util.Date().toString() %></h2> 
  </body> 
</html> 
对应的Java代码: 
/* 
 * Generated by the Jasper component of Apache Tomcat 
 * Version: Apache Tomcat/7.0.52 
 * Generated at: 2014-10-13 13:28:38 UTC 
 * Note: The last modified time of this file was set to 
 *       the last modified time of the source file after 
 *       generation to assist with modification tracking. 
 */ 
package org.apache.jsp; 
 
import javax.servlet.*; 
import javax.servlet.http.*; 
import javax.servlet.jsp.*; 
 
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase 
        implements org.apache.jasper.runtime.JspSourceDependent { 
 
    private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.J
spFactory 
            .getDefaultFactory(); 
 
    private static java.util.Map<java.lang.String, java.lang.Long> _jspx_dependants; 
 
    private javax.el.ExpressionFactory _el_expressionfactory; 
    private org.apache.tomcat.InstanceManager _jsp_instancemanager; 
 
    public java.util.Map<java.lang.String, java.lang.Long> getDependants() {  
        return _jspx_dependants; 
    } 
 
    public void _jspInit() { 
        _el_expressionfactory = _jspxFactory.getJspApplicationContext( 
                getServletConfig().getServletContext()).getExpressionFactory(); 
        _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory 
                .getInstanceManager(getServletConfig()); 
    } 
 
    public void _jspDestroy() { 
    } 
 
    public void _jspService( 
            final javax.servlet.http.HttpServletRequest request, 
            final javax.servlet.http.HttpServletResponse response) 
            throws java.io.IOException, javax.servlet.ServletException { 
        // 内置对象就是在这里定义的 
        final javax.servlet.jsp.PageContext pageContext; 
        javax.servlet.http.HttpSession session = null; 
        final javax.servlet.ServletContext application; 
        final javax.servlet.ServletConfig config; 
        javax.servlet.jsp.JspWriter out = null; 
        final java.lang.Object page = this; 
        javax.servlet.jsp.JspWriter _jspx_out = null; 
        javax.servlet.jsp.PageContext _jspx_page_context = null; 
 
        try { 
            response.setContentType("text/html;charset=UTF-8"); 
            pageContext = _jspxFactory.getPageContext(this, request, response, 
                    null, true, 8192, true); 
            _jspx_page_context = pageContext; 
            application = pageContext.getServletContext(); 
            config = pageContext.getServletConfig(); 
            session = pageContext.getSession(); 
            out = pageContext.getOut(); 
            _jspx_out = out; 
 
            out.write('\r');  
            out.write('\n'); 
 
            String path = request.getContextPath(); 
            String basePath = request.getScheme() + "://" 
                    + request.getServerName() + ":" + request.getServerPort() 
                    + path + "/"; 
// 以下代码通过输出流将HTML标签输出到浏览器中 
            out.write("\r\n"); 
            out.write("\r\n"); 
            out.write("<!DOCTYPE html>\r\n"); 
            out.write("<html>\r\n"); 
            out.write("  <head>\r\n"); 
            out.write("    <base href=\""); 
            out.print(basePath); 
            out.write("\">\r\n"); 
            out.write("    <title>首页</title>\r\n"); 
            out.write("    <style type=\"text/css\">\r\n"); 
            out.write("    \t* { font-family: \"Arial\"; }\r\n"); 
            out.write("    </style>\r\n"); 
            out.write("  </head>\r\n"); 
            out.write("  \r\n"); 
            out.write("  <body>\r\n"); 
            out.write("    <h1>Hello, World!</h1>\r\n"); 
            out.write("    <hr/>\r\n"); 
            out.write("    <h2>Current time is: "); 
            out.print(new java.util.Date().toString()); 
            out.write("</h2>\r\n"); 
            out.write("  </body>\r\n"); 
            out.write("</html>\r\n"); 
        } catch (java.lang.Throwable t) { 
            if (!(t instanceof javax.servlet.jsp.SkipPageException)) { 
                out = _jspx_out; 
                if (out != null && out.getBufferSize() != 0) 
                    try { 
                        out.clearBuffer(); 
                    } catch (java.io.IOException e) { 
                    } 
                if (_jspx_page_context != null) 
                    _jspx_page_context.handlePageException(t);  
                else 
                    throw new ServletException(t); 
            } 
        } finally { 
            _jspxFactory.releasePageContext(_jspx_page_context); 
        } 
    } 
} 
5、get和 post请求的区别?  
 
答:  
①get 请求用来从服务器上获得资源,而post是用来向服务器提交数据;  
②get 将表单中数据按照name=value的形式,添加到action  所指向的URL  后面,并且两者使用
"?"连接,而各个变量之间使用"&"连接;post 是将表单中的数据放在HTTP协议的请求头或消息
体中,传递到action所指向URL;  
③get 传输的数据要受到URL长度限制(1024 字节);而post 可以传输大量的数据,上传文件
通常要使用post 方式;  
④使用get 时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏
感数据还是应用使用post;  
⑤get 使用MIME类型application/x-www-form-urlencoded的URL编码(也叫百分号编码)文本
的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是"%20"。 
6、常用的 Web服务器有哪些?  
 
答:Unix和 Linux平台下使用最广泛的免费HTTP服务器是Apache服务器,而 Windows平台
的服务器通常使用IIS作为 Web服务器。选择 Web服务器应考虑的因素有:性能、安全性、日
志和统计、虚拟主机、代理服务器、缓冲服务和集成应用程序等。下面是对常见服务器的简介:  
- IIS: Microsoft的Web服务器产品,全称是Internet Information Services。 IIS是允许在公共Intranet
或Internet 上发布信息的 Web服务器。IIS是目前最流行的 Web服务器产品之一,很多著名的
网站都是建立在IIS的平台上。IIS提供了一个图形界面的管理工具,称为Internet 服务管理器,
可用于监视配置和控制Internet 服务。IIS是一种 Web服务组件,其中包括 Web服务器、FTP
服务器、NNTP服务器和SMTP服务器,分别用于网页浏览、文件传输、新闻服务和邮件发送 
等方面,它使得在网络(包括互联网和局域网)上发布信息成了一件很容易的事。它提供
ISAPI(Intranet Server API)作为扩展 Web服务器功能的编程接口;同时,它还提供一个Internet
数据库连接器,可以实现对数据库的查询和更新。  
- Kangle:Kangle Web服务器是一款跨平台、功能强大、安全稳定、易操作的高性能 Web服务
器和反向代理服务器软件。此外,Kangle 也是一款专为做虚拟主机研发的 Web服务器。实现虚
拟主机独立进程、独立身份运行。用户之间安全隔离,一个用户出问题不影响其他用户。支持
PHP、ASP、ASP.NET、Java、Ruby等多种动态开发语言。  
- WebSphere:WebSphere Application Server是功能完善、开放的 Web应用程序服务器,是IBM
电子商务计划的核心部分,它是基于Java的应用环境,用于建立、部署和管理Internet 和Intranet 
Web应用程序,适应各种 Web应用程序服务器的需要。  
- WebLogic:WebLogic Server是一款多功能、基于标准的 Web应用服务器,为企业构建企业应
用提供了坚实的基础。针对各种应用开发、关键性任务的部署,各种系统和数据库的集成、跨
Internet 协作等 Weblogic都提供了相应的支持。由于它具有全面的功能、对开放标准的遵从性、
多层架构、支持基于组件的开发等优势,很多公司的企业级应用都选择它来作为开发和部署的
环境。WebLogic Server在使应用服务器成为企业应用架构的基础方面一直处于领先地位,为构
建集成化的企业级应用提供了稳固的基础。  
- Apache:目前 Apache仍然是世界上用得最多的 Web服务器,其市场占有率很长时间都保持在
60%以上(目前的市场份额约40%左右)。世界上很多著名的网站都是 Apache的产物,它的成
功之处主要在于它的源代码开放、有一支强大的开发团队、支持跨平台的应用(可以运行在几
乎所有的Unix、Windows、Linux系统平台上)以及它的可移植性等方面。  
- Tomcat:Tomcat 是一个开放源代码、运行Servlet 和JSP的容器。Tomcat 实现了Servlet 和 JSP
规范。此外,Tomcat 还实现了 Apache-Jakarta规范而且比绝大多数商业应用软件服务器要好,
因此目前也有不少的 Web服务器都选择了Tomcat。  
- Nginx:读 作"engine x",是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP
代理服务器。  Nginx是由Igor Sysoev为俄罗斯访问量第二的Rambler站点开发的,第一个公开
版本0.1.0发布于2004年10月 4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、
丰富的功能集、示例配置文件和低系统资源的消耗而闻名。在2014年下半年,Nginx的市场份
额达到了14%。 
7、JSP和 Servlet是什么关系?  
 
答:其实这个问题在上面已经阐述过了, Servlet 是一个特殊的Java程序,它运行于服务器的 JVM
中,能够依靠服务器的支持向浏览器提供显示内容。JSP本质上是Servlet 的一种简易形式,JSP 
会被服务器处理成一个类似于Servlet 的Java 程序,可以简化页面内容的生成。Servlet 和 JSP最
主要的不同点在于,Servlet 的应用逻辑是在Java文件中,并且完全从表示层中的 HTML分离开
来。而JSP的情况是 Java和HTML可以组合成一个扩展名为.jsp的文件。有人说,Servlet 就是
在Java中写HTML,而 JSP就是在 HTML中写Java代码,当然这个说法是很片面且不够准确
的。 JSP侧重于视图, Servlet 更侧重于控制逻辑,在MVC架构模式中, JSP适合充当视图(view)
而Servlet 适合充当控制器(controller)。 
8、讲解 JSP中的四种作用域。  
 
答:JSP中的四种作用域包括page、request、session和application,具体来说:  
- page代表与一个页面相关的对象和属性。  
- request 代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,
涉及多个 Web组件;需要在页面显示的临时数据可以置于此作用域。  
- session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应
该放在用户自己的session中。  
- application代表与整个 Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,
包括多个页面、请求和会话的一个全局作用域。 
9、如何实现 JSP或 Servlet的单线程模式?  
 
答:  
对于JSP页面,可以通过page指令进行设置。 
<%@page isThreadSafe=”false”%> 
对于Servlet,可以让自定义的Servlet 实现SingleThreadModel标识接口。 
说明:如果将JSP或Servlet 设置成单线程工作模式,会导致每个请求创建一个Servlet 实例,这
种实践将导致严重的性能问题(服务器的内存压力很大,还会导致频繁的垃圾回收),所以通
常情况下并不会这么做。  
10、实现会话跟踪的技术有哪些?  
 
答:由于HTTP协议本身是无状态的,服务器为了区分不同的用户,就需要对用户会话进行跟
踪,简单的说就是为用户进行登记,为用户分配唯一的ID,下一次用户在请求中包含此ID,服
务器据此判断到底是哪一个用户。  
①URL  重写:在 URL中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到
URL结尾以标识一个会话。  
②设置表单隐藏域:将和会话跟踪相关的字段添加到隐式表单域中,这些信息不会在浏览器中
显示但是提交表单时会提交给服务器。  
这两种方式很难处理跨越多个页面的信息传递,因为如果每次都要修改URL或在页面中添加隐
式表单域来存储用户会话相关信息,事情将变得非常麻烦。  
③cookie:cookie有两种,一种是基于窗口的,浏览器窗口关闭后,cookie就没有了;另一种是
将信息存储在一个临时文件中,并设置存在的时间。当用户通过浏览器和服务器建立一次会话
后,会话ID就会随响应信息返回存储在基于窗口的cookie中,那就意味着只要浏览器没有关闭,
会话没有超时,下一次请求时这个会话ID又会提交给服务器让服务器识别用户身份。会话中可
以为用户保存信息。会话对象是在服务器内存中的,而基于窗口的cookie是在客户端内存中的。
如果浏览器禁用了cookie,那么就需要通过下面两种方式进行会话跟踪。当然,在使用cookie
时要注意几点:首先不要在cookie中存放敏感信息;其次cookie存储的数据量有限(4k),不
能将过多的内容存储cookie中;再者浏览器通常只允许一个站点最多存放20个 cookie。当然,
和用户会话相关的其他信息(除了会话ID)也可以存在cookie方便进行会话跟踪。  
④HttpSession:在所有会话跟踪技术中,HttpSession对象是最强大也是功能最多的。当一个用
户第一次访问某个网站时会自动创建HttpSession,每个用户可以访问他自己的HttpSession。可
以通过HttpServletRequest对象的getSession方法获得HttpSession,通 过HttpSession的setAttribute
方法可以将一个值放在HttpSession中,通过调用HttpSession对象的getAttribute方法,同时传
入属性名就可以获取保存在HttpSession中的对象。与上面三种方式不同的是,HttpSession放在
服务器的内存中,因此不要将过大的对象放在里面,即使目前的Servlet 容器可以在内存将满时
将HttpSession中的对象移到其他存储设备中,但是这样势必影响性能。添加到HttpSession中的
值可以是任意Java对象,这个对象最好实现了 Serializable接口,这样Servlet 容器在必要的时候
可以将其序列化到文件中,否则在序列化时就会出现异常。 
**补充:**HTML5中可以使用 Web Storage技术通过JavaScript 来保存数据,例如可以使用
localStorage和sessionStorage来保存用户会话的信息,也能够实现会话跟踪。  
11、过滤器有哪些作用和用法?  
 
答:  Java Web开发中的过滤器(filter)是从Servlet 2.3规范开始增加的功能,并在Servlet 2.4
规范中得到增强。对Web应用来说,过滤器是一个驻留在服务器端的 Web组件,它可以截取客
户端和服务器之间的请求与响应信息,并对这些信息进行过滤。当 Web容器接受到一个对资源
的请求时,它将判断是否有过滤器与这个资源相关联。如果有,那么容器将把请求交给过滤器
进行处理。在过滤器中,你可以改变请求的内容,或者重新设置请求的报头信息,然后再将请
求发送给目标资源。当目标资源对请求作出响应时候,容器同样会将响应先转发给过滤器,在
过滤器中你可以对响应的内容进行转换,然后再将响应发送到客户端。 
常见的过滤器用途主要包括:对用户请求进行统一认证、对用户的访问请求进行记录和审核、
对用户发送的数据进行过滤或替换、转换图象格式、对响应内容进行压缩以减少传输量、对请
求或响应进行加解密处理、触发资源访问事件、对XML的输出应用XSLT等。 
和过滤器相关的接口主要有:Filter、FilterConfig 和 FilterChain。 
编码过滤器的例子: 
import java.io.IOException; 
 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.annotation.WebFilter; 
import javax.servlet.annotation.WebInitParam; 
 
@WebFilter(urlPatterns = { "*" },  
        initParams = {@WebInitParam(name="encoding", value="utf-8")}) 
public class CodingFilter implements Filter { 
    private String defaultEncoding = "utf-8"; 
 
    @Override  
    public void destroy() { 
    } 
 
    @Override 
    public void doFilter(ServletRequest req, ServletResponse resp, 
            FilterChain chain) throws IOException, ServletException { 
        req.setCharacterEncoding(defaultEncoding); 
        resp.setCharacterEncoding(defaultEncoding); 
        chain.doFilter(req, resp); 
    } 
 
    @Override 
    public void init(FilterConfig config) throws ServletException { 
        String encoding = config.getInitParameter("encoding"); 
        if (encoding != null) { 
            defaultEncoding = encoding; 
        } 
    } 
} 
下载计数过滤器的例子: 
import java.io.File; 
import java.io.FileReader; 
import java.io.FileWriter; 
import java.io.IOException; 
import java.util.Properties; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.annotation.WebFilter; 
import javax.servlet.http.HttpServletRequest; 
  
@WebFilter(urlPatterns = {"/*"}) 
public class DownloadCounterFilter implements Filter { 
 
    private ExecutorService executorService = Executors.newSingleThreadExecutor(); 
    private Properties downloadLog; 
    private File logFile; 
 
    @Override 
    public void destroy() { 
        executorService.shutdown(); 
    } 
 
    @Override 
    public void doFilter(ServletRequest req, ServletResponse resp, 
            FilterChain chain) throws IOException, ServletException { 
        HttpServletRequest request = (HttpServletRequest) req; 
        final String uri = request.getRequestURI(); 
        executorService.execute(new Runnable() { 
 
            @Override 
            public void run() { 
                String value = downloadLog.getProperty(uri); 
                if(value == null) { 
                    downloadLog.setProperty(uri, "1"); 
                } 
                else { 
                    int count = Integer.parseInt(value); 
                    downloadLog.setProperty(uri, String.valueOf(++count)); 
                } 
                try { 
                    downloadLog.store(new FileWriter(logFile), ""); 
                }  
                catch (IOException e) { 
                    e.printStackTrace(); 
                } 
            } 
        }); 
        chain.doFilter(req, resp); 
    }  
 
    @Override 
    public void init(FilterConfig config) throws ServletException { 
        String appPath = config.getServletContext().getRealPath("/"); 
        logFile = new File(appPath, "downloadLog.txt"); 
        if(!logFile.exists()) { 
            try { 
                logFile.createNewFile(); 
            }  
            catch(IOException e) { 
                e.printStackTrace(); 
            } 
        } 
        downloadLog = new Properties(); 
        try { 
            downloadLog.load(new FileReader(logFile)); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
 
} 
说明:这里使用了Servlet 3规范中的注解来部署过滤器,当然也可以在web.xml中使用<filter>
和<filter-mapping>标签部署过滤器,如108题中所示。 
12、监听器有哪些作用和用法?  
 
答:Java Web开发中的监听器(listener)就是 application、session、request 三个对象创建、销毁
或者往其中添加修改删除属性时自动执行代码的功能组件,如下所示:  
①ServletContextListener:对Servlet 上下文的创建和销毁进行监听。  
②ServletContextAttributeListener:监听Servlet 上下文属性的添加、删除和替换。  
③HttpSessionListener:对Session的创建和销毁进行监听。 
补充:session的销毁有两种情况:1). session超时(可以在web.xml中通过
<session-config>/<session-timeout>标签配置超时时间);2). 通过调用session对象的 invalidate()
方法使session失效。  
④HttpSessionAttributeListener:对Session对象中属性的添加、删除和替换进行监听。  
⑤ServletRequestListener:对请求对象的初始化和销毁进行监听。  
⑥ServletRequestAttributeListener:对请求对象属性的添加、删除和替换进行监听。 
下面是一个统计网站最多在线人数监听器的例子。 
import javax.servlet.ServletContextEvent; 
import javax.servlet.ServletContextListener; 
import javax.servlet.annotation.WebListener; 
 
/** 
 上下文监听器,在服务器启动时初始化onLineCount和maxOnLineCount 两个变量 
 并将其置于服务器上下文(ServletContext)中,其初始值都是0 
*/ 
@WebListener 
public class InitListener implements ServletContextListener { 
 
    @Override 
    public void contextDestroyed(ServletContextEvent evt) { 
    } 
 
    @Override 
    public void contextInitialized(ServletContextEvent evt) { 
        evt.getServletContext().setAttribute("onLineCount", 0); 
        evt.getServletContext().setAttribute("maxOnLineCount", 0); 
    } 
 
} 
import java.text.DateFormat; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
 
import javax.servlet.ServletContext; 
import javax.servlet.annotation.WebListener; 
import javax.servlet.http.HttpSessionEvent; 
import javax.servlet.http.HttpSessionListener; 
 
/**  
 会话监听器,在用户会话创建和销毁的时候根据情况 
 修改 onLineCount和 maxOnLineCount的值 
*/ 
@WebListener 
public class MaxCountListener implements HttpSessionListener { 
 
    @Override 
    public void sessionCreated(HttpSessionEvent event) { 
        ServletContext ctx = event.getSession().getServletContext(); 
        int count = Integer.parseInt(ctx.getAttribute("onLineCount").toString()); 
        count++; 
        ctx.setAttribute("onLineCount", count); 
        int maxOnLineCount = Integer.parseInt(ctx.getAttribute("maxOnLineCount").toStrin
g()); 
        if (count > maxOnLineCount) { 
            ctx.setAttribute("maxOnLineCount", count); 
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
            ctx.setAttribute("date", df.format(new Date())); 
        } 
    } 
 
    @Override 
    public void sessionDestroyed(HttpSessionEvent event) { 
        ServletContext app = event.getSession().getServletContext(); 
        int count = Integer.parseInt(app.getAttribute("onLineCount").toString()); 
        count--; 
        app.setAttribute("onLineCount", count); 
    } 
} 
说明:这里使用了Servlet 3规范中的@WebListener注解配置监听器,当然你可以在web.xml 文
件中用<listener>标签配置监听器,如108题中所示。 
13、web.xml文件中可以配置哪些内容?  
 
答:web.xml用于配置 Web应用的相关信息,如:监听器(listener)、过滤器(filter)、  Servlet、
相关参数、会话超时时间、安全验证方式、错误页面等,下面是一些开发中常见的配置:  
①配置Spring上下文加载监听器加载Spring配置文件并创建IoC容器: 
  <context-param> 
     <param-name>contextConfigLocation</param-name> 
    <param-value>classpath:applicationContext.xml</param-value> 
  </context-param> 
 
  <listener> 
     <listener-class> 
       org.springframework.web.context.ContextLoaderListener 
     </listener-class> 
  </listener> 
②配置Spring 的OpenSessionInView过滤器来解决延迟加载和Hibernate会话关闭的矛盾: 
  <filter> 
      <filter-name>openSessionInView</filter-name> 
      <filter-class> 
         org.springframework.orm.hibernate3.support.OpenSessionInViewFilter 
      </filter-class> 
  </filter> 
 
  <filter-mapping> 
      <filter-name>openSessionInView</filter-name> 
      <url-pattern>/*</url-pattern> 
  </filter-mapping> 
③配置会话超时时间为10分钟: 
  <session-config> 
      <session-timeout>10</session-timeout> 
  </session-config> 
④配置404和Exception的错误页面: 
  <error-page> 
      <error-code>404</error-code> 
      <location>/error.jsp</location> 
  </error-page> 
  
  <error-page> 
      <exception-type>java.lang.Exception</exception-type> 
      <location>/error.jsp</location> 
  </error-page> 
⑤配置安全认证方式: 
  <security-constraint> 
      <web-resource-collection> 
          <web-resource-name>ProtectedArea</web-resource-name> 
          <url-pattern>/admin/*</url-pattern> 
          <http-method>GET</http-method> 
          <http-method>POST</http-method> 
      </web-resource-collection> 
      <auth-constraint> 
          <role-name>admin</role-name> 
      </auth-constraint> 
  </security-constraint> 
 
  <login-config> 
      <auth-method>BASIC</auth-method> 
  </login-config> 
 
  <security-role> 
      <role-name>admin</role-name> 
  </security-role> 
说明:对Servlet(小服务)、Listener(监听器)和 Filter(过滤器)等 Web组件的配置,Servlet 
3规范提供了基于注解的配置方式,可以分别使用@WebServlet、@WebListener、@WebFilter
注解进行配置。  
 
 
补充:如果Web提供了有价值的商业信息或者是敏感数据,那么站点的安全性就是必须考虑的
问题。安全认证是实现安全性的重要手段,认证就是要解决“Are you who you say you are?”的问
题。认证的方式非常多,简单说来可以分为三类:  
A. What you know? —  口令  
B. What you have? — 数字证书(U盾、密保卡)   
C. Who you are? —  指纹识别、虹膜识别  
在Tomcat 中可以通过建立安全套接字层(Secure Socket Layer, SSL)以及通过基本验证或表单
验证来实现对安全性的支持。 
14、你的项目中使用过哪些 JSTL标签?  
 
答:项目中主要使用了JSTL的核心标签库,包括<c:if>、<c:choose>、<c: when>、<c: otherwise>、
<c:forEach>等,主要用于构造循环和分支结构以控制显示逻辑。 
说明:虽然JSTL标签库提供了core、sql、fmt、xml等标签库,但是实际开发中建议只使用核
心标签库(core),而且最好只使用分支和循环标签并辅以表达式语言(EL),这样才能真正
做到数据显示和业务逻辑的分离,这才是最佳实践。 
15、使用标签库有什么好处?如何自定义 JSP标签?  
 
答:使用标签库的好处包括以下几个方面:  
-  分离JSP页面的内容和逻辑,简化了 Web开发;  
-  开发者可以创建自定义标签来封装业务逻辑和显示逻辑;  
-  标签具有很好的可移植性、可维护性和可重用性;  
-  避免了对Scriptlet(小脚本)的使用(很多公司的项目开发都不允许在JSP中书写小脚本) 
自定义JSP标签包括以下几个步骤:  
-  编写一个Java类实现实现Tag/BodyTag/IterationTag接口(开发中通常不直接实现这些接口而
是继承TagSupport/BodyTagSupport/SimpleTagSupport 类,这是对缺省适配模式的应用),重写
doStartTag()、doEndTag()等方法,定义标签要完成的功能  
-  编写扩展名为tld的标签描述文件对自定义标签进行部署,tld文件通常放在 WEB-INF文件夹
下或其子目录中  
-  在JSP页面中使用taglib指令引用该标签库 
下面是一个自定义标签库的例子。 
步骤1 -  标签类源代码TimeTag.java:  
package com.jackfrued.tags; 
 
import java.io.IOException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
 
import javax.servlet.jsp.JspException; 
import javax.servlet.jsp.JspWriter; 
import javax.servlet.jsp.tagext.TagSupport; 
 
public class TimeTag extends TagSupport { 
    private static final long serialVersionUID = 1L; 
 
    private String format = "yyyy-MM-dd hh:mm:ss"; 
    private String foreColor = "black"; 
    private String backColor = "white"; 
 
    public int doStartTag() throws JspException { 
         SimpleDateFormat sdf = new SimpleDateFormat(format); 
         JspWriter writer = pageContext.getOut(); 
         StringBuilder sb = new StringBuilder(); 
         sb.append(String.format("<span style='color:%s;background-color:%s'>%s</span>", 
             foreColor, backColor, sdf.format(new Date()))); 
         try { 
           writer.print(sb.toString()); 
         } catch(IOException e) { 
           e.printStackTrace(); 
         } 
         return SKIP_BODY; 
      } 
 
    public void setFormat(String format) { 
        this.format = format; 
    } 
 
    public void setForeColor(String foreColor) { 
        this.foreColor = foreColor; 
    } 
  
    public void setBackColor(String backColor) { 
        this.backColor = backColor; 
    } 
} 
步骤2 -  编写标签库描述文件 my.t ld: 
<?xml version="1.0" encoding="UTF-8" ?> 
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee  
    http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" 
    version="2.0"> 
 
    <description>定义标签库</description> 
    <tlib-version>1.0</tlib-version> 
    <short-name>MyTag</short-name> 
    <tag> 
        <name>time</name> 
        <tag-class>com.jackfrued.tags.TimeTag</tag-class> 
        <body-content>empty</body-content> 
        <attribute> 
            <name>format</name> 
            <required>false</required> 
        </attribute> 
        <attribute> 
            <name>foreColor</name> 
        </attribute> 
        <attribute> 
            <name>backColor</name> 
        </attribute> 
    </tag> 
</taglib> 
步骤3 -  在JSP页面中使用自定义标签: 
<%@ page pageEncoding="UTF-8"%> 
<%@ taglib prefix="my" uri="/WEB-INF/tld/my.tld" %> 
<% 
String path = request.getContextPath();  
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.
getServerPort() + path + "/"; 
%> 
 
<!DOCTYPE html> 
<html> 
  <head> 
    <base href="<%=basePath%>"> 
    <title>首页</title> 
    <style type="text/css"> 
        * { font-family: "Arial"; font-size:72px; } 
    </style> 
  </head> 
 
  <body> 
    <my:time format="yyyy-MM-dd" backColor="blue" foreColor="yellow"/> 
  </body> 
</html> 
提示:如果要将自定义的标签库发布成JAR文件,需要将标签库描述文件(tld文件)放在 JAR
文件的META-INF目录下,可以 JDK中的 jar 工具完成JAR文件的生成,如果不清楚如何操作,
可以请教谷老师和百老师。 
16、说一下表达式语言(EL)的隐式对象及其作用 
 
答:EL的隐式对象包括:pageContext、initParam(访问上下文参数)、param(访问请求参数)、
paramValues、header(访问请求头)、headerValues、cookie(访问 cookie)、applicationScope
(访问application作用域)、sessionScope(访问session作用域)、requestScope(访问request
作用域)、pageScope(访问page作用域)。 
用法如下所示: 
${pageContext.request.method} 
${pageContext["request"]["method"]} 
${pageContext.request["method"]} 
${pageContext["request"].method}  
${initParam.defaultEncoding} 
${header["accept-language"]} 
${headerValues["accept-language"][0]} 
${cookie.jsessionid.value} 
${sessionScope.loginUser.username} 
补充:表达式语言的.和[]运算作用是一致的,唯一的差别在于如果访问的属性名不符合Java 标
识符命名规则,例如上面的accept-language就不是一个有效的Java标识符,那么这时候就只能
用[]运算符而不能使用.运算符获取它的值 
17、表达式语言(EL)支持哪些运算符?  
 
答:除了.和[]运算符,EL还提供了:  
-  算术运算符:+、-、*、/或div、%或 mod  
-  关系运算符:==或eq、!=或 ne、>或gt、>=或ge、<或 lt、<=或 le  
-  逻辑运算符:&&或and、||或or、!或not  
-  条件运算符:${statement? A : B}(跟Java的条件运算符类似)  
- empty运算符:检查一个值是否为 null或者空(数组长度为0或集合中没有元素也返回true) 
18、Java Web开发的 Model 1和 Model 2分别指的是什么?  
 
答:Model 1是以页面为中心的Java Web开发,使用JSP+JavaBean技术将页面显示逻辑和业务
逻辑处理分开,JSP实现页面显示,JavaBean对象用来保存数据和实现业务逻辑。Model 2 是基
于MVC(模型-视图-控制器,Model-View-Controller)架构模式的开发模型,实现了模型和视图
的彻底分离,利于团队开发和代码复用,如下图所示。 
  
19、Servlet 3中的异步处理指的是什么?  
 
答:在Servlet 3中引入了一项新的技术可以让Servlet 异步处理请求。有人可能会质疑,既然都
有多线程了,还需要异步处理请求吗?答案是肯定的,因为如果一个任务处理时间相当长,那
么Servlet 或 Filter会一直占用着请求处理线程直到任务结束,随着并发用户的增加,容器将会
遭遇线程超出的风险,这这种情况下很多的请求将会被堆积起来而后续的请求可能会遭遇拒绝
服务,直到有资源可以处理请求为止。异步特性可以帮助应用节省容器中的线程,特别适合执
行时间长而且用户需要得到结果的任务,如果用户不需要得到结果则直接将一个Runnable对象
交给Executor并立即返回即可。 
补充:多线程在Java诞生初期无疑是一个亮点,而Servlet 单实例多线程的工作方式也曾为其赢
得美名,然而技术的发展往往会颠覆我们很多的认知,就如同当年爱因斯坦的相对论颠覆了牛
顿的经典力学一般。事实上,异步处理绝不是Serlvet 3首创,如果你了解Node.js的 话 ,对Servlet 
3的这个重要改进就不以为奇了。 
下面是一个支持异步处理请求的Servlet 的例子。 
import java.io.IOException; 
import javax.servlet.AsyncContext; 
import javax.servlet.ServletException; 
import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
@WebServlet(urlPatterns = {"/async"}, asyncSupported = true) 
public class AsyncServlet extends HttpServlet { 
    private static final long serialVersionUID = 1L; 
 
    @Override 
    public void doGet(HttpServletRequest req, HttpServletResponse resp)  
            throws ServletException, IOException { 
        // 开启Tomcat异步 Servlet支持 
        req.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true); 
 
        final AsyncContext ctx = req.startAsync();  // 启动异步处理的上下文 
        // ctx.setTimeout(30000); 
        ctx.start(new Runnable() {  
 
            @Override 
            public void run() { 
                // 在此处添加异步处理的代码 
 
                ctx.complete(); 
            } 
        }); 
    } 
} 
20、如何在基于 Java的 Web项目中实现文件上传和下载?  
 
答:在Sevlet 3 以前,Servlet API中没有支持上传功能的 API,因此要实现上传功能需要引入第
三方工具从POST请求中获得上传的附件或者通过自行处理输入流来获得上传的文件,我们推
荐使用 Apache的commons-fileupload。  
从Servlet 3开始,文件上传变得无比简单,相信看看下面的例子一切都清楚了。 
上传页面 index.jsp: 
<%@ page pageEncoding="utf-8"%> 
<!DOCTYPE html> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<title>Photo Upload</title> 
</head> 
<body> 
<h1>Select your photo and upload</h1> 
<hr/> 
<div style="color:red;font-size:14px;">${hint}</div> 
<form action="UploadServlet" method="post" enctype="multipart/form-data"> 
    Photo file: <input type="file" name="photo" /> 
    <input type="submit" value="Upload" /> 
</form> 
</body>  
</html> 
支持上传的Servlet: 
package com.jackfrued.servlet; 
 
import java.io.IOException; 
 
import javax.servlet.ServletException; 
import javax.servlet.annotation.MultipartConfig; 
import javax.servlet.annotation.WebServlet; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.Part; 
 
@WebServlet("/UploadServlet") 
@MultipartConfig 
public class UploadServlet extends HttpServlet { 
    private static final long serialVersionUID = 1L; 
 
    protected void doPost(HttpServletRequest request, 
            HttpServletResponse response) throws ServletException, IOException { 
        // 可以用request.getPart()方法获得名为photo的上传附件 
        // 也可以用 request.getParts()获得所有上传附件(多文件上传) 
        // 然后通过循环分别处理每一个上传的文件 
        Part part = request.getPart("photo"); 
        if (part != null && part.getSubmittedFileName().length() > 0) { 
            // 用ServletContext对象的 getRealPath()方法获得上传文件夹的绝对路径 
            String savePath = request.getServletContext().getRealPath("/upload"); 
            // Servlet 3.1 规范中可以用Part对象的getSubmittedFileName()方法获得上传的文件名 
            // 更好的做法是为上传的文件进行重命名(避免同名文件的相互覆盖) 
            part.write(savePath + "/" + part.getSubmittedFileName()); 
            request.setAttribute("hint", "Upload Successfully!"); 
        } else { 
            request.setAttribute("hint", "Upload failed!"); 
        } 
        // 跳转回到上传页面 
        request.getRequestDispatcher("index.jsp").forward(request, response);  
    } 
 
} 
21、服务器收到用户提交的表单数据,到底是调用 Servlet 的 doGet()还
是 doPost()方法?  
 
答: HTML的<form>元素有一个 method属性,用来指定提交表单的方式,其值可以是get 或post。
我们自定义的Servlet 一般情况下会重写doGet()或doPost()两个方法之一或全部,如果是GET请
求就调用doGet()方法,如果是POST请求就调用doPost()方法,那为什么为什么这样呢?我们
自定义的Servlet 通常继承自HttpServlet,HttpServlet 继承自GenericServlet 并重写了其中的
service()方法,这个方法是Servlet 接口中定义的。HttpServlet 重写的 service()方法会先获取用户
请求的方法,然后根据请求方法调用doGet()、doPost()、doPut()、doDelete()等方法,如果在自
定义Servlet 中重写了这些方法,那么显然会调用重写过的(自定义的)方法,这显然是对模板
方法模式的应用(如果不理解,请参考阎宏博士的《Java与模式》一书的第37章)。当然,自
定义Servlet 中也可以直接重写service()方法,那么不管是哪种方式的请求,都可以通过自己的
代码进行处理,这对于不区分请求方法的场景比较合适。 
22、JSP中的静态包含和动态包含有什么区别?  
 
答:静态包含是通过JSP的 include指令包含页面,动态包含是通过JSP标准动作<jsp:forward>
包含页面。静态包含是编译时包含,如果包含的页面不存在则会产生编译错误,而且两个页面
的"contentType"属性应保持一致,因为两个页面会合二为一,只产生一个class文件,因此被包
含页面发生的变动再包含它的页面更新前不会得到更新。动态包含是运行时包含,可以向被包
含的页面传递参数,包含页面和被包含页面是独立的,会编译出两个class文件,如果被包含的
页面不存在,不会产生编译错误,也不影响页面其他部分的执行。代码如下所示: 
<%-- 静态包含 --%> 
<%@ include file="..." %> 
 
<%-- 动态包含 --%> 
<jsp:include page="...">  
    <jsp:param name="..." value="..." /> 
</jsp:include> 
23、Servlet中如何获取用户提交的查询参数或表单数据?  
 
答:可以通过请求对象(HttpServletRequest)的getParameter()方法通过参数名获得参数值。如
果有包含多个值的参数(例如复选框),可以通过请求对象的getParameterValues()方法获得。
当然也可以通过请求对象的getParameterMap()获得一个参数名和参数值的映射(Map)。 
24、 Servlet中如何获取用户配置的初始化参数以及服务器上下文参数?  
 
答:可以通过重写Servlet 接口的 init(ServletConfig)方法并通过ServletConfig 对象的
getInitParameter()方法来获取Servlet 的初始化参数。可以通过ServletConfig对象的
getServletContext()方法获取ServletContext 对象,并通过该对象的getInitParameter()方法来获取
服务器上下文参数。当然,ServletContext 对象也在处理用户请求的方法(如doGet()方法)中通
过请求对象的getServletContext()方法来获得。 
25、如何设置请求的编码以及响应内容的类型?  
 
答:通过请求对象(ServletRequest)的setCharacterEncoding(String)方法可以设置请求的编码,
其实要彻底解决乱码问题就应该让页面、服务器、请求和响应、Java程序都使用统一的编码,
最好的选择当然是UTF-8;通过响应对象(ServletResponse)的 setContentType(String)方法可以
设置响应内容的类型,当然也可以通过HttpServletResponsed对象的setHeader(String, String)方法
来设置。 
说明:现在如果还有公司在面试的时候问JSP 的声明标记、表达式标记、小脚本标记这些内容
的话,这样的公司也不用去了,其实JSP内置对象、JSP指令这些东西基本上都可以忘却了,关
于Java Web开发的相关知识,可以看一下《Servlet&JSP思维导图》,上面有完整的知识点的罗
列。想了解如何实现自定义MVC框架的,可以看一下《Java Web自定义MVC框架详解》。  
26、解释一下网络应用的模式及其特点。  
 
答:典型的网络应用模式大致有三类:B/S、C/S、P2P。其中B代表浏览器(Browser)、C 代
表客户端(Client)、S代表服务器(Server),P2P是对等模式,不区分客户端和服务器。B/S
应用模式中可以视为特殊的C/S应用模式,只是将C/S应用模式中的特殊的客户端换成了浏览
器,因为几乎所有的系统上都有浏览器,那么只要打开浏览器就可以使用应用,没有安装、配
置、升级客户端所带来的各种开销。P2P应用模式中,成千上万台彼此连接的计算机都处于对
等的地位,整个网络一般来说不依赖专用的集中服务器。网络中的每一台计算机既能充当网络
服务的请求者,又对其它计算机的请求作出响应,提供资源和服务。通常这些资源和服务包括:
信息的共享和交换、计算资源(如CPU的共享)、存储共享(如缓存和磁盘空间的使用)等,
这种应用模式最大的阻力安全性、版本等问题,目前有很多应用都混合使用了多种应用模型,
最常见的网络视频应用,它几乎把三种模式都用上了。 
补充: 此题要跟"电子商务模式"区分开,因为有很多人被问到这个问题的时候马上想到的是B2B
(如阿里巴巴)、B2C(如当当、亚马逊、京东)、C2C(如淘宝、拍拍)、C2B(如威客)、
O2O(如美团、饿了么)。对于这类问题,可以去百度上面科普一下。 
27、什么是 Web Service(Web服务)?  
 
答:从表面上看,Web Service就是一个应用程序,它向外界暴露出一个能够通过Web进行调用
的 API。这就是说,你能够用编程的方法透明的调用这个应用程序,不需要了解它的任何细节,
跟你使用的编程语言也没有关系。例如可以创建一个提供天气预报的 Web Service,那么无论你
用哪种编程语言开发的应用都可以通过调用它的 API并传入城市信息来获得该城市的天气预
报。之所以称之为 Web Service,是因为它基于HTTP协议传输数据,这使得运行在不同机器上
的不同应用无须借助附加的、专门的第三方软件或硬件,就可相互交换数据或集成。 
补充:这里必须要提及的一个概念是SOA(Service-Oriented Architecture,面向服务的架构),
SOA是一种思想,它将应用程序的不同功能单元通过中立的契约联系起来,独立于硬件平台、
操作系统和编程语言,使得各种形式的功能单元能够更好的集成。显然,Web Service 是SOA
的一种较好的解决方案,它更多的是一种标准,而不是一种具体的技术。  
28、概念解释:SOAP、WSDL、UDDI。  
 
答:  
- SOAP:简单对象访问协议(Simple Object Access Protocol),是 Web Service中交换数据的一
种协议规范。  
- WSDL:Web服务描述语言(Web Service Description Language),它描述了 Web服务的公共
接口。这是一个基于XML的关于如何与 Web服务通讯和使用的服务描述;也就是描述与目录
中列出的 Web服务进行交互时需要绑定的协议和信息格式。通常采用抽象语言描述该服务支持
的操作和信息,使用的时候再将实际的网络协议和信息格式绑定给该服务。  
- UDDI:统一描述、发现和集成(Universal Description, Discovery and Integration),它是一个基
于XML的跨平台的描述规范,可以使世界范围内的企业在互联网上发布自己所提供的服务。简
单的说,UDDI是访问各种 WSDL的一个门面(可以参考设计模式中的门面模式)。 
提示:关于Web Service的相关概念和知识可以在 W3CSchool上找到相关的资料。 
29、Java规范中和 Web Service相关的规范有哪些?  
 
答:Java规范中和 Web Service相关的有三个:  
- JAX-WS(JSR 224):这个规范是早期的基于SOAP的 Web Service规范JAX-RPC的替代版本,
它并不提供向下兼容性,因为RPC样式的 WSDL以及相关的 API已经在 Java EE5中被移除了。
WS-MetaData是JAX-WS的依赖规范,提供了基于注解配置 Web Service和SOAP消息的相关
API。  
- JAXM(JSR 67):定义了发送和接收消息所需的 API,相当于Web Service的服务器端。  
- JAX-RS(JSR 311 & JSR 339 & JSR 370):是Java针对 REST(Representation State Transfer)架
构风格制定的一套 Web Service规范。REST是一种软件架构模式,是一种风格,它不像SOAP
那样本身承载着一种消息协议,  (两种风格的Web Service均采用了HTTP做传输协议,因为
HTTP协议能穿越防火墙, Java的远程方法调用(RMI)等是重量级协议,通常不能穿越防火墙),
因此可以将REST视为基于HTTP协议的软件架构。 REST中最重要的两个概念是资源定位和资
源操作,而HTTP协议恰好完整的提供了这两个点。HTTP协议中的URI可以完成资源定位,
而GET、POST、OPTION、DELETE方法可以完成资源操作。因此REST完全依赖HTTP协议
就可以完成 Web Service,而不像SOAP协议那样只利用了HTTP的传输特性,定位和操作都是 
由SOAP协议自身完成的,也正是由于SOAP 消息的存在使得基于SOAP的 Web Service显得笨
重而逐渐被淘汰。 
30、介绍一下你了解的 Java领域的 Web Service框架。  
 
答:Java领域的 Web Service框架很多,包括 Axis2(Axis 的升级版本)、Jersey(RESTful的
Web Service框架)、CXF(XFire的延续版本)、Hessian、Turmeric、JBoss SOA等,其中绝大
多数都是开源框架。 
提示:面试被问到这类问题的时候一定选择自己用过的最熟悉的作答,如果之前没有了解过就
应该在面试前花一些时间了解其中的两个,并比较其优缺点,这样才能在面试时给出一个漂亮
的答案。 
 
31、转发与重定向的区别   
转发:Servlet收到请求以后不去处理请求而是去调用服务器内部的其他资源处理请求 
重定向:Servlet 发送给浏览器一个特殊的响应,这个响应告诉浏览器再次向另一个地址发送请求。 
  转发  重定向 
请求的次数  1  2 
发起的位置  服务器  浏览器 
地址栏的改变  不改变  改变 
浏览器是否感知  否  是 
从数据共享上(区别):forword 是一个请求的延续,可以共享 request 作用域的数据。redirect 开启一个新的
请求,不可以共享request作用域的数据,但可以通过 URL 方式进行数据发送。 
从性能上(区别):forword性能要高于 redirect。(因为性能上有区别,在本系统中请求跳转建议使用 forword,
如果是跨域访问,建议使用 redirect。) 
32、session和 cookie的区别 
1、session是存储在服务器端,cookie 是存储在客户端的,所以从安全来讲session的安全性要比cookie高。 
2、单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie,而 session 是存
放在服务器的内存中,所以 session里的东西不断增加会造成服务器的负担,所以一般把很重要的信息才存储
在 session 中,而把一些次要东西存储在客户端的 cookie 里(例如将登陆信息等重要信息存放为 session,其他
信息如果需要保留,可以放在cookie) 
3.1、cookie 分为两大类分为会话cookie 和持久化cookie,会话cookie,存放在客户端浏览器的内存中,他的生
命周期和浏览器是一致的,浏览器关了会话cookie 也就消失了,而持久化cookie 是存放在客户端硬盘中,而
持久化cookie 的生命周期就是我们在设置cookie 时候设置的那个保存时间 
3.2、当浏览器关闭时session会不会丢失,session的信息是通过会话cookie 的 sessionid获取的,当浏览器关
闭的时候会话 cookie 消失,所以我们的 sessionid 也就消失了,但是 session 的信息还存在服务器端,这时我 
们只是查不到所谓的session但它并不是不存在。 
3.3、 session在什么情况下丢失,就是在服务器关闭的时候(也可以说说session的活化和钝化),或者是session
过期(默认时间是 30 分钟),再或者调用了 invalidate()的或者是我们想要 session 中的某一条数据消失调用
session.removeAttribute()方法 
3.4、 session在什么时候被创建呢,确切的说是通过调用getsession()来创建。访问HTML页面是不会创建session,
但是访问 index.JSP 时会创建session(JSP 实际上是一个 Servlet,Servlet 中有getSession方法)。 
33、如何防止表单重复提交 
针对于重复提交的整体解决方案: 
1.用 redirect(重定向)来解决重复提交的问题 
2.点击一次之后,按钮失效 
3.通过 loading(Loading 原理是在点击提交时,生成 Loading 样式,在提交完成之后隐藏该样式) 
4.自定义重复提交过滤器 
 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值