这部分主要是与Java Web和Web Service相关的面试题。
答: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技术。
- ServletConfig getServletConfig()
Web容器加载Servlet并将其实例化后,Servlet生命周期开始,容器运行其init()方法进行Servlet的初始化;请求到达时调用Servlet的service()方法,service()方法会根据需要调用与请求对应的doGet或doPost等方法;当服务器关闭或项目被卸载时服务器会将Servlet实例销毁,此时会调用Servlet的destroy()方法。
答:forward是容器中控制权的转向,是服务器请求资源,服务器直接访问目标地址的URL,把那个URL 的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。redirect就是服务器端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,因此从浏览器的地址栏中可以看到跳转后的链接地址,很明显redirect无法访问到服务器保护起来资源,但是可以从一个网站redirect到其他网站。forward更加高效,所以在满足需要时尽量使用forward(通过调用RequestDispatcher对象的forward()方法,该对象可以通过ServletRequest对象的getRequestDispatcher()方法获得),并且这样也有助于隐藏实际的链接;在有些情况下,比如需要访问一个其它服务器上的资源,则必须使用重定向(通过HttpServletResponse对象调用其sendRedirect()方法实现)。
- 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页面:
1 <%@ page pageEncoding="UTF-8"%> 2 <% 3 String path = request.getContextPath(); 4 String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; 5 %> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <base href="<%=basePath%>"> 11 <title>首页</title> 12 <style type="text/css"> 13 * { font-family: "Arial"; } 14 </style> 15 </head> 16 17 <body> 18 <h1>Hello, World!</h1> 19 <hr/> 20 <h2>Current time is: <%= new java.util.Date().toString() %></h2> 21 </body> 22 </html>
对应的Java代码:
1 /* 2 * Generated by the Jasper component of Apache Tomcat 3 * Version: Apache Tomcat/7.0.52 4 * Generated at: 2014-10-13 13:28:38 UTC 5 * Note: The last modified time of this file was set to 6 * the last modified time of the source file after 7 * generation to assist with modification tracking. 8 */ 9 package org.apache.jsp; 10 11 import javax.servlet.*; 12 import javax.servlet.http.*; 13 import javax.servlet.jsp.*; 14 15 public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase 16 implements org.apache.jasper.runtime.JspSourceDependent { 17 18 private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory 19 .getDefaultFactory(); 20 21 private static java.util.Map<java.lang.String, java.lang.Long> _jspx_dependants; 22 23 private javax.el.ExpressionFactory _el_expressionfactory; 24 private org.apache.tomcat.InstanceManager _jsp_instancemanager; 25 26 public java.util.Map<java.lang.String, java.lang.Long> getDependants() { 27 return _jspx_dependants; 28 } 29 30 public void _jspInit() { 31 _el_expressionfactory = _jspxFactory.getJspApplicationContext( 32 getServletConfig().getServletContext()).getExpressionFactory(); 33 _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory 34 .getInstanceManager(getServletConfig()); 35 } 36 37 public void _jspDestroy() { 38 } 39 40 public void _jspService( 41 final javax.servlet.http.HttpServletRequest request, 42 final javax.servlet.http.HttpServletResponse response) 43 throws java.io.IOException, javax.servlet.ServletException { 44 // 内置对象就是在这里定义的 45 final javax.servlet.jsp.PageContext pageContext; 46 javax.servlet.http.HttpSession session = null; 47 final javax.servlet.ServletContext application; 48 final javax.servlet.ServletConfig config; 49 javax.servlet.jsp.JspWriter out = null; 50 final java.lang.Object page = this; 51 javax.servlet.jsp.JspWriter _jspx_out = null; 52 javax.servlet.jsp.PageContext _jspx_page_context = null; 53 54 try { 55 response.setContentType("text/html;charset=UTF-8"); 56 pageContext = _jspxFactory.getPageContext(this, request, response, 57 null, true, 8192, true); 58 _jspx_page_context = pageContext; 59 application = pageContext.getServletContext(); 60 config = pageContext.getServletConfig(); 61 session = pageContext.getSession(); 62 out = pageContext.getOut(); 63 _jspx_out = out; 64 65 out.write(‘\r‘); 66 out.write(‘\n‘); 67 68 String path = request.getContextPath(); 69 String basePath = request.getScheme() + "://" 70 + request.getServerName() + ":" + request.getServerPort() 71 + path + "/"; 72 // 以下代码通过输出流将HTML标签输出到浏览器中 73 out.write("\r\n"); 74 out.write("\r\n"); 75 out.write("<!DOCTYPE html>\r\n"); 76 out.write("<html>\r\n"); 77 out.write(" <head>\r\n"); 78 out.write(" <base href=\""); 79 out.print(basePath); 80 out.write("\">\r\n"); 81 out.write(" <title>首页</title>\r\n"); 82 out.write(" <style type=\"text/css\">\r\n"); 83 out.write(" \t* { font-family: \"Arial\"; }\r\n"); 84 out.write(" </style>\r\n"); 85 out.write(" </head>\r\n"); 86 out.write(" \r\n"); 87 out.write(" <body>\r\n"); 88 out.write(" <h1>Hello, World!</h1>\r\n"); 89 out.write(" <hr/>\r\n"); 90 out.write(" <h2>Current time is: "); 91 out.print(new java.util.Date().toString()); 92 out.write("</h2>\r\n"); 93 out.write(" </body>\r\n"); 94 out.write("</html>\r\n"); 95 } catch (java.lang.Throwable t) { 96 if (!(t instanceof javax.servlet.jsp.SkipPageException)) { 97 out = _jspx_out; 98 if (out != null && out.getBufferSize() != 0)