Java Server Page :动态web资源,可写java代码
<% java代码 %>
1.本质servlet
jsp最终转义成了servlet:\apache-tomcat-7.0.64\work\Catalina\localhost\xxProject\org\apache\jsp\xx_jsp.java
观察:xx_jsp extends HttpJspBase ; HttpJspBase extends Servlet implements HttpJspPage
jsp 内嵌对象:
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;
2.语法
1.jsp脚本片段:内嵌java代码 :<% 编写java 代码 ,使用内嵌对象 %>
可以有多个脚本片段,相互可以访问
因为:
jsp转servlet的时候,java代码原封不懂的转换,所有按照.java编写一样的规则
多个脚本默认放在了java类中的_jspService方法里面
所以相互可以访问
<%
for(int i =0;i<10;i++)
{
%>
<%out.print("xx"); %> //也可以!!!
<%
}
%>
2.jsp 脚本表达式,输出数据:<%=xx %> ,不能有封号,不能多行
3.jsp 声明:<%! 方法 %>
#$jsp所有java代码默认转换到_jspService方法里面,方法里面不能内嵌方法
然而jsp声明中的java代码会转换到_jspService方法外面
#$jsp声明:用于java的静态代码块、成员变量、方法的声明
#$可以有多个jsp声明
#$jsp 内嵌对象,只在_jspService方法中,所以jsp声明不能使用内嵌对象
4.jsp 注释:<%-- --%> 不输送给浏览器
html注释:<!-- -->:回输出给客户端!!!
//
3.指令(page、include、taglib)
<%@ 指令 属性名=“值” %> 通常在jsp首行、可以有多个指令
page指令:
<%-- 指定语言 与编码 [处理乱码 的]--%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%-- 导包 默认已经导入了许多包 java.lang.* javax.servlet.* 等内嵌对象使用包 --%>
<%@ page import="java.util.* , java.io.*" %>
<%@ page import="java.sql.*" %>
<%-- session="true" 会在 _jspService方法里 ,
创建session对象,内嵌对象有session,相反 无session对象引用 ,默认true!
--%>
<%@ page session="false" %>
<% request.getSession(); %> <%-- 手动添加session --%>
<%--缓存 默认8kb --%>
<%@ page buffer="none|8kb" %>
<%--缓存 满了自动刷新 默认true --%>
<%@ page autoFlush="true" %>
<%-- 默认true servlet线程不安全 ,false 将实现 SingleThreadModel接口 --%>
<%@ page isThreadSafe="true" %>
<%-- --%>
<%@ page info="text" %>
<%-- 忽略el表达式false --%>
<%@ page isELIgnored="false" %>
错误处理: jsp错误处理比web.xml的优先级高
<%@ page errorPage="相对路径" %>
在web.xml 中可使用 <error-page>元素 为整个项目配置错误处理界面,
子元素<exception-type>java.lang.NullPointException,子元素指定异常处理类的完全名称
子元素 <error-code> 404,错误code
子元素<location>/errors/nullError.jsp, 处理错误路径 /代表当前web应用 [WebRoot]
<%-- 错误处理界面 默认false, 在错误处理处理界面 声明,true:会有错误对象 Throwable exception--%>
<%@ page isErrorPage="false" %>
include指令:
静态包含:jsp会编译成一个jsp,尽量使用
<%@ include file="/public/head.jsp" %>
<%@ include file="/public/foot.jsp" %>
动态包含:jsp会编译成多个jsp,运行时包含
<% request.getRequestDispatcher("/public/head.jsp").include(request, response); %>
pageContext.include()
<jsp:include page="/index.jsp"></jsp:include>
taglib指令:
导入标签库
3.jsp标签 :jsp action[jsp动作]元素
<% int xxx = 10;%>
<%-- 包含 动态包含 --%>
<jsp:include page="/index.jsp"></jsp:include>
<%-- 跳转 --%>
<jsp:forward page="/servlet/IndexServlet">
<jsp:param name="x" value="123" /> <%-- 参数 --%>
<jsp:param name="xxx" value="<%= xxx %>" />
</jsp:forward>
JavaBean标签:
1.<jsp:userBean id="beanName" class="com.xxx.Student" scope="page|request|session|application">
body
</jsp:userBean >
指定域找,如果没有,创建存放在域中;标签体只在实例化对象的时候执行,如果对象不空就不执行
2.<jsp:setProperty name="beanName" property="age" value="xxx"> 手工赋值
<jsp:setProperty name="beanName" property="age" param="age"> 请求参数?age=112 ,只支持基本数据的转换
<jsp:setProperty name="beanName" property="birthDay" value="<%=new Date(request.getParameter("birthDay" ))%>">表达式 ?birthDay=1990-1-2
<jsp:setProperty name="beanName" property="*" > 所有请求参数给bean赋值
3.<jsp:getProperty>
<jsp:getProperty name="beanName" property="age" > null->"null"
4.jsp映射
在web.xml中:
<servlet>
<servlet-name>jspX</servlet-name>
<jsp-file>/xx/xx.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>jspX</servlet-name>
<url-pattern>/xx.html</url-pattern>
</servlet-mapping>
5.jsp模式:
模式一: jsp + javaBean[封装数据] ;jsp负责处理请求、显示数据,适合简单的web程序
模式二: jsp +servlet + javaBean ;mvc servlet 请求、jsp显示
6.el表达式 expression language
pageContext.findAttrubite(“xxx”); 小域到大域找 找不到返回“”
1.属性 ${ property}
2.实体${ bean.property} 、 ${ bean.subBean.property}
3.bean list ${ list[1].property}
4.beanmap ${map.key.property}、${map['111'].name} 数值或特殊字符要中括号['123'] ['aa-cc']
el表达式取数时,通常用. ;当取不出的时候用[]
5.${pageContext.request.contextPath} //当前web应用的路径 <a href="${pageContext.request.contextPath} /aa.jsp">aa<a/>
6.逻辑运算${num+1} ${user==null} true、false
7.直接使用11大隐式对象${ page }
pageContext(1:8)、
param(map集合,封装请求参数?aa=xx&bb=xx)、paramValues(封装同名请求参数?aa=xx&aa=xx) Map<String,String[]>、(request多个map中的引用!!)
header(map集合,封装所有请求头)、headerValues(map集合,封装所有请求头)、
pageScope、requestScope、sessionScope、applicationScope、 (map集合,区分不同域[域一部分的引用!!],相同名的取值问题)
cookie(map集合,封装所有客户端cookie) Map<String,Cookie>、
initParam(map集合,封装所有web应用初始化参数)
7.JSTL标签
c.tld 核心标签库 fmt.tld国际化fn.tld函数sql.tld数据库标签x.tld xml标签
1.导入jstl.jar、standerd.jar
2.在jsp中用tablib指令导入标签库
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
1.迭代 forEach
<c:forEach items="${list}" var="item" begin="1" end="6" step="1" varStatus="status">
<span style="white-space:pre"> </span><tr class=" ${<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">status.count/2==0?'even':'odd'} "> <</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">%</span><span style="font-size: 12px; font-family: Arial, Helvetica, sans-serif;">-- 奇偶判断 --%></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">
</span><span style="white-space:pre"> </span>${item.property} </br>
</c:forEach>
map 迭代 entrySet Set<Entry>集合
<c:forEach items="${map}" var="entry">
${entry.key} </br>
${entry.value} </br>
${entry.property} </br>
</c:forEach>
2.判断 if
<c:if test="${user!=null}" var="booleanValue" scope="page">
已经登入
</c:if>
3.输出 out
<c:out value="<a href=''>转义</a>" default="" escapeXml="true" />
4.设置 set
1.<c:set var="data" value ="xxx" scope="page" > </c:set>
${data}<br/>
<% Map map = new HashMap();
pageContext.setAttribute("map", map);
%>
2.<c:set value ="map" target="${map}" property="propertyName" > </c:set>
${map.propertyName}<br/>
3.<c:set value ="java bean
" target="${bean}" property="propertyName" > </c:set>
${bean.propertyName}<br/>
5.catch
<c:catch var="ex" >
<% int a = 1/0; %>
</c:catch>
${ex.message}
6.choose
<c:choose>
<c:when test="${map==null}">c:when map null </c:when>
<c:otherwise> c:otherwise </c:otherwise>
</c:choose>
6.url
url重写 自动加 /project + sessionId{(禁用的情况下)
<a href="/project/xx" >xxx</a> <br/>
<c:url value="/xx" > </c:url>
<c:url value="/xx" var="temp"> </c:url><br/>
<c:url value="/xx" var="temp">
<c:param name="param" value="自动URL编码"></c:param>
</c:url><br/>
<a href="${temp}" >xxx</a><br/>
7.分割 forTokens
<% request.setAttribute("data", "aa,dd,cc"); %>
<c:forTokens var="item" items="${data}" delims=",">
${item}
</c:forTokens>
8.自定义标签
1.java类实现Tag接口,标签处理类[一般2.0以前实现TagSupport,以后:SimpleTag]
public class MyTag extends TagSupport
{
@Override
public int doStartTag() throws JspException
{
HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest();
String remoteAddr = request.getRemoteAddr();
JspWriter out = this.pageContext.getOut();
try
{
out.write(remoteAddr+"hello world");
} catch (IOException e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
return super.doStartTag();
}
}
public class ControlTag extends TagSupport
{
@Override
public int doStartTag() throws JspException
{
int evalBodyInclude = Tag.EVAL_BODY_INCLUDE; //都执行
int skipBody = Tag.SKIP_BODY; //不执行
return evalBodyInclude;
}
@Override
public int doEndTag() throws JspException
{
//控制整个jsp
int evalBodyInclude = Tag.EVAL_BODY_INCLUDE; //都执行
int skipBody = Tag.SKIP_BODY; //2.整个余下的jsp 都不会执行!
return evalBodyInclude;
}
int a = 1 ;
//3.标签执行后执行,循环方法 重复执行
@Override
public int doAfterBody() throws JspException
{
a++;
if(a<4)
{
return IterationTag.EVAL_BODY_AGAIN;
}
return IterationTag.SKIP_BODY;
}
}
SimpleTagSupport :使用后会release ,##父类共享变量做if else
public class SimpleTagDemo extends SimpleTagSupport
{
@Override
public void doTag() throws JspException, IOException
{
//4.不显示 以后的代码 ##refer 防盗链开发
//throw new SkipPageException();
JspFragment jspBody = this.getJspBody();
JspContext pageContext = this.getJspContext();//pageContext
JspWriter out = pageContext.getOut();
out.write("xxxxxadada"); //向外输出数据
//1.如果不写,标签体内容不会显示 ,2. 循环for执行的话就可以多次显示标签提 foreach标签开发
//jspBody.invoke(out); ==jspBody.invoke(null);
//3。截取标签体内容,可做修改
StringWriter sw = new StringWriter();
jspBody.invoke(sw);
out.write(sw.toString());
}
}
public class SimpleTagDemoWithProperty extends SimpleTagSupport
{
private String propertyName;//属性
public void setPropertyName(String propertyName){this.propertyName = propertyName;}
private int count;
public void setCount(int count){this.count = count;}
private Date date;
public void setDate(Date date){this.date = date;}
@Override
public void doTag() throws JspException, IOException
{
JspFragment jspBody = this.getJspBody();
jspBody.getJspContext().getOut().write(date.toLocaleString()); //写数据
for (int i = 0; i <count; i++)
{
jspBody.invoke(null);
}
}
}
2.编辑标签库描述符(tld),把处理类标志成一个标签;位置放在WEB-INF下
apache-tomcat-7.0.64\webapps\examples\WEB-INF\jsp2
<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">
<description>A tag library exercising SimpleTag handlers.</description>
<tlib-version>1.0</tlib-version>
<short-name>SimpleTagLibrary</short-name>
<uri>http://xxxx</uri>
<tag>
<name>tagName</name>
<tag-class>com.tag.MyTag</tag-class>
<body-content>empty</body-content>
</tag>
<tag>
<name>controlTag</name>
<tag-class>com.tag.ControlTag</tag-class>
<body-content>JSP</body-content>
</tag>
</taglib>
SimpleTagSupport
<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">
<description>A tag library exercising SimpleTag handlers.</description>
<tlib-version>1.0</tlib-version>
<short-name>SimpleTagLibrary</short-name>
<uri>http://xxxx.simple</uri>
<tag>
<name>simpleTagName</name>
<tag-class>com.tag.SimpleTagDemo</tag-class>
<body-content>scriptless</body-content>
</tag>
<tag>
<name>simplePropertyTagName</name>
<tag-class>com.tag.SimpleTagDemoWithProperty</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>count</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>date</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
3.jsp中tagLib引入标签
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ page import="java.util.*"%>
<%@taglib uri="http://xxxx" prefix="xx" %>
<%@taglib uri="http://xxxx.simple" prefix="s" %>
<%-- prefix 最好是 xx.tld 前缀 --%>
<%-- <xx:controlTag/> 不显示 以后的代码 --%>
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<xx:tagName/>
<xx:controlTag>
控制输出<br/>
</xx:controlTag>
<s:simpleTagName>
控制输出?
</s:simpleTagName>
<s:simplePropertyTagName count="9" date="<%= new Date() %>">
屬性<br/>
</s:simplePropertyTagName>
</body>
</html>
具体步骤: 可以看翻译源码 [jsp翻译成servlet]
自定义标签使用
自定义迭代标签:
public class ForeachTag extends SimpleTagSupport
{
private Object items;
public void setItems(Object items)
{
this.items = items;
if(items instanceof Collection) //list set
{
this.collection = (Collection) items;
}
else if(items instanceof Map) //list set
{
Map map = (Map) items;
this.collection = map.entrySet() ;
}
else if(items.getClass().isArray()) //反射
{
this.collection = new ArrayList();
int length = Array.getLength(items);//反射包 Array 对任意 数组操作!
for (int i = 0; i < length; i++)
{
Object value = Array.get(items, i);
this.collection.add(value);
}
}
}
private String var;
public void setCount(String var){this.var = var;}
private Collection collection;
@Override
public void doTag() throws JspException, IOException
{
Iterator iterator = this.collection.iterator();
while (iterator.hasNext())
{
Object next = iterator.next();
this.getJspContext().setAttribute(var, next); //page域
this.getJspBody().invoke(null);
}
}
/*
<f:foreach var="item" items="${list}"> ${item}</f:foreach>
<f:foreach var="item" items="${map}"> ${item}</f:foreach>
<f:foreach var="item" items="${boolArr}"> ${item}</f:foreach>
<f:foreach var="item" items="${intArr}"> ${item}</f:foreach>
*/
}
html转义标签:
public class HttpFilterTag extends SimpleTagSupport
{
@Override
public void doTag() throws JspException, IOException
{
StringWriter sw = new StringWriter();
JspFragment jspBody = this.getJspBody(); // <a href=""> xx</a>
jspBody.invoke(sw);
String html = sw.getBuffer().toString();//内容
String httpFilter = httpFilter(html);//转义
this.getJspContext().getOut().write(httpFilter);
}
public static String httpFilter(String message) {
if (message == null)
return (null);
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuilder result = new StringBuilder(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
default:
result.append(content[i]);
}
}
return (result.toString());
}
/*
<f:htmlFilter > <a href=""> xx</a> </f:foreach>
<tag>
<name>htmlFilter</name>
<tag-class>com.tag.HtmlFilter</tag-class>
<body-content>scriptless</body-content>
</tag>
*/
}
标签打包
9.自定义el函数
同自动以标签:
1.tld
<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">
<description>A tag library exercising SimpleTag handlers.</description>
<tlib-version>1.0</tlib-version>
<short-name>SimpleTagLibrary</short-name>
<uri>http://myfuncation</uri>
<function>
<description>xxx</description>
<name>elFun</name>
<function-class>com.tld.func.MyFun</function-class>
<function-signature>java.lang.String elFun( java.lang.String )</function-signature> //函数签名
</function>
</taglib>
2.函数
public final class MyFun
{
public static String elFun(String msg)
{
return "hello ";
}
}
3.jsp中使用
<%@taglib uri="http://myfuncation" prefix="myfunc" %>
<% request.setAttribute("test", "xxxxxxxxxxxxxxxx"); %>
${myfunc:elFun(test)}