设为首页 收藏本站
查看: 991|回复: 0

[经验分享] Java程序员面试题集(116-135)

[复制链接]

尚未签到

发表于 2017-2-19 10:28:34 | 显示全部楼层 |阅读模式
  摘要:这一部分讲解基于Java的Web开发相关面试题,即便在Java走向没落的当下,基于Java的Web开发因为拥有非常成熟的解决方案,仍然被广泛应用。不管你的Web开发中是否使用框架,JSP和Servlet都是一个必备的基础,在面试的时候被问到的概率还是很高的。
  
  116、说出Servlet的生命周期,并说出Servlet和CGI的区别?
  答:Web 容器加载Servlet并将其实例化后,Servlet生命周期开始,容器运行其init()方法进行Servlet的初始化;请求到达时调用 Servlet的service方法,service方法会调用与请求对应的doGet或doPost等方法;当服务器关闭会项目被卸载时服务器会将 Servlet实例销毁,此时会调用Servlet的destroy方法。Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线 程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI 对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于Servlet。
  【补 充1】SUN公司在1996年发布Servlet技术就是为了和CGI进行竞争,Servlet是一个特殊的Java程序,一个基于Java的Web应用 通常包含一个或多个Servlet类。   Servlet不能够自行创建并执行,它是在Servlet容器中运行的,容器将用户的请求传递给Servlet程序,此外将Servlet的响应回传给 用户。通常一个Servlet会关联一个或多个JSP页面。以前CGI经常因为性能开销上的问题被诟病,然而Fast CGI早就已经解决了CGI效率上的问题,所以面试的时候大可不必诟病CGI,腾讯的网站就使用了CGI技术,相信你也没感觉它哪里不好。
  【补充2】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()

  117、转发(forward)和重定向(redirect)的区别?
  答:forward 是容器中控制权的转向,是服务器请求资源,服务器直接访问目标地址的URL,把那个URL 的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。redirect就 是服务器端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,因此从浏览器的地址栏中可以看到跳转后的链接地址。前者更加高效,在前者可以满足需 要时,尽量使用转发(通过RequestDispatcher对象的forward方法,RequestDispatcher对象可以通过 ServletRequest对象的getRequestDispatcher方法获得),并且,这样也有助于隐藏实际的链接;在有些情况下,比如,需要 跳转到一个其它服务器上的资源,则必须使用重定向(通过HttpServletResponse对象调用其sendRedirect方法)。
  
  118、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页面:



[html] view plaincopy DSC0000.jpg DSC0001.jpg

  • <%@ 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代码:



[java] view plaincopy

  • /*
  • * 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.JspFactory  
  •             .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 {  
  • // 9个内置对象就是在这里定义的  
  •         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);
  •         }
  •     }
  • }
  
  119、get和post请求的区别?
  答:
  ①get请求用来从服务器上获得资源,而post是用来向服务器提交数据;
  ②get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,并且两者使用“?”连接,而各个变量之间使用“&”连接;post是将表单中的数据放在HTML头部(header),传递到action所指向URL;
  ③get传输的数据要受到URL长度限制(1024字节);而post可以传输大量的数据,上传文件只能使用post方式;
  ④使用get时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏感数据还是应用使用post;
  ⑤get使用MIME类型application/x-www-form-urlencoded的URL 编码(URL encoding,也叫百分号编码)文本的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是"%20"。
  
  120、常用的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:BEA WebLogic Server是一种多功能、基于标准的Web应用服务器,为企业构建自己的应用提供了坚实的基础。各种应用开发、部署所有关键性的任务,无论是集成各种系 统和数据库,还是提交服务、跨Internet协作,Weblogic都提供了相应的支持。由于它具有全面的功能、对开放标准的遵从性、多层架构、支持基 于组件的开发,基于Internet的企业都选择它来开发、部署最佳的应用。BEA WebLogic Server在使应用服务器成为企业应用架构的基础方面一直处于领先地位,为构建集成化的企业级应用提供了稳固的基础,它们以 Internet的容量和速度,在连网的企业之间共享信息、提交服务,实现协作自动化。
  • Apache:目前Apache仍然是世界上用得最多的Web服务器,市场占有率约为60%左右。世界上很多著名的网站都是Apache的产物,它的成功之处主要在于它的源代码开放、有一支强大的开发团队、支持跨平台的应用(可以运行在几乎所有的Unix、Windows、Linux系统平台上)以及它的可移植性等方面。
  • Tomcat:Tomcat 是一个开放源代码、运行Servlet和JSP的容器。TomcatServer实现了Servlet和JSP规范。此外,Tomcat还实现了 Apache-Jakarta规范而且比绝大多数商业应用软件服务器要好,因此目前也有不少的Web服务器都选择了Tomcat。
  • Nginx:读作"engine x",是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。 Nginx是由Igor Sysoev为俄罗斯访问量第二的 Rambler.ru站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。
  
  121、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)。
  
  122、JSP中的四种作用域?
  答:page、request、session和application,具体如下:
  ①page 代表与一个页面相关的对象和属性。
  ②request 代表与Web客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个Web 组件;需要在页面显示的临时数据可以置于此作用域
  ③session代表与某个用户与服务器建立的一次会话相关的对象和属性。跟某个用户相关的数据应该放在用户自己的session中
  ④application代表与整个Web应用程序相关的对象和属性,它实质上是跨越整个Web应用程序,包括多个页面、请求和会话的一个全局作用域。
  
  123、如何实现JSP或Servlet的单线程模式?
  答:



[html] view plaincopy

  • <%@page isThreadSafe=”false”%>  
【补充】Servlet默 认的工作模式是单实例多线程,如果Servlet实现了标识接口SingleThreadModel又或是JSP页面通过page指令设置 isThreadSafe属性为false,那么它们生成的Java代码会以单线程多实例方式工作。显然,这样做会导致每个请求创建一个Servlet实 例,这种实践将导致严重的性能问题。  
  124、实现会话跟踪的技术有哪些?
  答:由于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容 器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。
  
  126、过滤器有哪些作用和用法?
  答:  Java Web开发中的过滤器(filter)是从Servlet 2.3规范开始增加的功能,并在Servlet  2.4规范中得到增强。对Web应用来说,过滤器是一个驻留在服务器端的Web组件,它可以截取客户端和服务器之间的请求与响应信息,并对这些信息进行过 滤。当Web容器接受到一个对资源的请求时,它将判断是否有过滤器与这个资源相关联。如果有,那么容器将把请求交给过滤器进行处理。在过滤器中,你可以改 变请求的内容,或者重新设置请求的报头信息,然后再将请求发送给目标资源。当目标资源对请求作出响应时候,容器同样会将响应先转发给过滤器,再过滤器中, 你可以对响应的内容进行转换,然后再将响应发送到客户端。
  常见的过滤器用途主要包括:对用户请求进行统一认证、对用户的访问请求进行记录和审核、对用户发送的数据进行过滤或替换、转换图象格式、对响应内容进行压缩以减少传输量、对请求或响应进行加解密处理、触发资源访问事件、对XML的输出应用XSLT等。
  和过滤器相关的接口主要有:Filter、FilterConfig、FilterChain
  编码过滤器的例子:



[java] view plaincopy

  • package com.lovo.filter;  

  • 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;
  •         }
  •     }
  • }
  下载计数过滤器:



[java] view plaincopy

  • package com.accp.filter;  

  • 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();
  •         }
  •     }

  • }
  127、监听器有哪些作用和用法?
  答:Java Web开发中的监听器(listener)就是application、session、request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件,如下所示:
  ①ServletContextListener:对Servlet上下文的创建和销毁进行监听。
  ②ServletContextAttributeListener:监听Servlet上下文属性的添加、删除和替换。
  ③HttpSessionListener:对Session的创建和销毁进行监听。
  补 充:session的销毁有两种情况:1session超时(可以在web.xml中通过<session- config>/<session-timeout>标签配置超时时间);2通过调用session对象的invalidate()方 法使session失效。
  ④HttpSessionAttributeListener:对Session对象中属性的添加、删除和替换进行监听。
  ⑤ServletRequestListener:对请求对象的初始化和销毁进行监听。
  ⑥ServletRequestAttributeListener:对请求对象属性的添加、删除和替换进行监听。
  下面是一个统计网站最多在线人数及时间的监听器:
  上下文监听器,在上下文中放置onLineCount和maxOnLineCount属性,初始值为0



[java] view plaincopy

  • package com.lovo.listeners;  

  • import javax.servlet.ServletContextEvent;  
  • import javax.servlet.ServletContextListener;  
  • import javax.servlet.annotation.WebListener;  

  • @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);  
  •     }

  • }
  会话监听器,监听到会话创建时判断是否达到最大在线人数并记录时间



[java] view plaincopy

  • package com.lovo.listeners;  

  • 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;  

  • @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").toString());  
  •         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);  
  •     }
  • }
  【注意】这里使用注解@WebListener配置该监听器,当然你可以在web.xml文件中用<listener>标签配置监听器,如下题所示。

128、web.xml 的作用?  答:用于配置Web应用的相关信息,如:监听器(listener)、过滤器(filter)、 Servlet、相关参数、会话超时时间、安全验证方式、错误页面等。例如:
  ①配置Spring上下文加载监听器加载Spring配置文件:




[html] view plaincopy

  • <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会话关闭的矛盾:




[html] view plaincopy

  • <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分钟:




[html] view plaincopy

  • <session-config>  
  •   <session-timeout>10</session-timeout>  
  • </session-config>  

④配置404和Exception的错误页面:




[html] view plaincopy

  • <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>  

⑤配置安全认证方式:




[html] view plaincopy

  • <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>  
  【补 充1】从Servlet  3开始,可以不用在web.xml中部署Servlet(小服务)、Filter(过滤器)、Listener(监听器)等Web组件,Servlet  3提供了基于注解的部署方式,可以分别使用@WebServlet、@WebFilter、@WebListener三个部署小服务、过滤器、监听器。
【补充2】如果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)以及通过基本验证或表单验证来实现对安全性的支持。
  
  129、你的项目中使用过哪些JSTL标签?
  答: 项目中主要使用了JSTL的核心标签库,包括<c:if>、<c:choose>、<c:  when>、<c: otherwise>、<c:forEach>等,主要用于构造循环和分支结构以控制显示逻辑。
  【说明】虽然JSTL标签库提供了core、sql、fmt、xml等标签库,但是实际开发中建议只使用核心标签库(core),而且最好只使用分支和循环标签并辅以表达式语言(EL),这样才能真正做到数据显示和业务逻辑的分离,这才是最佳实践。
  
  130、使用标签库有什么好处?如何自定义JSP标签?
  答:使用标签库的好处包括以下几个方面:

  • 分离JSP页面的内容和逻辑,简化了Web开发;
  • 开发者可以创建自定义标签来封装业务逻辑和显示逻辑;
  • 标签具有很好的可移植性、可维护性和可重用性;
  • 避免了对Scriptlet(小脚本)的使用(很多公司的项目开发都不允许在JSP中书写小脚本)
  自定义JSP标签包括以下几个步骤:

  • 编写一个Java类实现实现Tag/BodyTag/IterationTag接口(通常不直接实现这些接口而是继承TagSupport/BodyTagSupport/SimpleTagSupport类,这是对适配器模式中缺省适配模式的应用)
  • 重写doStartTag()、doEndTag()等方法,定义标签要完成的功能
  • 编写扩展名为tld的标签描述文件对自定义标签进行部署,tld文件通常放在WEB-INF文件夹或其子目录
  • 在JSP页面中使用taglib指令引用该标签库
  下面是一个例子:
  标签类源代码



[java] view plaincopy

  • package com.lovo.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;%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;  
  •     }
  • }
标签库描述文件(该文件通常放在WEB-INF目录或其子目录下)


[html] view plaincopy

  • <?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.lovo.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>  
JSP页面


[html] view plaincopy

  • <%@ 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>  
  运行结果
   DSC0002.jpg

  【注意】如果要将自定义的标签库发布成JAR文件,需要将标签库描述文件(tld文件)放在JAR文件的META-INF目录下,可以JDK自带的jar工具完成JAR文件的生成,如果不清楚如何操作,可以请教谷老师(各位亲,点击这里真的可以使用用谷歌)和百老师。
  
  131、表达式语言(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标识符,那么这时候就只能用[]运算符而不能使用.获取它的值
  132、表达式语言(EL)支持哪些运算符?
  答:除了.和[]运算符,EL还提供了:

  • 算术运算符:+、-、*、/或div、%或mod
  • 关系运算符:==或eq、!=或ne、>或gt、>=或ge、<或lt、<=或le
  • 逻辑运算符:&&或and、||或or、!或not
  • 条件运算符:${statement? A : B}(跟Java的条件运算符类似)
  • empty运算符:检查一个值是否为null或者空(数组长度为0或集合中没有元素也返回true)
  133、Java Web开发的Model 1和Model 2分别指的是什么?
  答:Model 1是以页面为中心的Java Web开发,只适合非常小型的应用程序,Model 2是基于MVC架构模式的应用,这一点在前文的面试题中已经详细讲解过了。
  

  

  134、Servlet 3中的异步处理指的是什么?
  答: 在Servlet  3中引入了一项新的技术可以让Servlet异步处理请求。有人可能会质疑,既然都有多线程了,还需要异步处理请求吗?答案是肯定的,因为如果一个任务处 理时间相当长,那么Servlet或Filter会一直占用着请求处理线程直到任务结束,随着并发用户的增加,容器将会遭遇线程超出的风险,这这种情况下 很多的请求将会被堆积起来而后续的请求可能会遭遇拒绝服务,直到有资源可以处理请求为止。异步特性可以帮助应用节省容器中的线程,特别适合执行时间长而且 用户需要得到结果的任务,如果用户不需要得到结果则直接将一个Runnable对象交给Executor(如果不清楚请查看前文关于多线程和线程池的部 分)并立即返回即可。
  【补充】多线程在Java诞生初期无疑是一个亮点,而Servlet单实例多线程的工作方式也曾为其赢得美名,然而技术的发展往往会颠覆我们很多的认知,就如同当年爱因斯坦的相对论颠覆了牛顿的经典力学一般。事实上,异步处理绝不是Serlvet 3首创,如果你了解Node.js的话,对Servlet  3的这个重要改进就不以为奇了。
  下面是一个支持异步处理请求的Servlet的例子:



[java] view plaincopy

  • package com.lovo.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();
  •             }
  •         });
  •     }
  • }
  135、如何在基于Java的Web项目中实现文件上传和下载?
  答:(稍后呈现,我准备用HTML5写一个带进度条的客户端,然后再用Servlet 3提供的文件上传支持来做一个多文件上传的例子)
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-344137-1-1.html 上篇帖子: jboss eap 6.3 域(Domain)模式配置 下篇帖子: 怎么做性能测试--响应时间
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表