您的位置:首页 > 编程语言 > Java开发

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

2016-02-24 21:15 519 查看
一 JSP 基本原理

概念

JSP的本质是Servlet,当用户向指定Servlet发送请求时,Servlet利用输出流动态生成HTML页面,包括每个静态的HTML标签和所有在HTML页面中出现的内容,即JSP页面的内容有两部分:标准的HTML标签、静态的页面内容,这些内容与静态的HTML一致和受java程序控制的内容,由java脚本动态加载。

原理

事实上,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

<!-- 这是一jsp页面-->
<%@ page contentType="text/html;charset=GBK" language="java" errorPage="" %>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
<title>JSP页面</title>
</head>
<body>
<!-- 下面是java脚本-->
<%
for(int i =0; i<7;i++){
out.println("<font size ='" + i + "'>");
%>
这是个验证页面
<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<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 {

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("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\r\n");
out.write("\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n");
out.write("<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n");
out.write("<head>\r\n");
out.write("\t<title> JSP页面 </title>\r\n");
out.write("\t<meta name=\"website\" content=\"http://www.crazyit.org\" />\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("<!-- 下面是Java脚本 -->\r\n");
for(int i = 0 ; i < 7; i++)
{
out.println("<font size='" + i + "'>");

out.write("\r\n");
out.write("这是个验证页面</font>\r\n");
out.write("<br/>\r\n");
}
out.write("\r\n");
out.write("</body>\r\n");
out.write("</html>");
} 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():对用户请求生成响应的方法

工作原理可以概括为如下



当服务器启动后,当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或者对象,再将动态内容插入预定义的模板

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

JSP文件必须在JSP服务器内运行

JSP文件必须生成Servlet才能执行

每个JSP页面的第一个访问者熟读很慢,因必须等JSP编译成Servlet

JSP页面的访问者无需安装客户端,甚至不需要可以运行的java运行环境

二 Servlet&Struts基本知识

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

Servlet开发工作原理

流程图:



当客户端浏览器向服务器请求一个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文件中如果
<servlet>
元素中指定了
load-on-startup>
子元素时,Servlet容器在启动web服务器时,将按照顺序创建并初始化Servlet对象。

  注意:在web.xml文件中,某些Servlet只有
<serlvet>
元素,没有
<servlet-mapping>
元素,这样我们无法通过url的方式访问这些Servlet,这种Servlet通常会在
<servlet>
元素中配置一个
<load-on-startup>
子元素,让容器在启动的时候自动加载这些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工作原理

流程图:



在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工作流程

请求–>响应的流程图:



1、客户端浏览器发出HTTP请求.

2、根据web.xml配置,该请求被FilterDispatcher接收

3、根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,将值注入给Aciton

4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。

5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳转到相应页面

6、返回HTTP响应到客户端浏览器

Struts2应用的开发流程

在web.xml文件中定义核心Filter来拦截用户

由于web的应用时给予请求/响应架构的应用,所以不管哪个MVC WEB框架,都需要在web.xml中配置该框架的核心Serlet或Filter,这样才让框架接入web应用中

如果需要以Post方式提交请求,则定义包含表单数据的JSP页面。如果仅仅只是一GET方式发送请求,则无须此步骤。

定义处理用户请求的Action

这一步也是所有MVC框架中必不可少的。因这步Action是MVC的C,即控制器。在MVC框架中,控制器是由两部分组成,即拦截所有用户请求,处理请求的通用代码都是有核心控制器完成。而实际的业务控制由Action处理

配置Action

通过指定哪个请求对用哪个Action进行处理,从而让核心控制器根据该配置来创建合适的Action实例,并调用该Action的业务控制方法。

配置处理结果和物理视图资源之间的对应关系

如下代码的配置:

<action name ="login" class="test.gmail.app.action.LoginAction">

<result name="input">/WEB-INF/content/loginForm.jsp</result>

<result name="error">/WEB-INF/content/error.jsp</result>

<result name="success">/WEB-INF/content/welcom.jsp</result>

</action>


编写视图资源
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: