JSP+Servlet+Struts2的基本原理学习笔记

一 JSP 基本原理
  1. 概念
    JSP的本质是Servlet,当用户向指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面,包括每个静态的HTML标签和所有在HTML页面中出现的内容,即JSP页面的内容有两部分:标准的HTML标签、静态的页面内容,这些内容与静态的HTML一致和受java程序控制的内容,由java脚本动态加载。
  2. 原理
    事实上,JSP是Servlet的一种特殊形式(一个特殊的java类),每个JSP页面就是一个Servlet实例——JSP页面由系统编译成Servlet,Servlet再负责响应用户请求。即,JSP其实也是Servlet的一种简化,使用JSP时,其实还是使用Servlet,因为Web应用中的每个JSP页面都会由Servlet容器生成对应的Servlet。对于Tomcat而言,JSP页面生成的Servlet放在work路径对应的Web应用下。
    如\webapps\myapp\test.jsp

<%@ page contentType="text/html;charset=GBK" language="java" errorPage="" %>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>JSP页面title>
head>
<body>

<%
for(int i =0; i<7;i++){
out.println("");
%>
这是个验证页面
<br/>
<%}%>
body>
html>

当启动Tomcat后,可以在Tomcat的work\Catalina\localhost\myapp\org\apache\jsp目录下找到如下文件:test_jsp.java和test_jsp.class。这两个文件都是Tomcat生成的,Tomcat根据JSP页面生成对应Servlet的Java文件及class文件

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/8.0.8
 * Generated at: 2014-05-23 16:56:11 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 test_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.lang.String,java.lang.Long> _jspx_dependants;

    private javax.el.ExpressionFactory _el_expressionfactory;
    private org.apache.tomcat.InstanceManager _jsp_instancemanager;

    public java.util.Map.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=GBK");
            pageContext = _jspxFactory.getPageContext(this, request, response,
                        "", 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\n");
            out.write("\r\n");
            out.write("\r\n");
            out.write(");
            out.write("\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n");
            out.write("\r\n");
            out.write("\r\n");
            out.write("\t JSP页面 \r\n");
            out.write("\t\r\n");
            out.write("\r\n");
            out.write("\r\n");
            out.write("\r\n");
            for(int i = 0 ; i < 7; i++)
            {
            out.println("");

            out.write("\r\n");
            out.write("这是个验证页面\r\n");
            out.write("
\r\n"
); } out.write("\r\n"); out.write("\r\n"); out.write(""); } 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); } } }
  • init():初始化JSP/Servlet的方法
  • destroy():销毁JSP/Servlet之前的方法
  • service():对用户请求生成响应的方法
    工作原理可以概括为如下
    JSP+Servlet+Struts2的基本原理学习笔记_第1张图片
    当服务器启动后,当Web浏览器端发送过来一个页面请求时,Web服务器先判断是否是JSP页面请求。
    如果该页面只是一般的HTML/XML页面请求,则直接将HTML/XML页面代码传给Web浏览器端。
    如果请求的页面是JSP页面,则由JSP引擎检查该JSP页面,
    如果该页面是第一次被请求、或不是第一次被请求但已被修改,则JSP引擎将此JSP页面代码转换成Servlet代码,
    然后JSP引擎调用服务器端的Java编译器javac.exe对Servlet代码进行编译,
    把它变成字节码(.class)文件,然后再调用JAVA虚拟机执行该字节码文件,然后将执行结果传给Web浏览器端。
    如果该JSP页面不是第一次被请求,且没有被修改过,则直接由JSP引擎调用JAVA虚拟机执行已编译过的字节码.class文件,然后将结果传送Web浏览器端。
    需要注意的是
    JSP文件不是在服务器启动的时候转换成 Servlet 类的。而是在被客户端访问
    的时候才可能发生转换的 ( 如 JSP 文件内容没有被更新等,就不再发生 Servlet 转换 )。
    JSP页面中没有任何业务逻辑处理,它只是简单的检索Servlet先前创建的Beans或者对象,再将动态内容插入预定义的模板

经过上面的介绍可以总结为:

  1. JSP文件必须在JSP服务器内运行
  2. JSP文件必须生成Servlet才能执行
  3. 每个JSP页面的第一个访问者熟读很慢,因必须等JSP编译成Servlet
  4. JSP页面的访问者无需安装客户端,甚至不需要可以运行的java运行环境

    二 Servlet&Struts基本知识

    Servlet是Java提供的用于开发Web服务器应用程序的一个组件,运行在服务器端,由Servlet容器所管理,用于生成动态的内容。Servlet是平台独立的Java类,编写一个Servlet,实际上就是按照Servlet规范编写一个Java类

    1. Servlet开发工作原理

    流程图:
    JSP+Servlet+Struts2的基本原理学习笔记_第2张图片

当客户端浏览器向服务器请求一个Servlet时,Servlet容器收到该请求后
首先到容器中检索与请求匹配的Servlet实例是否已经存在。
若不存在,则Servlet容器负责加载并实例化出该类Servlet的一个实例对象,接着容器框架负责调用该实例的init()方法来对实例做一些初始化工作,然后Servlet容器运行该实例的service() 方法。
若Servlet实例已经存在,则容器框架直接调用该实例的service()方法。
service()方法在运行时,自动派遣运行与用户请求相对应的doXX()方法来响应用户发起的请求。
通常,每个Servlet类在容器中只存在一个实例,每当请求到来时,则分配一条线程来处理该请求

2.Servlet生命周期
Servlet 没有 main 方法,不能够独立的运行,它的运行需要容器的支持,Tomcat 是最常用的 JSP/Servlet 容器。
Servlet 运行在 Servlet 容器中,并由容器管理从创建到销毁的整个过程。

Servlet 的生命周期
(1) 创建Servlet实例
Servlet容器装载和实例化一个Servlet,创建出该 servlet类的一个实例。
Servlet何时被创建:
  1,默认情况下,当WEB客户第一次请求访问某个Servlet的时候,WEB容器将创建这个Servlet的实例。
  2,当web.xml文件中如果元素中指定了load-on-startup>子元素时,Servlet容器在启动web服务器时,将按照顺序创建并初始化Servlet对象。
  注意:在web.xml文件中,某些Servlet只有元素,没有元素,这样我们无法通过url的方式访问这些Servlet,这种Servlet通常会在元素中配置一个子元素,让容器在启动的时候自动加载这些Servlet并调用init()方法,完成一些全局性的初始化工作。
(2) 初始化
在Servlet实例化完成之后,Web容器负责调用该Servlet实例的init()方法,在处理用户请求之前,来做一些额外的初始化工作。
(3) 处理请求
Servlet初始化后,将一直存在于容器中,用于响应客户端的请求。当Servlet容器接收到一个Servlet请求时,便运行与之对应的servlet实例的service()方法,service()方法再派遣运行与请求相对应的doXX(doGet,doPost)方法来处理用户请求。
对于用户到达Servlet的请求,Servlet容器会创建特定于这个请求的ServletRequest对象和ServletResponse对象,然后调用Servlet的service方法。service方法从ServletRequest对象获得客户请求信息,处理该请求,并通过ServletResponse对象向客户返回响应信息。
(4) 销毁
当 Servlet 容器决定将一个 Servlet 从服务器中移除时 ( 如 Servlet 文件被更新 ),便调用该 Servlet 实例的 destroy() 方法,在销毁该 Servlet 实例之前,来做一些其他的工作。
当WEB应用被终止,或Servlet容器终止运行,或Servlet容器重新装载Servlet新实例时,Servlet容器会先调用Servlet的destroy()方法,在destroy()方法中可以释放掉Servlet所占用的资源。
其中,(1)(2)(4) 在 Servlet 的整个生命周期中只会被执行一次。

Struts2工作原理

流程图:
JSP+Servlet+Struts2的基本原理学习笔记_第3张图片
在Struts2框架中的处理大概分为以下几个步骤
1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2 请求被提交到一系列(主要是三层)的过滤器(Filter),如(ActionContextCleanUp、其他过滤器(SiteMesh等)、 FilterDispatcher)。注意这里是有顺序的,先ActionContextCleanUp,再其他过滤器(SiteMesh等)、最后到FilterDispatcher。
3 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action ,FilterDispatcher是控制器的核心。
4 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
5 ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
6 ActionProxy创建一个ActionInvocation的实例。
7 ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper
在上述过程中所有的对象(Action,Results,Interceptors等)都是通过ObjectFactory来创建的。

Struts2工作流程

请求–>响应的流程图:
JSP+Servlet+Struts2的基本原理学习笔记_第4张图片
1、客户端浏览器发出HTTP请求.
2、根据web.xml配置,该请求被FilterDispatcher接收
3、根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,将值注入给Aciton
4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。
5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面
6、返回HTTP响应到客户端浏览器

Struts2应用的开发流程

  1. 在web.xml文件中定义核心Filter来拦截用户
    由于web的应用时给予请求/响应架构的应用,所以不管哪个MVC WEB框架,都需要在web.xml中配置该框架的核心Serlet或Filter,这样才让框架接入web应用中
  2. 如果需要以Post方式提交请求,则定义包含表单数据的JSP页面。如果仅仅只是一GET方式发送请求,则无须此步骤。
  3. 定义处理用户请求的Action
    这一步也是所有MVC框架中必不可少的。因这步Action是MVC的C,即控制器。在MVC框架中,控制器是由两部分组成,即拦截所有用户请求,处理请求的通用代码都是有核心控制器完成。而实际的业务控制由Action处理
  4. 配置Action
    通过指定哪个请求对用哪个Action进行处理,从而让核心控制器根据该配置来创建合适的Action实例,并调用该Action的业务控制方法。
  5. 配置处理结果和物理视图资源之间的对应关系
    如下代码的配置:


    /WEB-INF/content/loginForm.jsp
    /WEB-INF/content/error.jsp
    /WEB-INF/content/welcom.jsp

  6. 编写视图资源

你可能感兴趣的:(javaweb)