JaveEE 面试知识整理

2016/09/12 面试

介绍一些Jsp、Servlet的知识

1、Servlet接口五种方法介绍。

1.init()

在Servlet实例化后,Servlet 容器会调用 init() 方法来初始化该对象,主要是为了让 Servlet 对象在处理客户请求前可以完成一些初始化工作,例如:建立数据库的连接,获取配置信息等。对于每一个 Servlet 实例,init() 方法只能被调用一次。init() 方法有一个类型为ServletConfig的参数,Servlet 容器通过这个参数向 Servlet 传递配置信息。Servlet 使用 ServletConfig 对象从 Web 应用程序的配置信息中获取以名-值对形式提供的初始化参数。另外,在 Servlet 中,还可以通过 ServletConfig 对象获取描述 Servlet 运行环境的 ServletContext 对象,使用该对象,Servlet 可以和它的 Servlet 容器进行通信.

2.service()

容器调用 service() 方法来处理客户端的请求。要注意的是,在 service() 方法被容器调用之前,必须确保 init() 方法正确完成。容器会构造一个表示客户端请求信息的请求对象(类型为 ServletRequest)和一个用于对客户端进行响应的响应对象(类型为 ServletResponse)作为参数传递给 service()。在 service() 方法中,Servlet 对象通过 ServletRequest 对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用 ServletResponse 对象的方法设置响应信息.

3.destroy()

当容器检测到一个 Servlet 对象应该从服务中被移除的时候,容器会调用该对象的 destroy()方法,以便让Servlet对象可以释放它所使用的资源,保存数据到持久存储设备中,例如将内存中的数据保存到数据库中,关闭数据库的连接等。当需要释放内存或者容器关闭时,容器就会调用 Servlet 对象的 destroy() 方法,在 Servlet 容器调用 destroy() 方法前,如果还有其他的线程正在 service() 方法中执行容器会等待这些线程执行完毕或者等待服务器设定的超时值到达。一旦 Servlet 对象的 destroy() 方法被调用,容器不回再把请求发送给该对象。如果需要改 Servlet 再次为客户端服务,容器将会重新产生一个 Servlet 对象来处理客户端的请求。在 destroy() 方法调用之后,容器会释放这个 Servlet对象,在随后的时间内,该对象会被 java 的垃圾收集器所回收。

4.getServletConfig()

该方法返回容器调用 init() 方法时传递给 Servlet 对象的 ServletConfig 对象,ServletConfig 对象包含了 Servlet 的初始化参数。

5.getServletInfo()

返回一个 String 类型的字符串,其中包括了关于 Servlet 的信息,例如,作者、版本和版权。该方法返回的应该是纯文本字符串,而不是任何类型的标记。

2、转发(forward)和重定向(redirect)的区别?

  • forward 是服务器端行为, redirect 是客户端行为。
  • forward 是客户端一次 request 请求, redirect 是客户端两次 request 请求。
  • forward 不会刷新浏览器 URL 地址, redirect 会刷新浏览器 URL 地址, 显示的是当前页面的 URL。
  • forward 无法请求本服务外的资源, redirect 可以请求本服务器外的资源。
  • forward 跳转后要加上 return 语句, 因为页面跳转后还会执行跳转后面的语句。 redirect 则不需要。
  • forward 页面间可以共享 request 和 response 对象, redirect 页面间无法共享。
  • forward 比 redirect 的效率更高。

3、JSP有哪些内置对象?作用分别是什么?

  • request:代表了客户端的请求信息,其中包含来自GET或POST请求的参数;
  • response:代表服务器对客户端的响应;
  • pageContext:通过该对象可以获取其他对象;
  • session:由服务器自动创建的与用户请求相关的对象;
  • application:封装服务器运行环境的对象,可将信息保存在服务器中,直到服务器关闭,否则 application 对象中保存的信息会在整个应用中都有效。与 session 对象相比,application 对象生命周期更长,类似于系统的 “全局变量” ;
  • out:输出服务器响应的输出流对象,用于在 Web 浏览器内输出信息,并且管理应用服务器上的输出缓冲区;
  • config:Web应用的配置对象,主要作用是取得服务器的配置信息;
  • page:JSP页面本身(相当于Java程序中的this);
  • exception:封装页面抛出异常的对象,作用是显示异常信息,只有在包含 isErrorPage=”true” 的页面中才可以被使用,在一般的JSP页面中使用该对象将无法编译JSP文件。

4、Get 和 Post 的区别?

  1. 根据 HTTP 规范 Get 用于信息获取, 而且应该是安全和幂等的。没有副作用。 安全:指的是 Get 用于获取信息而非修改信息,即不会影响资源的状态。

    幂等: 指的是同一 URL 的多个请求应该返回同样的结果。但在实际中, 例如从新闻网站 Get 信息, 信息都是不同的,但也被认为是安全和幂等的,因为它总是返回当前的新闻。从根本上说,如果目标是当用户打开一个链接时,他可以确信从自身的角度来看没有改变资源即可。

  2. 根据 HTTP 规范,POST 表示可能修改变服务器上的资源的请求。是不幂等的, 有副作用。

  3. 在 HTML 中 Get 方式由于浏览器或服务器的限制,提交的数据长度有限。而理论上 Post 方式没有这个限制。

    注意:在 HTTP 协议中 Get 和 Post 方式长度并没有限制。

  4. Get 方式发送的数据附加在 URL 上, 而 Post 方式则是存储在 消息体(Body)中。

  5. Get 的请求,由于参数在 URL 中,刷新页面不会丢失,Post 刷新之后要重新提交。

注意:HTTP 是应用层协议, 不是传输协议。Get 和 Post 方式都是明文传输的, 都是不安全的。

5、Jsp 和 Servlet 的区别?

  • Jsp 的本质是 Servlet,Jsp 在第一次运行时会被编译成 Servlet。
  • Jsp 侧重的是页面的显示对应 MVC 模式中的 V(View)层。Servlet 侧重的是逻辑控制,对应 MVC 模式中的 C(Control)层。
  • Jsp 有9大内置对象, Servlet 没有。
  • Jsp 页面由 HTML代码 和 Jsp标签构成。Servlet 为纯 Java 代码。

6、实现会话跟踪的技术有哪些?

由于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 来保存用户会话的信息,也能够实现会话跟踪。

7、过滤器的作用和用法?

作用:

对 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";

    @Overridepublic void destroy() {
    }

    @Overridepublic void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        req.setCharacterEncoding(defaultEncoding);
        resp.setCharacterEncoding(defaultEncoding);
        chain.doFilter(req, resp);
    }

    @Overridepublic 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;

    @Overridepublic void destroy() {
        executorService.shutdown();
    }

    @Overridepublic void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        final String uri = request.getRequestURI();
        executorService.execute(new Runnable() {

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

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

}

8、监听器的作用和用法?

Java Web开发中的监听器(listener)就是 application、session、request 三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件,如下所示:

 ServletContextListener:对Servlet上下文的创建和销毁进行监听。 
 ServletContextAttributeListener:监听Servlet上下文属性的添加、删除和替换。 
 HttpSessionListener:对Session的创建和销毁进行监听。 

session 的销毁有两种情况:
1). session 超时(可以在web.xml中通过 / 标签配置超时时间);
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
*/@WebListenerpublic class InitListener implements ServletContextListener {@Overridepublic void contextDestroyed(ServletContextEvent evt) {
    }

    @Overridepublic 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的值
*/
@WebListenerpublic class MaxCountListener implements HttpSessionListener {@Overridepublic 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()));
        }
    }

    @Overridepublic void sessionDestroyed(HttpSessionEvent event) {
        ServletContext app = event.getSession().getServletContext();
        int count = Integer.parseInt(app.getAttribute("onLineCount").toString());
        count--;
        app.setAttribute("onLineCount", count);
    }
}

9、Web.xml 文件中可以配置那些内容?

  • 配置 Spring 上下文加载监听器、加载 Spring 配置文件并创建 Ioc 容器:
    <!-- 配置通用文件上下文路径 -->
	<!-- 定义了一个全局的上下文参数,参数定义一个全局的spring配置文件 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	<!--定义一个上下文监听器,当上下文加载的时候会自动加载上面的contextConfigLocation -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
  • 配置 Spring 分发器和字符过滤器:
    <!-- 配置SpringMVC核心的分发类 -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring-config.xml</param-value>
		</init-param>
		<!-- 容器初始化,Servlet被加载的优先级,如果值为负数或者不存在,则容器不会会自动加载 -->
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<!-- 这里可以为Servlet加上.do后缀 -->
		<!-- 注意这里不能加上/ 例如:/*.do -->
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<!-- spring提供的字符编码过滤器 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
  • 配置 JSTL :
    <!-- 引入jstl相关标签 -->
	<jsp-config>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
			<taglib-location>/WEB-INF/tld/fmt.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/fmt-rt</taglib-uri>
			<taglib-location>/WEB-INF/tld/fmt-rt.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
			<taglib-location>/WEB-INF/tld/c.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/core-rt</taglib-uri>
			<taglib-location>/WEB-INF/tld/c-rt.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/sql</taglib-uri>
			<taglib-location>/WEB-INF/tld/sql.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/sql-rt</taglib-uri>
			<taglib-location>/WEB-INF/tld/sql-rt.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/x</taglib-uri>
			<taglib-location>/WEB-INF/tld/x.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jstl/x-rt</taglib-uri>
			<taglib-location>/WEB-INF/tld/x-rt.tld</taglib-location>
		</taglib>
	</jsp-config>
  • 配置会话超过时间为 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)以及通过基本验证或表单验证来实现对安全性的支持。

10、你的项目中使用过哪些JSTL标签?

项目中主要使用了JSTL的核心标签库,包括<c:if>、<c:choose>、<c: when>、<c: otherwise>、<c:forEach>等,主要用于构造循环和分支结构以控制显示逻辑。

说明:虽然JSTL标签库提供了core、sql、fmt、xml等标签库,但是实际开发中建议只使用核心标签库(core),而且最好只使用分支和循环标签并辅以表达式语言(EL),这样才能真正做到数据显示和业务逻辑的分离,这才是最佳实践。

11、说一下表达式语言(EL)的隐式对象及其作用?

答:EL的隐式对象包括:pageContextinitParam(访问上下文参数)、param(访问请求参数)、paramValuesheader(访问请求头)、headerValuescookie(访问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 标识符,那么这时候就只能用 [ ] 运算符而不能使用.运算符获取它的值

12、表达式语言(EL)支持哪些运算符?

答:除了.和[]运算符,EL还提供了:

  • 算术运算符:+、-、*、/或div、%或mod
  • 关系运算符:==或eq、!=或ne、>或gt、>=或ge、<或lt、<=或le
  • 逻辑运算符:&&或and、||或or、!或not
  • 条件运算符:${statement? A : B}(跟Java的条件运算符类似)
  • empty运算符:检查一个值是否为null或者空(数组长度为0或集合中没有元素也返回true)

13、使用标签库有什么好处?如何自定义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.tld:

<?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><%@ 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>

14、Java Web开发的Model 1和Model 2分别指的是什么?

Model 1 是以页面为中心 Java Web 开发,使用 JSP+JavaBean 技术将页面显示逻辑和业务逻辑处理分开,JSP 实现页面显示,JavaBean对象用来保存数据和实现业务逻辑。Model 2 是基于 MVC(模型-视图-控制器,Model-View-Controller)架构模式的开发模型,实现了模型和视图的彻底分离,利于团队开发和代码复用。

Model 1 示例图

Model 1

Model 2 示例图

Model 2

15、JSP中的静态包含和动态包含有什么区别?

  • 静态包含使用: <%@ include file=” ”%> 是指令元素。动态包含使用: <jsp:include page=” ”/> 是行为元素。
  • 最终编译成java文件的数目不同。
    • 静态包含在转换成为java文件的时候将包含文件的内容“复制”到主体文件,然后作为一个整体编译。最终编译为一个java文件。
    • 动态包含是各个jsp文件分别转换,分别编译。最终编程成多个java文件。
  • 执行时间不同 静态包含发生在:JSP—->java文件阶段。 动态包含发生在:执行class文件阶段。动态加入。
  • 静态包含在两个文件中不能有相同的变量,动态包含允许。 由于静态包含相当于将包含文件内容直接复制到主体文件中,如果出现相同的变量,就会出现覆盖等问题,导致文件出错。而动态包含相当于调用不同的jsp,变量所在的空间不同,自然不会出现覆盖等现象。
  • 无论是动态包含还是静态包含,其request对象都是相同的。也就是同一个request对象。 静态包含最终编译成一个java文件,有一个request对象很好理解。而动态包含最终编译成多个jsp文件,为何会使用一个request对象呢?其实这些jsp组合的过程是一个请求转发的过程,自然也使用同一个request对象了。

总结:静态包含的是被包含页的代码,动态包含包含的是被包含页的结果。

16、Servlet中如何获取用户配置的初始化参数以及服务器上下文参数?

通过重写 Servlet 接口的 init(ServletConfig) 方法并通过 ServletConfig 对象的 getInitParameter() 方法来获取 Servlet 的初始化参数。可以通过 ServletConfig 对象的 getServletContext() 方法获取 ServletContext 对象,并通过该对象的 getInitParameter() 方法来获取服务器上下文参数。当然,ServletContext 对象也在处理用户请求的方法(如 doGet() 方法)中通过请求对象的 getServletContext() 方法来获得。

代码示例图片:

Servlet中获取用户配置的初始化参数

17、如何设置请求的编码以及响应内容的类型?

通过请求对象(ServletRequest)的 setCharacterEncoding(String) 方法可以设置请求的编码,其实要彻底解决乱码问题就应该让页面、服务器、请求和响应、Java程序都使用统一的编码,最好的选择当然是 UTF-8;通过响应对象(ServletResponse)的 setContentType(String) 方法可以设置响应内容的类型,当然也可以通过 HttpServletResponsed 对象的 setHeader(String, String) 方法来设置。

Search

    Post Directory