JSP简单介绍
Posted 鬼王呵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JSP简单介绍相关的知识,希望对你有一定的参考价值。
JSP
- JSP–Java Server Pages,和servlet技术一样,都是SUN公司定义的一种用于开发动态的web资源的技术。
- JSP技术最大的特点在于:写JSP就像在写html,但它相比html而言,html只能为用户提供静态数据,而JSP技术允许在页面中嵌套java代码,为用户提供动态的数据。
JSP原理
- 浏览器访问JSP页面时,Web服务器时如何调用并执行一个JSP页面的?
- Web服务器在执行JSP页面时,是如何把JSP页面中的html排版标签是如何执行的?
- JSP页面中的java代码服务器是如何执行的?
- Web服务器在调用JSP时,会给JSP提供一些什么java对象?
JSP实际上就是Servlet,它是由容器翻译成Servlet源文件,再编译,用户看到的是Servlet的响应结果。
JSP最佳实践
Servlet作为Web应用中的控制器组件,JSP技术作为数据显示模板。
JSP语法
- JSP模板:JSP页面中HTML都是模板代码。
- JSP表达式:
- 作用:将程序数据输出到客户端
- 语法:
<%= 变量或表达式%>
注:其中没有分号。
JSP脚本片段
- 作用:在JSP中编写java代码
- 语法:
<% 第一行java代码; 第二行java代码; ... %>
JSP声明:JSP页面中编写的所有代码,默认是翻译到Servlet的_jspService方法中,而JSP声明中的java代码被翻译到_jspService方法的外面。
- 语法:
<%! java代码;... %>
- JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法。[在实际开发中用的不多]
- JSP注释:JSP引擎在将JSP页面翻译成Servlet程序时,忽略JSP页面中被注释的内容。
- 格式:
<%-- 注释信息 --%>
或者在<%%>
中使用java规定的注释。 - 注:HTML注释格式:
<!-- 注释信息 -->
,这个在翻译的Servlet中是有显示的,只是控制显示不显示而已。
- 格式:
JSP指令
- JSP指令是为了JSP引擎(Tomcat)而设计的,它们并不直接产生任何可见的输出,而只是告诉引擎如何处理JSP页面中的其余部分。
- JSP指令的基本语法格式:
<%@ 指令 属性名="值" %>
,举例:<%@page import="com.hsx.Student"%>
- 如果一个指令有多个属性,着多个属性可以写在一个指令中,也可以分开写。
<!-- 写成多个 --> <%@page import="com.hsx.Student"%> <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!-- 写成一个 --> <%@page import="com.hsx.Student" language="java" import="java.util.*" pageEncoding="UTF-8"%>
- 常用指令:
page指令:用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它的作用都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
属性:
- language:指示该JSP页面所使用的脚本语言,目前只能是JAVA。
- extends:指示该JSP生成的Servlet继承的父类是谁。大家不要改。
- import:在JSP中java脚本中需要用的类,导入该类
如果导入多个类,比如java.util.List 和java.util.ArrayList
<%@page import=”java.util.List,java.util.ArrayList”%>
或者
<%@page import=”java.util.List”%>
<%@page import=”java.util.ArrayList”%>
JSP引擎会自动导入下面的包:
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;//JSP的包 - session:true|false,默认为true,作用就是是否创建session对象。true时会创建session对象
- buffer:jsp输出的缓存。none,表示不要缓存;8kb,这是默认值,一般情况不需要修改,或者指定大小的缓存,单位是kb。
- autoFlush:缓存满后自动刷新。true|false,默认是true
- isThreadSafe:该JSP是否是线程安全的。true|false
默认值是true:不安全的
false:线程安全的
该属性实际上就是指示JSP对应的Servlet类是否实现SingleThreadModel接口 - errorPage:指示错误页面是谁。如果路径以”/”开头,并不代表应用名称
也可以通过web.xml配置全局错误页面
<error-page> <!-- 异常类型 --> <exception-type>java.lang.Throwable</exception-type> <location>/errors/error.jsp</location> </error-page> <error-page> <!-- 针对响应错误码 --> <error-code>404</error-code> <location>/errors/404.jsp</location> </error-page>
errorPage属性优先于web.xml中配置的错误页面
- isErrorPage:true|false(默认值),当前页面是否是错误处理页面。实际上是指对应的Servlet中加不加入Exception对象。
- contentType=”text/html;charset=UTF-8”:指示页面显示的MIME类型和编码。(给客户端)
- pageEncoding=”UTF-8”:告知引擎用什么编码来翻译(serlvet)该JSP文件
- isELIgnored=true|false:是否忽略EL表达式。true是忽略,false不会略
include指令:
- 用于引入其他JSP页面,如果使用include指令引入其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个Servlet,include指令引入通常也称之为静态引入,下面给出静态引入的图介绍:
- 动态引入
request.getRequestDispatcher("demo1.jsp").include(request, response);
,生成两个单独的.java文件,然后把两个运行的结果包含在一起,下面给出动态引入的图介绍:
- 语法:
<%@ include file="被包含组件的绝对URL或者相对URL" %>
其中file属性用于指定被引入文件的路径,路径以”/”开头,表示代表当前web应用。 - 细节:
- 被引入的文件必须遵循JSP语法。
- 被引入的文件可以使用任意的扩展名,即时其扩展名是html,JSP引擎会按照处理jsp页面的方式处理它里面的内容,为了见名知意,JSP规范建议使用
.jspf
(JSP fragments)作为静态引入文件的扩展名。 - 由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个Servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。
- 用于引入其他JSP页面,如果使用include指令引入其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个Servlet,include指令引入通常也称之为静态引入,下面给出静态引入的图介绍:
- taglib指令:用户引入JSP页面中导入标签库,格式:
<%@ taglib uri="http://xxx" prefix="s"%>
,比如引入Struts2中的OGNL:<%@ taglib prefix="s" uri="/struts-tags" %>
JSP中文乱码
- 解决方案:第一步,统一默认编码UTF-8;第二步,在*.jsp文件上加page指令:
<%@ page pageEncoding="UTF-8" %>
JSP运行原理和九大内置对象
- 每个JSP页面在第一次被访问时,Web容器都会把请求交给JSP引擎(一个Java程序)去处理》JSP引擎先将JSP翻译成一个_jspServlet(实质上也是有一个servlet),然后按照servlet的调用方式调用。
- 由于JSP第一次访问时会翻译成Servlet,所以第一次访问通常会比较慢,但是第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。
- JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。JSP技术的设计者为了便于开发人员在编写JSP页面时获得这些Web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得者9个对象的引用。
- 九大内置对象:
- request – 请求对象HttpServletRequest
- response – 响应对象HttpServletResponse
- config – ServletConfig
- application – ServletContext
- exception – 异常对象(isErrorPage必须为true)
- session – HttpSession
- page – this,代表当前的Servlet对象
- out – 输出对象JspWriter(作用同于PrintWriter) *
- pageContext – PageContext对象 *
- out内置对象:
- out内置对象用于向客户端发送文本数据。
- out对象通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
- JSP页面中的out内置对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
- 只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回PrintWriter对象将out的缓存区中的内容真正写入到Servlet引擎提供的缓存区中。
out.println("a<br/>");
response.getWriter().println("b<br/>");
上面的输出的结果是先b再a,如果想先输出a再输出b,可以采用关闭缓存或者out.flush();
使得缓存满。
- pageContext对象:
- pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不尽封装了对其它8个内置对象的引用,它自身还是一个域对象,可以用来保存数据,并且,这个对象还封装了web开发中经常涉及到的一些常用的操作,例如引入和跳转其它资源、检索其它域对象中的属性等。
- 通过pageContext获得其它对象:
- getException方法返回exception内置对象
- getPage方法返回page内置对象
- getRequest方法返回request内置对象
- getResponse方法返回response内置对象
- getServletConfig方法返回config内置对象
- getServletContext方法返回application内置对象
- getSession方法返回session内置对象
- getOut方法返回out内置对象。
- pageContext封装其他8个内置对象的意义:把pageContext对象传递给一个普通java对象。
public class Demo
public void method(PageContext pageContext)
ServletRequest request = pageContext.getRequest();
ServletResponse response = pageContext.getResponse();
- forward():
pageContext.forward("demo1.jsp");
request.getRequestDispatcher("demo1.jsp").forward(request, response);
<jsp:forward page="demo1.jsp"/>
- include():
pageContext.include("demo1.jsp");
request.getRequestDispatcher("demo1.jsp").include(request, response);
<%@ include file="demo1.jsp"%> //只有这一种才是静态包含
<jsp:include page="demo1.jsp"></jsp:include>
- pageContext对象中常用的方法
// 针对page范围的域对象绑定、获取、删除
public void setAttribute(java.lang.String name, java.lang.Object value);
public java.lang.Object getAttribute(java.lang.String name);
public void removeAttribute(java.lang.String name);
// pageContext对象中还封装了访问其他域的方法
public void setAttribute(java.lang.String name, java.lang.Object value, int scope);
public java.lang.Object getAttribute(java.lang.String name, int scope);
public void removeAttribute(java.lang.String name, int scope);
// 代表各个域的常量
PageContext.APPLICATION_SCOPE
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE
// 依次从page、request、session、application范围内获取搜寻指定的参数
findAttribute()
JSP页面图片下载
图片下载必须使用到字节流,但是JSP页面有内置对象out,out又可以看成PrintWriter,其实字符流,而在Servlet中不允许同时存在字节流和字符流,则需要把JSP页面调用的out内置对象的所有行删除,注意一个空行或者一个空格都调用了out内置对象。
<%@page import="java.io.OutputStream"%><%@page import="java.io.FileInputStream"%><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%
String realPath = application.getRealPath("/img/p1.jpg");
FileInputStream fis = new FileInputStream(realPath);
OutputStream os = response.getOutputStream();
//通知客户端的下载的方式
response.setHeader("Content-Disposition", "attachment;filename=p1.jpg");
byte[] buffer = new byte[1024];
int len = -1;
while ((len = fis.read(buffer)) != -1)
os.write(buffer, 0, len);
fis.close();
%>
JSP标签
JSP标签页称为JSP Action(JSP动作)元素,它用于在JSP页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成JSP页面难以维护。常用的JSP标签:
<jsp:include>
标签:用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。语法:<jsp:include page="relativeURL | <%=expression%>" flush="true|false"/>
- page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
- flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。
<jsp:forward>
标签:用于把请求转发给另外资源。语法:<jsp:forword page="relativeURL | <%=expression%>"/>
- page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式获得。
<jsp:param>
标签:当使用<jsp:include>
和<jsp:forward>
标签引入或将请求转发给其他资源时,可以使用<jsp:param>
标签向这个资源传递参数。
JSP映射
由于JSP实际上就是一个Servlet,那么可以像配置Servlet映射那样配置来映射JSP。
<servlet>
<servlet-name>HelloWorld</servlet-name>
<jsp-file>/demo1.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/demo1.html</url-pattern>
</servlet-mapping>
JSP页面调错
根据页面的信息,找到对应已经翻译成的Servlet,查看错误的原因。
4大域对象
- page PageContext 当前页面
- request HttpServletRequest 请求范围,只要响应了,就结束
- session HttpSession 会话范围,session立刻失效或超时,就结束
- application ServletContext 应用范围,web重新加载或者停止,就结束
JavaBean
JavaBean是一个遵循特定写法的Java类,它通常有以下特点:
- 这个Java类必须具有一个无参的构造方法。
- 字段必须私有化。
- 私有化的字段必须通过public类型的方法[getter/setter]暴露给其它程序,并且方法的命名也必须遵守一定的命名规范。
- 实现Serialiazable接口,便于序列化和反序列化。
JavaBean在JavaEE开发中,通常用于封装数据,对于遵循以上写法的JavaBean组件,其它程序可以通过反射技术实例化JavaBean对象,并且通过反射那些遵循命名规范的方法,从而获知JavaBean的属性,进而调用其属性保存数据。
- 封装对象
- 表示实际业务的某些名词(实际/抽象)。
在JSP中使用JavaBean
JSP技术提供了三个关于JavaBean组件的动作元素 [内置JSP标签],分别是:
<jsp:useBean>
标签:用于在JSP页面中的域范围内查找或实例化一个JavaBean对象。
- 如果存在则直接返回该JavaBean对象的引用。
- 如果不存在则实例化一个新的JavaBean对象并将它指定的名称存储到指定的域范围中。
- 常用语法
<jsp:useBean id="beanName" class="package.class" scope="page | request | session | application"><jsp:useBean>
- id属性用于指定JavaBean实例对象的引用名称和其存储在域范围中的名称。
- class属性用于指定JavaBean的完整类名(即必须带有包名)。
- scope属性用于指定JavaBean实例对象所存储的域范围,其取值只能是page/request/session/application等四个值中的一个(其默认的是page)。
<jsp:setProperty>
标签:用于在JSP页面中设置一个JavaBean对象的属性,前提Bean存在。<jsp:getProperty>
标签:用于在JSP页面中获取一个JavaBean对象的属性,前提Bean存在。
<jsp:useBean id="hh" class="com.hsx.Student" scope="page"></jsp:useBean>
<%=hh.getName() %>
<%=hh.getId() %>
<jsp:setProperty property="id" name="hh" value="23"/>
<jsp:setProperty property="name" name="hh" value="皇后搜寻"/>
<jsp:getProperty property="id" name="hh"/>
<jsp:getProperty property="name" name="hh"/>
<%=hh.getName() %>
<%=hh.getId() %>
<jsp:setProperty property="id" name="hh" param="id"/>
<jsp:setProperty property="name" name="hh" param="id"/>
<jsp:setProperty property="*" name="hh"/>
EL表达式
获取数据
- 使用El表达式获取数据语法:”$标识符”
- EL表达式语句在执行是,会调用pageContext.findAttribute方法,用标识符为关键字,分别从page、request、session、application四个域中查找相应的对象,找到则返回相应的对象,找不到则返回”“(注意,不是null,而是空字符串)。
<jsp:useBean id="s" class="com.hsx.Student" scope="page"></jsp:useBean>
$s.name
<br/>
<jsp:getProperty property="name" name="s"/>
<br/>
<%
Object o = pageContext.findAttribute("s");
Student student = (Student) o;
out.println(student.getName());
%>
<br/>
$o
上面的代码$o
中的o没有存放在域中,那么在浏览器上显示的是”“.。
- EL表达式也可以很轻松获取JavaBean的属性,或获取数组、Collection、Map类型的数据[
$user.address.city
,$user.list[0]
,$map.key
]
<%
Student student = new Student();
student.setName("你好");
Address address = new Address();
address.setProvince("安徽");
address.setCity("黄山");
student.setAddress(address);
request.setAttribute("student", student);
%>
$student.name
$student.address.city
<hr/>
<%
List<String> list = new ArrayList<String>();
list.add("11");
list.add("22");
request.setAttribute("list", list);
%>
$list[1]
<hr/>
<%
Map<String, String> map = new HashMap<String, String>();
map.put("one", "111");
map.put("two", "222");
request.setAttribute("map", map);
%>
$map.one
结合JSTL的foreach标签,使用EL表达式也可以很轻松迭代各种类型的数组或集合[迭代数组、迭代colleation类型集合、迭代map类型集合]
empty运算符:检查对象是否为null或空,当对象不存在null或空字符串或空集合或空数组,
$empty xx
都打印true
<%
Student s = new Student();
request.setAttribute("s", s);
%>
$empty s
- 二元表达式:
$user != null ? user.name : ""
$student.gender == 1 ? "男" : "女"
获取web开发常用对象
- El表达式语言中定义了11个隐含对象,使用这些隐含对象可以很方便地获取web开发中的一些常用对象,并读取这些对象的数据。语法:
$隐式对象名称
获取对象的引用。
- pageContext:代表JSP中pageContext对象,获取其他8个内置对象。
- pageScope:代表page域中的对象
- requestScope:代表request域中的对象
- sessionScope:代表session域中的对象
- applicationScope:代表application域中的对象
- param:Map对象,保存了所有请求参数的Map对象,http地址传过来的参数
http://localhost:8080/jsp/el.jsp?username=hsx
,$param.username
- paramValues:表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是一个String[],Httphttp地址传过来的参数
http://localhost:8080/jsp/el.jsp?username=hsx&username=hhh
,$paramValues.username[0]
- header:Map对象,获取一个请求头的值,
$header.accept
,当其中的请求头中有-隔开的请求头,那么$header["Accept-language"]
- headerValues:表示一个保存了所有请求头中的Map对象,它对于某个请求头,返回的是一个String[]。
- cookie:表示一个保存了所有cookie的Map对象(value对应一个cookie值)。
- initParam:表示一个保存了所有web应用初始化参数[web.xml]的map对象。
使用El调用Java方法
EL表达式语法允许开发人员开发自定义函数,以调用Java类的方法。
- 示例:$prefix: method(params)
- 在EL表达式中调用的只能是Java类的静态方法。
- 这个Java类的静态方法需要在TLD文件中描述,才可以被EL表达式调用。
- EL自定义函数用于扩展EL表达式的功能,可以让EL表达式完成普通的Java程序代码所能完成的功能。
- EL自定义函数开发与应用包括以下三个步骤:
- 编写一个Java类的静态方法
- 编写标签库描述(tld)文件,在tld文件中描述自定义函数
- 在JSP页面中导入和使用自定义函数。
//-------------编写一个Java类的静态方法--------------------------
public class Small2Big
public static String toUpperCase(String value)
return value.toUpperCase();
//--------编写标签库描述(tld)文件,在tld文件中描述自定义函数(放在工程下的WEB-INF目录下)--------
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<jspversion>1.1</jspversion>
<description>myfun</description>
<short-name>hsx</short-name>
<uri>http://www.hsx.com/jsp/jstl/myfun</uri>
<function>
<description>toUpperCase</description>
<name>toUpperCase</name>
<function-class>com.hsx.Small2Big</function-class>
<function-signature>java.lang.String toUpperCase(java.lang.String)</function-signature>
<example><hsx:toUpperCase('aaa')</example>
</function>
</taglib>
//-----------在JSP页面中导入和使用自定义函数----------
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="hsx" uri="http://www.hsx.com/jsp/jstl/myfun" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title></title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
$hsx:toUpperCase('aaa')
</body>
</html>
JSTL
- 要引入两个jar包:jstl.jar和standard.jar
在JSP页面中加上
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
元素导入标签库。- 简单练习下jstl中的core[核心包]
<!-- list -->
<%
List<Student> list = new ArrayList<Student>();
list.add(new Student(1, "aaa"));
list.add(new Student(2, "bbb"));
list.add(new Student(3, "ccc"));
list.add(new Student(4, "ddd"));
list.add(new Student(5, "eee"));
request.setAttribute("list", list); //存放在request域中
%>
<table border="1" width="50%">
<tr>
<th>序号</th>
<td>ID</td>
<td>NAME</td>
</tr>
<c:forEach items="$list " var="student" varStatus="s">
<tr style="background-color: $s.count % 2 == 0 ? 'red' : 'yellow' ">
<td>$s.count </td>
<td>$student.id </td>
<td>$student.name </td>
</tr>
</c:forEach>
</table>
<hr/>
<!-- map -->
<%
Map<String, Student> map = new HashMap<String, Student>();
map.put("a", new Student(1, "aaa"));
map.put("b", new Student(2, "bbb"));
map.put("c", new Student(3, "ccc"));
map.put("d", new Student(4, "ddd"));
map.put("e", new Student(5, "eee"));
request.setAttribute("map", map);
%>
<c:forEach items="$map " var="st">
$st.key =$st.value.name :$student.value.id
</c:forEach>
<hr/>
<!-- if -->
<%
session.setAttribute("stud", new Student(1, "hsx"));
%>
<c:if test="$sessionScope.stud == null ">
<input type="text" name=""/>登录
</c:if>
<c:if test="$sessionScope.stud != null ">
欢饮您!$sessionScope.stud.name
</c:if>
以上是关于JSP简单介绍的主要内容,如果未能解决你的问题,请参考以下文章