JSP 运行机制与基本语法

1.背景(why study)

1.2 jsp小历史

    sun公司早期推出了servlet技术,用于动态页面的html输出。但是,由于直接使用响应流输出的html格式内容,不方便修改和调整html代码。为了解决这一麻烦问题,衍生出了JSP技术,通过嵌入标签的方式写入java代码。总之:使用此技术的目的是为了将数据与页面结合起来,数据不断变化,页面跟着不断变化,简称为动态页面。编译流程为JSP——Servlet——class.


1.3 login.jsp编译成login_jsp.java文件

public final class login_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
private static final javax.servlet.jsp.JspFactory _jspxFactory =
org.apache.jasper.runtime.JspSourceImports {
javax.servlet.jsp.JspFactory.getDefaultFactory();

1.4 查看源码可见servlet的生命周期方法

public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final HttpServletRequest request, final HttpServletResponse response)

1.5 查看service方法,对比jsp代码和servlet代码

    从代码可以看出JSP内置对象的初始化操作,切记servlet没有9大内置对象(一部分有对应对象,一部分没有  page、pageContext、exection)。简略描述下PageContext:页面上下文,可以拿到页面上的所有东西包括对象

1.5.1 嵌入java代码前后比对
final javax.servlet.jsp.PageContext pageContext;
HttpSession session = null;
final ServletConfig config;
final ServletContext application;
final Object page = this;
javax.servlet.jsp.JspWriter out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
javax.servlet.jsp.JspWriter _jspx_out = null; try {
pageContext = _jspxFactory.getPageContext(this, request, response,
response.setContentType("text/html;charset=UTF-8"); null, true, 8192, true);
config = pageContext.getServletConfig();
_jspx_page_context = pageContext; 
 application = pageContext.getServletContext();
_jspx_out = out;
session = pageContext.getSession();
out = pageContext.getOut();

1.5.2 发现html代码用输出语句进行输出,java代码则直接执行。

<head>
<%
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
<link rel="stylesheet" type="text/css" href="MyCss.css"/>
%>
</head>
out.write("<head>\n");
out.write(" ");
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
out.write("\n");
out.write(" <link rel=\"stylesheet\" type=\"text/css\" href=\"MyCss.css\"/>\n");
out.write("</head>\n");

1.5.3 发现碰到java代码后直接执行,输出数据,打印

<script>
var error=<%=request.getAttribute("error")%>;
if(error==0){ alert("账号密码错误,请重新输入!");
}
   out.write("<script>\n");
out.write(" var error=");
out.print(request.getAttribute("error"));
out.write(";\n");
out.write(" alert(\"账号密码错误,请重新输入!\");\n");
out.write(" if(error==0){\n");
out.write(" }\n");

2.内容(what study)

2.1.页面组成结构

(1)HTML
(2)JSP标记(指令、动作、自定义)<%@> <jsp: >
指令标记:

  原理:翻译阶段提供全局信息,所有指令元素在整个JSP页面都有效。指令标记通知JSP引擎如何处理JSP页面。

  1.include指令标记

    原理:直接插入一段代码,属于静态的,先合并成一个jsp文件后才进行编译。由于属于同一个页面,所以一些语法规则要遵守。(不能对出import外的其他属性赋值多次,将会报错)

    方法:<%@ include file="文件URL" %>  

  2.page指令标记

    原理:只能应用本页面的指令,可以用来定义JSP页面的全局属性并设置属性值,page指令可以修改多个属性,与写入顺序无关,只是习惯把这类指令写在开头而已。(除import属性以外,其他属性只能出现一次)

例如属性有:

定义脚本语言:<%page language="java">

导入包:<%page import="java.util.*">

继承<%page extends="package.class">

指定页面输出内容的格式 <%page contentType="text/html"; charset=gb2312">

抛出异常的时候自动跳转页面 <%page errorPage="URL">

是否定义本jsp页面为错误页面 <%page isErrorPage="true"> (可以使用内置的execption对象)

   3.taglib指令标记

原理:为了简化jsp页面的开发,将一些公共部分的逻辑代码抽取出来放到一个.tag文件中

方法:<% taglib tagdir="标记资源位置" prefix="前缀">

动作标记:

    原理:在执行阶段为页面提供插件或动态引入资源,就是说实际上会编译成两个servlet,只是把另一个servlet的返回结果拿到而已,所以说动作标记不要遵守jsp的页面规定,因为是两个页面,两次编译。

    1.jsp:include

        原理:include动作在执行阶段才处理被插入的文件,可动态传递参数,处理灵活,但是运行速度慢。

        方法:<jsp:include page="URL" flush=true|false>

                    <jsp:param name="name" value="value"/>

              </jsp :include>

            可传递参数,参数可以通过request.getParameter()获取

     2.jsp:forward

        原理:在原页面跳转到另外一个页面,但是地址不会改变。

        方法:<jsp:forward page="URL">

              同样也可以传递参数,此处不再描述。

     3.jsp:plugin(省略)

     4.jsp:useBean

        原理:javaBean是一种可以重复使用的软件组件,是用java语言编写的一种类。JSP引擎根据useBean中id属性指定的名字,在一个同步块中,查找内置对象pageContext中是否包含该id指定的名字和scope指定的作用域的对象。如果存在则分配。根据scope范围的不同,useBean的可共享域也不同。

        方法:<jsp:useBean id="bean实例名字" class="bean完整类名">

                    <scope="page|request|session|application">   page:作用域只在当前页面

                    ...以此类推

                </jsp:useBean>

      5.jsp:setProperty

        原理:设置useBean的属性值,功能上可以类似于springmvc的属性自动映射

        方法:<jsp:setProperty name="bean的名字" property="bean的属性" value="xx">

                直接赋值

              <jsp:setProperty                                         param="请求的参数名字">

                写上参数名字,进行值的映射

              <jsp:setProperty                                         param="*">

                所有复合的参数名字,全部都映射

              

(3)java代码片段<% %>

实际上就是java代码片段,从源代码可以看出来全部一股脑都在servlet的service方法里面,那么理所当然的所有定义的变量或者程序段都位于方法里面,所以是局部变量,它跟成员变量不同,所以每个用户的变量都是新的变量。

方法:

    利用java代码可以重复渲染某些数组的数据。

     <%   for(int i=0;i<10;i++){      %>          

                 html代码、、、 

     <%                  }                 %>

(4)声明变量、方法、对象<%! %>

原理:由于遵循单例原则,多用户同时访问同一个页面的时候都是同一个单例,所以理所当然的共享成员变量。

方法:<%! int i=6;%> 记得要加分号

      <%! Circle a=new Circle();%>

(5)表达式 <%= %>

原理:直接使用PrintWriter.print()输出表达式的值,这个表达式其实就是java表达式,这个表达式理所当然的可以访问JSP的各种内部对象。

方法:<%= MyDate.toLocalString()%>

(6)注释(HTML、JSP、脚本语言)

HTML:<!-- -->

JSP <%--  --%>

脚本语言:java 编译自动忽略

// 

/* */

3.总结(after study)

    优点:

            1.jsp引擎实行单例模式,减少内存开销。

            2.动作指令和指示指令(include),可以按照场景去使用,需要提前得到结果的肯定是先用动作指令,将一些重复代码提炼出来则用指示指令。

            3.jsp:usebean,也就是pojo了,可以根据作用域去实例化,有sping容器管理bean的概念和技术。

            4.声明变量,可以做一些需要所有用户共享变量的功能

            5.taglib自定义标签,可以将一些重复可提炼的工具逻辑程序段提取出来,使用自定义标签代替

    缺点:

            1.java代码和html代码混合,混乱不堪,解决办法有使用jstl标签技术和EL表达式

            2.动态页面的通病,没有彻底与前后端分离(是否分离看业务需要)




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值