Java Web基础:JSP与Servlet

作者:陆金龙    发表时间:2022-04-05 16:34   

关键词Servlet, Tomcat, JSP, Listener, Filter, WebSocket

    本文内容主要来源于李刚《轻量级Java EE 企业应用实战--Structs2+Spring4+Hibernate》一书的第2章 JSP/Servlet及相关技术详解。本文对相关内容要点进行了整理。

1.部署在Tomcat下的Java Web应用文件结构

1.1 Web应用文件结构简介

<webappName> 

|--WEB-INF

|          |--classes   

|          |--lib

|          |--web.xml

|--<index.jsp>  --此处可存放多个JSP页面

webappName为web应用的名称,Tomcat的webapps路径下该应用的文件夹。这里可以根据需要命名文件夹。

classes和lib两个文件夹都是保存Web应用所需的Java类文件。其中classes保存单个*.class文件,lib保存打包后的JAR包文件。。

web.xml文件为配置描述符。从Servlet3.0开始,可通过注解来配置管理Web组件,因此web.xml可以变得更加简洁。

与WEB-INF同级的*.jsp是一个或多个JSP页面文件。

1.2 web.xml配置内容

  • 配置JSP和JSP属性
  • 配置和管理Servlet
  • 配置和管理Listener
  • 配置管理Filter
  • 配置标签库
  • 配置和管理JAAS授权认证
  • 配置管理资源引用
  • 配置Web应用首页

web.xml文件的根元素是<web-app .../>元素。web.xml文件中配置首页使用welcome-flle-list元素,例如:

<welcome-flle-list>

    <welcome-file> index.html</welcome-file>

   <welcome-file> index.jsp</welcome-file>

</welcome-flle-list>

2.JSP的基本原理

Servlet原理:用户向指定的Serlvet发送请求时,Servlet利用输出流动态生成HTML页面。

JSP的本质是Servlet(一个特殊的Java类),JSP页面由系统编译成Servlet,Servlet再负责响应用户请求。

JSP通过在标准的HTML页面中嵌入Java代码,其静态内容部分无须开发者通过Java程序,动态部分内容使用Java脚本控制。这样页面布局、色彩、图像等静态文本、格式与表现逻辑不用耦合在Java代码中,简化Servlet的开发。

JSP页面经过Tomcat编译后是一个继承HttpJspBase的类,HttpJspBase是HttpServlet子类。HttpServlet 指能够处理 HTTP 请求的 servlet,它在原有 Servlet 接口上添加了一些与 HTTP 协议处理方法,它比 Servlet 接口的功能更为强大(HttpServlet 扩展了GenericServlet,而GenericServlet实现了Servlet 接口)。

JSP页面经过Tomcat编译后的类主要包含__jspInit(),__jspDestroy(),__jspService(HTTPServletRequest,HTTPServletResponse)三个方法。对应的Servlet中是init、destroy、service三个方法。

JSP的4种基本语法:

(1)JSP注释 <%--注释内容--%>

(2)JSP声明 <%! 这里是声明部分,包括变量和方法 %>

(3)输出JSP表达式 <%=表达式 %>

(4)JSP脚本 <% java脚本代码 %>

JSP的3个编译指令:

(1)page:针对当前页面的指令,包括language、import、contentType、info、errorPage等。

(2)include:用于指定包含另一个页面可以是静态页面或JSP页面(被包含的页面不需要是完整的页面)。

(3)taglib:用户定义和访问自定义标签。

JSP的7个动作指令:

(1)jsp:forword:执行页面转向。客户端请求地址不变,客户端请求参数不会丢失。

(2)jsp:param:用于传递参数,与其他支持参数的标签一起使用。

(3)jsp:include:用于动态引入一个JSP页面。

(4)jsp:plugin:用于下载javaBean或Applet到客户端执行。

(5)jsp:useBean:创建一个JavaBean的实例。

(6)jsp:setProperty:设置JavaBean实例的属性值。

(7)jsp:getProperty:输出JavaBean实例的属性值。

JSP脚本中的9个内置对象:

(1)application:javax.servlet.ServletContext 的实例,整个web应用(只要服务端不重启,贯彻web应用运行的整个生命周期)。application可通过setAttribute和getAttribute实现多个JSP、Servlet共享数据,通过getInitParameter获得web应用的配置参数。

(2)config:javax.servlet.ServletConfig 的实例。该对象更多的在Servlet中有效。通过getInitParameter获取配置信息。

(3)exception:java.lang.Throwable的实例,在错误页中代表其他页面的异常和错误。常用的有getClass、getMessage方法。

(4)out:javax.servlet.jsp.jspWriter的实例,JSP页面的输出流。out.printlin("content")输出内容。

(5)page:代表页面本身,也就是servlet中的this。

(6)pageContext:javax.servlet.jsp.PageContext的实例,JSP页面上下文。通过getAttribute可以访问page 、request、session、application范围的变量,通过setAttribute将指定变量放入page 、request、session、application范围内。默认范围为page。

(7)request:javax.servlet.http.HttpServletRequest的实例。封装了客户端的一次请求(可以涉及多个JSP页面或Servlet)。可以获取请求头(getHeader、getHeaderNames、getHeaders),获取请求参数(getParameter、getParameterMap、getParameterNames、getParameterValues),操作request范围的属性(setAttribute、getAttribute),执行forword或include(例如执行forword:getRequestDispatcher("a.jsp").forword(request,response))。

(8)response:javax.servlet.http.HttpServletResponse的实例,代表服务器对客户端的响应。可生成字符或非字符响应,重定向、增加Cookie。

(9)session:javax.servlet.http.HttpSession的实例,代表一次会话(可以包含先后多次请求)。操作session范围的属性(setAttribute、getAttribute)

3.Servlet介绍

Servlet是个特殊的Java类,必须继承HttpServlet。

Servlet提供的响应客户端请求的主要方法:doGet、doPost、doPut、doDelete。重写service方法则可以响应客户端的所有请求。还包含init、destroy两个方法,用来初始化资源和回收资源。

Servlet的配置

为了让Servlet能响应用户请求,需要将Servlet配置在web.xml中进行配置。

<servlet>
         <!-- servlet的内部名称,自定义 -->
        <servlet-name>HelloServlet</servlet-name>
        <!-- servlet的类全名:包名+类名 -->
        <servlet-class>com.mycompany.controller.HelloServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
</servlet>
<!-- servlet的映射配置 -->
<servlet-mapping>
        <!-- servlet的内部名称,一定要和上面的内部名称保持一致 -->
        <servlet-name>HelloServlet</servlet-name>
        <!-- servlet的映射路径(访问serclet的名称 -->
        <url-pattern>/hello</url-pattern>
</servlet-mapping>
 
可以通过init-param为servlet配置初始化参数。在service方法中通过getServletConfig()获取配置类对象,通过getInitParameter方法获取初始化参数。

使用Servlet作为控制器

直接使用Servlet生成表现出页面时,页面所有的HTML标签都要采用Servlet的输出流来输出,开发效率非常低。

自MVC规范出现后,Servlet的责任开始明确下来,仅仅作为控制器使用。

控制器负责接收客户端的请求,它既不直接对客户端输出响应,也不处理用户请求。只调用JavaBean来处理用户请求,Servlet根据处理结果调用不同的JSP页面向浏览器呈现处理结果。

4.Filter介绍

Filter主要用于用户请求的预处理和对HttpServletResponse进行后处理,是个典型的处理链。

Filter的作用:在HttpServletRequest到达Servlet之前,进行拦截,可以修改HttpServletRequest的请求头和数据。在HttpServletResponse到达客户端之前,进行拦截,可以修改HttpServletResponse的响应头和数据。Filter可以拦截多个请求或响应。

应用场景有用户授权的Filter、日志Filter等。

创建Filter的2个步骤:1)创建Filter处理类实现javax.servlet.Filter接口,2)在web.xml中配置Filter。

javax.servlet.Filter接口定义了以下3个方法:

void init(FilterConfig config);

void destroy();

void doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain);

通过chain.doFilter(request,response)将请求放行到目的地址。通常在chain.doFilter之前进行请求预处理,在chain.doFilter之后进行响应执行后的处理。

Filter的配置示例:


<filter>
  <filter-name>filterLog</filter-name>
  <filter-class>com.mycompany.filter.filterLog</filter-class>
</filter>
<filter-mapping>
  <filter-name>filterLog</filter-name>
  <url-pattern>/*</url-pattern>
  <!-- /*是对所有的文件进行拦截 -->
</filter-mapping>

5.Listener

5.1 Web事件监听器简介

Web应用在Web容器中运行时,发生的事件包括:Web应用启动、Web应用停止、用户Session开始、用户Session结束、用户请求到达等。

使用Listener的2个步骤:1)创建Listener实现类,2)通过注解或在web.xml中配置Listener。

常用的Web事件监听器接口有以下几个:

ServletContextListener:监听Web应用的启动和关闭。

ServletContextAttributeListener:监听ServletContext范围(application)内属性的改变。

HttpSessionListener:监听用户Session的开始和结束。

HttpSessionAttributeListener:监听HttpSession范围(session)内属性的改变。

ServletRequestListener:监听用户请求。

ServletRequestAttributeListener:监听ServletRequest范围(request)内属性的改变。

5.2 Listener的配置

方式一:使用@WebListener修饰Listener实现类。

方式二:web.xml配置中Listener:

<listener>

    <listener-class>com.mycompany.AppListener</listener-class>

</listener>

5.3 Web事件监听器接口说明

ServletContextListener2个方法: contextInitialized(ServletContextEvent sce)、contextDestroyed(ServletContextEvent sce)

ServletContextAttributeListener:attributeAdded(ServletContextAttributeEvent event)、attributeRemoved(ServletContextAttributeEvent event)、attributeReplaced(ServletContextAttributeEvent event)

ServletRequestListener2个方法:contextInitialized(ServletRequestEvent sre)、contextDestroyed(ServletRequestEvent sre)。

ServletRequestAttributeListener3个方法:attributeAdded(ServletRequestAttributeEvent event)、attributeRemoved(ServletRequestAttributeEvent event)、attributeReplaced(ServletRequestAttributeEvent event)。

HttpSessionListener2个方法: sessionCreated(HttpSessionEvent se)、sessionDestroyed(HttpSessionEvent se)

HttpSessionAttributeListener3个方法:attributeAdded、attributeRemoved、attributeReplaced。

6.Serlvet3.x特性

6.1基于注解的配置

使用注解配置取代web.xml配置。

Servlet3 .0在javax.servlet.annotation包下提供了以下注解:

@WebServlet、@MutipartConfig:修饰Servlet类,取代web.xml中对Servlet的配置。

@WebFilter:修饰Filter类,取代web.xml中对Filter的配置。

@WebInitParam:用于与@WebServlet和@WebFilter一起使用,为Servlet和Filter配置参数。

@WebListener:修饰Listener类。

@ServletSecurity、@HttpConstraint、@HttpMethodConstraint:与JAAS有关的注解,修饰Servlet,指定其安全与授权控制。

6.2 增加了web模块支持

Web模块要在META-INF目录下添加一个web-fragment.xml文件,Web模块部署描述符。

<webmoduleName> 

|--META-INF

|           |--web-fragment.xml

|--Web模块所使用的类文件、资源文件

6.3 增加了异步处理

通过ServletRequest的AsyncContext startAsync()或AsyncContext startAsync(ServletRequest,ServletResponse)方法开启异步调用、创建AsyncContext对象。

AsyncContext的start方法执行新的线程任务。

6.4 其他

改进了Servlet API,增加了文件上传下载的支持。允许通过编程的方式动态注册Servlet、Filter。

Servlet3.1新增了非阻塞式IO: ServletInputStream新增了setReadListener(ReadListener listener) 方法。

7.Tomcat8的WebSocket支持

开发WebSocket服务端的两种方式:
方式1:使用注解,被@ServerEndPoint修饰的Java类即可作为WebSocket服务端。3个关键的方法:@OnOpen start(Session session)、@OnClose end()、@OnMessage imcoming(String message)
方式2:继承EndPoint类实现WebSocket服务端。