时间:2023-05-30 21:57:01 | 来源:网站运营
时间:2023-05-30 21:57:01 来源:网站运营
JavaWeb详解(第四篇)之JSP 简介:<%@ page contentType="text/html;charset=GBK" language="java" isErrorPage="true"%><!DOCTYPE html><html><head><title>a.jsp</title></head><body> <h1>我是a.jsp</h1> <% String s = "HelloWorld"; out.println(s); %></body></html>
当我第一次访问时,找到我们项目的部署位置:package org.apache.jsp;import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.jsp.*;public final class a_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent, org.apache.jasper.runtime.JspSourceImports { 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 static final java.util.Set<java.lang.String> _jspx_imports_packages; private static final java.util.Set<java.lang.String> _jspx_imports_classes; static { _jspx_imports_packages = new java.util.HashSet<>(); _jspx_imports_packages.add("javax.servlet"); _jspx_imports_packages.add("javax.servlet.http"); _jspx_imports_packages.add("javax.servlet.jsp"); _jspx_imports_classes = null; } private volatile javax.el.ExpressionFactory _el_expressionfactory; private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; } public java.util.Set<java.lang.String> getPackageImports() { return _jspx_imports_packages; } public java.util.Set<java.lang.String> getClassImports() { return _jspx_imports_classes; } public javax.el.ExpressionFactory _jsp_getExpressionFactory() { if (_el_expressionfactory == null) { synchronized (this) { if (_el_expressionfactory == null) { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); } } } return _el_expressionfactory; } //JSP也是Servlet,运行时只有一个实例 public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() { if (_jsp_instancemanager == null) { synchronized (this) { if (_jsp_instancemanager == null) { _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); } } } return _jsp_instancemanager; } public void _jspInit() { } 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 { //9大内置对象 final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; java.lang.Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request); //页面声明了isErrorPage="true"属性才会有 if (exception != null) { response.setStatus(javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } 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, null, 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("<!DOCTYPE html>/r/n"); out.write("<html>/r/n"); out.write("<head>/r/n"); out.write("<title>a.jsp</title>/r/n"); out.write("</head>/r/n"); out.write("<body>/r/n"); out.write(" <h1>我是a.jsp</h1>/r/n"); out.write(" "); String s = "HelloWorld"; out.println(s); 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 { if (response.isCommitted()) { out.flush(); } else { 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); } }}
我们发现有个叫a_jsp.java的文件,跟踪原代码看到它它继承了HttpJspBase 类。 HttpJspBase 类又继承了 HttpServlet 类。 也就是说。 jsp 翻译出来的 java 类, 它间接了继承了 HttpServlet 类。 也就是说, 翻译出来的是一个 Servlet 程序 。细心的人可能发现,输出跟我们手写的很像,是的jsp帮我们完成了这部分复杂的工作。<%@ page language="java" import="java.util.*" pageEncoding="GBK"%><%@ include file=" " %><%@ taglib prefix=" " uri="" %>
<%@ page contentType="text/html;charset=GBK" language="java" %>
page 指令中常用属性有:语法:<%@ include file=”文件路径” %>案例:它会把b.jsp的内容都包含进来,再一起编译。<%@ include file=”b.jsp” %>
<%!声明变量、方法和类的代码%>
<% java代码 %>
<%=变量或可以返回值的方法或 Java 表达式%>
//单行注释
/*多行注释*/
/**文档注释*/
java 注释<!-- -->
会在 servlet 中生成对应的 out.write(“<!-- -->”)
,这样在返回给浏览器的静态页面中也有<!-- -->
,只是用户看不到而已;<%-- --%>
则在 servlet 中没有任何输出,建议使用<%-- --%>JSP动作(JSP Actions)是一组JSP内置的标签,只书写少量的标记代码就能够使用JSP提供丰富的功能,JSP行为是对常用的JSP功能的抽象和封装。JSP Actions是使用 xml 语法写的,是 jsp 规定的一些列标准动作,在容器处理 jsp 时,当容器遇到动作元素时,就执行相应的操作。可能看完概念还是很抽象。
<jsp:forward page="跳转的jsp页面"> [<jsp:param name="" value=""/>] [<jsp:param name="" value=""/>] </jsp:forward>
转发JSP Actions | 语法 | 描述 |
---|---|---|
include | <jsp:include page="relativeURL|<%=expressicry%>"></jsp:include> | 动态引入另一个文件 |
forward | <jsp:forward page="跳转的jsp页面">[<jsp:param name="" value=""/>][<jsp:param name="" value=""/></jsp:forward>转发 | 在开发jsp的过程中,我们通常把jsp放入WEB-INF目录,目的是为了防止用户直接访问这些jsp文件.在WebRoot下我们有一个入口页面,它的主要转发<jsp:forward file="/WEB-INF/xx.jsp"></jsp:forward> |
param | <jsp:param name="" value=""/> | 给一个 JSP 设置参数,常常与<jsp:include>或者<jsp:forward>集合使用<jsp:include page=""><jsp:param name="" value=""/><jsp:param name="" value=""/></jsp:include>,也可以给Bean或Applet传递参数。 |
useBean | <jsp:useBean class="" id=""></jsp:useBean> | 创建一个 javaBean 实例 |
setProperty | <jsp:setProperty name="对象" property="属性" value="属性值" scope="作用域"/> | 给一个 javaBean 实例属性赋值 |
getProperty | <jsp:getProperty property="" name=""/> | 取得一个 javaBean 实例的成员变量 |
plugin | <sp:plugin code="" codebase="" type="bean"></jsp:plugin> | 使用插件 |
fallback | <jsp:fallback></jsp:fallback> | 指定浏览器不支持或无法启动Bean或Applet时,在页面上打印输出信息 |
directive | <jsp:directive.include file="head.jsp"></jsp:directive.include> | 替代指令`<%@%>`的语法的 |
<jsp:include>
动作是通过 page 属性来指定被包含页面的,该属性支持 JSP 表达式。<html></html>
、<body></body>
这种标记,还要避免变量冲突)<jsp:include>
动作包含文件时,只有当该标记被执行时,才会引入被包含的的页面进行编译,再将译之后的视图再引入到当前页面,然后继续执行后面的代码。所以被引入的页面即使有与当前相同的Java变量也没影响。org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "b.jsp", out, false);
<%@ page contentType="text/html;charset=GBK" language="java"%><!DOCTYPE html><html><head><title>a.jsp</title></head><body> <h1>我是a.jsp</h1> <% String s = "HelloWorld"; out.println(s); %> <jsp:forward page="b.jsp"></jsp:forward></body></html>
3)案例效果if (true) { _jspx_page_context.forward("b.jsp"); return;}
使用案例2:<jsp:forward page="b.jsp"> <jsp:param name="username" value="mjx"/> <jsp:param name="password" value="123"/></jsp:forward>
2)在b.jsp中使用我获取到的参数:<% String username = request.getParameter("username"); String password = request.getParameter("password");%><br>用户名:<%=username %><br>密码:<%=password %>
3)案例效果<jsp:include>
或</jsp:forword>
时可以使用param动作向这个资源传递参数。上面的案例中已经使用到了,这里就不再演示了。public class User { //------------------User类封装的私有属性--------------------------------------- // 姓名 String类型 private String name; // 性别 String类型 private String sex; // 年龄 int类型 private int age; //------------------User类的无参数构造方法--------------------------------------- public User() { } //------------------User类对外提供的用于访问私有属性的public方法----------------------- public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
在学useBean之前,我们要使用一个对象,可能会这样写:<%@ page contentType="text/html;charset=GBK" language="java"%><%@ page import="com.cn.domain.User" %><!DOCTYPE html><html><head><title>a.jsp</title></head><body> <h1>我是a.jsp</h1> <% User u = new User(); u.setName("mjx"); u.setAge(18); u.setSex("男"); %> <% String userInfo = "姓名:"+u.getName() +" 性别:"+u.getSex()+" 年龄:"+u.getAge();%> <%=userInfo %></body></html>
案例效果:<jsp:useBean>
用于在指定的域范围内查找指定名称的JavaBean对象。语法一(常用):<jsp:useBean id="实例化对象的名称" class="类的全名" scope="保存范围page|request|session|application" ></jsp:useBean>语法二:<jsp:useBean id="stu" class="com.Bean.StudentInfo" type="com.Bean.StudentBase(父类)" scope="session" />
使用案例:<%@ page contentType="text/html;charset=GBK" language="java"%><!DOCTYPE html><html><head><title>a.jsp</title></head><body> <h1>我是a.jsp</h1> <jsp:useBean id="user" class="com.cn.domain.User" scope="page"/> <% user.setName("mjx"); user.setAge(18); user.setSex("男"); %> <% String userInfo = "姓名:"+user.getName() +" 性别:"+user.getSex()+" 年龄:"+user.getAge();%> <%=userInfo %></body></html>
案例编译部分源码:com.cn.domain.User user = null;user = (com.cn.domain.User) _jspx_page_context.getAttribute("user", javax.servlet.jsp.PageContext.PAGE_SCOPE);if (user == null){ //这里就是为什么需要一个无参构造了 user = new com.cn.domain.User(); _jspx_page_context.setAttribute("user", user, javax.servlet.jsp.PageContext.PAGE_SCOPE);}user.setName("mjx");user.setAge(18);user.setSex("男");String userInfo = "姓名:"+user.getName() +" 性别:"+user.getSex()+" 年龄:"+user.getAge();
<jsp:setProperty>
动作标记通常与<jsp:useBean>
动作标记一起使用,它以请求中的参数给创建的JavaBean中对应的属性赋值,通过调用 bean 中的 setXxx() 方法来完成。<%@ page contentType="text/html;charset=GBK" language="java"%><!DOCTYPE html><html><head><title>b.jsp</title></head><body> <form action="a.jsp" method="post"> 用户名:<input type="text" name="name"><br> 性别:<input type="text" name="sex"><br> 年龄:<input type="text" name="age"><br> <input type="submit" value="提交"> </form></body></html>
2)修改a.jsp<%@ page contentType="text/html;charset=GBK" language="java"%><!DOCTYPE html><html><head><title>a.jsp</title></head><body> <h1>我是a.jsp</h1> <jsp:useBean id="user" class="com.cn.domain.User" scope="page"/> <% String name = request.getParameter("name"); String sex = request.getParameter("sex"); int age = Integer.parseInt(request.getParameter("age")); user.setName(name); user.setSex(sex); user.setAge(age); %> <% String userInfo = "姓名:"+user.getName() +" 性别:"+user.getSex()+" 年龄:"+user.getAge();%> <%=userInfo %></body></html>
使用案例2:<%@ page contentType="text/html;charset=GBK" language="java"%><!DOCTYPE html><html><head><title>a.jsp</title></head><body> <h1>我是a.jsp</h1> <% request.setCharacterEncoding("GBK"); %> <jsp:useBean id="user" class="com.cn.domain.User" scope="page"/> <!--name:对象名称 property:属性名称,如果指定为*号则自动匹配 value:指定值 --> <jsp:setProperty name:"user" property="name" value="自定义名字"/> <jsp:setProperty name="user" property="age"/> <jsp:setProperty name="user" property="sex" /> <% String userInfo = "姓名:"+user.getName() +" 性别:"+user.getSex()+" 年龄:"+user.getAge(); %> <%=userInfo %></body></html>
案例使用原理: org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper(_jspx_page_context.findAttribute("user"), "name", "自定义名字", null, null, false); out.write("/r/n"); out.write(" "); org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper(_jspx_page_context.findAttribute("user"), "age", request.getParameter("age"), request, "age", false); out.write("/r/n"); out.write(" "); org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper(_jspx_page_context.findAttribute("user"), "sex", request.getParameter("sex"), request, "sex", false);
需要保持表单中的属性名和定义的javaBean属性名一致的原因就是,编译后是使用request.getParameter("sex")的值。并且,类型都会帮我们自动转换。<jsp:getProperty>
标记用来获得 bean中的属性,并将其转换为字符串,再在 JSP 页面中输出,该 bean 中必须具有 getXxx() 方法。<%@ page contentType="text/html;charset=GBK" language="java"%><!DOCTYPE html><html><head><title>a.jsp</title></head><body> <h1>我是a.jsp</h1> <% request.setCharacterEncoding("GBK"); %> <jsp:useBean id="user" class="com.cn.domain.User" scope="page"/> <%--自动匹配并设置值--%> <jsp:setProperty name="user" property="*"/> <%--自动匹配并设置值--%> 姓名:<jsp:getProperty name="user" property="name"/> 性别:<jsp:getProperty name="user" property="sex"/> 年龄:<jsp:getProperty name="user" property="age"/></body></html>
案例效果:<%@ page contentType="text/html;charset=GBK" language="java"%><!DOCTYPE html><html><head><title>c.jsp</title></head><body> <h1>我是c.jsp</h1> <% // out 输出 out.write("这是 out 的第一次输出<br/>"); // out flush 之后。 会把输出的内容写入 writer 的缓冲区中 out.flush(); // 最后一次的输出, 由于没有手动 flush, 会在整个页面输出到客户端的时候, 自动写入到 writer缓冲区 out.write("这是 out 的第二次输出<br/>"); // writer 的输出 response.getWriter().write("这是 writer 的第一次输出<br/>"); response.getWriter().write("这是 writer 的第二次输出<br/>"); %></body></html>
案例效果:<%@ page contentType="text/html;charset=GBK" language="java" errorPage="error.jsp" %><html><head> <title></title></head><body><%--模拟空指针异常的错误--%><% String isnull = null; isnull.length();%></body></html>
2)新建一个error.jsp<%@ page language="java" contentType="text/html; charset=GBK" pageEncoding="GBK" isErrorPage="true"%><!--注意:isErrorPage="true"时才能使用exception--><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; GBK"><title>Insert title here</title></head><body> <%out.println("程序抛出了异常:" + exception); %></body></html>
3)案例效果:官方文档上描述:pageContext对象常用API:
PageContext 为页面/组件作者和页面实现者提供了许多工具,其中包括:
-管理各种范围名称空间的单个 API
-许多便捷 API,用于访问各种公共对象
-获取 JspWriter 以供输出的机制
- 通过页面管理会话使用的机制
-向脚本环境公开页面指令属性的机制
-将当前请求转发或包含到应用程序中其他活动组件的机制
-处理 errorpage 异常处理的机制
<%@ page contentType="text/html;charset=GBK" language="java"%><!DOCTYPE html><html><head><title>e.jsp</title></head><body> <h1>我是e.jsp</h1> <% request.setAttribute("info","value of request scope"); session.setAttribute("info","value of request scope"); application.setAttribute("info","value of application scope"); %> pageContext 查找各个范围内的值:查找顺序page—>request->session->application <br> 输出: <%=pageContext.findAttribute("info") %> <hr> pageContext 取出以下范围内的值(方法一):<br> request 设定的值:<%=pageContext.getRequest().getAttribute("info") %> <br> session 设定的值:<%=pageContext.getSession().getAttribute("info") %> <br> application 设的值:<%=pageContext.getServletContext().getAttribute("info") %> <hr> pageContext取出以下范围内各值(方法二):<br> 范围1(page)内的值:<%=pageContext.getAttribute("info",1) %> <br> 范围2(request)内的值:<%=pageContext.getAttribute("info",2) %> <br> 范围3(session)内的值:<%=pageContext.getAttribute("info",3) %> <br> 范围4(application)内的值:<%=pageContext.getAttribute("info",4) %> <hr> pageContext 修改或删除某个范围内的值: 1)修改 request 设定的值:<br> <% pageContext.setAttribute("info","value of request scope is modified by pageContext",2); %> <br> 修改后的值:<%=pageContext.getRequest().getAttribute("info") %> <br> 2)删除 session 设定的值:<% pageContext.removeAttribute("info"); %> 删除后的值:<%=session.getAttribute("info") %></body></html>
2)案例效果<%@ page contentType="text/html;charset=GBK" language="java"%><!DOCTYPE html><html><head><title>c.jsp</title></head><body> <h1>scope.jsp</h1> <% // 往四个域中都分别保存了数据 pageContext.setAttribute("key", "pageContext"); request.setAttribute("key", "request"); session.setAttribute("key", "session"); application.setAttribute("key", "application"); %> pageContext 域是否有值: <%=pageContext.getAttribute("key")%> <br> request 域是否有值: <%=request.getAttribute("key")%> <br> session 域是否有值: <%=session.getAttribute("key")%> <br> application 域是否有值: <%=application.getAttribute("key")%> <br> <% session.setAttribute("findKey", "session"); application.setAttribute("findKey", "application"); %><br> 使用key去查找值:按作用域从小到大查<br> key:<%=pageContext.findAttribute("key")%><br> findKey:<%=pageContext.findAttribute("findKey")%></body></html>
2)案例效果关键词: