案例中的分帧页面:frameset不能再body中
将多个页面用帧标签组合
Javascript:void(0)取消默认的行为
Onclick="hidden(document.getElementById(d1))"
点击事件:隐藏组件
Function hidden(div){
div.style.display='block'?'none':'block';
}
Jsp中使用javabean:
例子:
例子:
例子:
属性可能为NULL,要先判断,再输出,后面可以用el 表达式解决
Jsp的2中开发模式:
Jsp+javabean:jsp 处理可显示数据, bean封装数据,用于业务逻辑不太复杂的WEB应用
案例:计算器
四舍五入:
BigDecimal类是大数字,setScale(int,int),设置精度和舍入模式
BigDecimal bd=new BigDecimal(thi.resutl);//将数字封装到big中
bd=db.setScale(2,BigDecimal.ROUND_HALF_UP);
This.resutl=bd.doubleValue();
Servlet+jsp+javabean:servlet处理请求,jsp显示,bean封装数据
三层架构:
Web层( jsp和servlet),业务处理层(service负责业务逻辑),数据访问层(dao负责数据处理),3层通过javaBean衔接
层与层之间的解耦:上层调用接口,下层实现接口
通过报名组织接口和实现:cn.beijing.service;cn.beijing.service.impl;
项目目录:请求通过servlet转发到(forward)jsp。为防止用户直接访问jsp ,应该将 jsp放在web-inf目录下的文件夹中。(把JSP调用交给服务器处理。浏览器不能直接访问了)
EL表达式和JSTL标签:
取出域中的数据:${name}
${标识符}//原理:内部调用 pageContext.findAttribute() ,从 pageContext,request,session,application域中查找数据,如果不存在,就返回“”;
获取bean的属性:${person.age}
获取bean中的bean中的属性:${person.address.city}
取集合中的数据:$(lsit[0].age);${liat[1]};${map.aa}(key不能为数字)
El表达式map集合中取数据,点不行时,用${map["1"]};
其他常用EL表达式:
动态配置地址:
El表达式:
El表达式内不能嵌套EL表达式,后面不用加分号
4个作用:
1.获取数据:从4个域中查找数据(各种集合),替换jsp中的脚本表达式
2.执行运算:
支持数字相加,不支持字符串相加
支持关系运算符(大于,小于,等于。。)和逻辑运算符(与或等。。。)(参考PPT)${1==1}//返回true或false
Empty运算符:检查是否为NULL或“”,${!empty(list)}
二元表达式:${!user=null?user.name:""}
二元表达式应用:回显数据
${user.gender=='male'?:'checked':''}>男
[]和.运算符:点不行就用[]
3.获得WEB开发常用对象:EL表达式语言中定义了11个隐士对象。可以直接用对象
pageContext//可以拿到其他域对象
${pageScope}//返回page域中用于保存数据的MAP集合
${pageScopte[i]},${pageContext.key}
pageScope,requestScope,sessionScope,applicationScope
${sessionScope.user==null}//检查用户是否登录
Param(所有请求参数MAP集合),paramValues(针对一个请求参数时,返回String[]),header(所有请求头MAP集合),headerValues(返回String[]),cookie,initParam(WEB应用所有初始化参数MAP)
${header.Accept},${header["Accept-encoding"]}
4 .用EL掉JAVA方法:EL自定义函数
使用:写一个静态方法,TLD(参考 tomcat中的例子)中描述方法(function),导入标签库,在EL中调用即可。
${user==null?"对不起":fx:join("欢迎你",user.name)}
可用EL函数优化,HTML转义
JSTL和El函数什么时候用?JSTL标签可以移除所有的JAVA代码,El函数只能移除与 开发无关的外部代码。如 涉及到域时就只能用JSTL 标签
如果不解析El可以加<%@page isIgnored="true"%>
SUN公司El函数库:主要都是操作字符串
要导入sun公司EL 函数库
fn:toLowerCae//转小写${fn:toLowerCae("AAAA")}
fn:toUpperCase//转大写
fn:trim//去掉两边的空格
fn:length//返回集合和数组大小,常常和JSTL标签合用
用函数迭代集合:
${list[index]}
如果为NULL,返回0
Fn:split//以字符串种的特定字符分割字符串,返回字符串数组
${fn:split("www.hd.us",".")}
Fn:join//以指定的字符串将某个字符串数组中的所有元素组合成字符串。
String[] arr={"www","hd","us"};
${fn:join(arr,".")}//结果为www.hd.us
应用:检测一个字符串数组中是否包含某个字符串,先组合成字符串,然后检测
Fn:contains//字符串种是否包含指定的字符串,大小写敏感
Fn:containsIgnoreCase//忽略大小写
${fn:contains(fn:join(user.likes,","),"sing")?'checked':''}
Fn:indexOf//返回一个字符在一个字符串种第一次出现的位置
Fn:startsWith//是否以指定字符串开头
Fn:endsWith//是否以指定字符串结尾
Fn:replace("www fn "," ",".")//替换字符串
Fn:subString//截取字符串,从哪儿开始,截取到什么地方(区别于截取多少个)${"www.it315.org",4,9}结果是"it315",从4后开始,包含9
Fn:substringAfter("www.it315.org",".")//"it315.org"
Fu:substirngBefore
Fn:escapeXml("点点")//转义
Jstl标签:
如果servlet将产生的数据封装到集合中返回给jsp。则jsp需要迭代集合,然后显示数据。要用到jstl 标签
使用JSTL标签:
1.导入jar包:jstl.jar;standard.jar
2.用taglib指令导入标签库: uri="" standard.jar---meta-inf----c.tld
Prefix="c"
Jstl+el表达式迭代结合:
${person.name}
JSTL+EL迭代map结合:
${me.key}=${me.value}
欢迎你:${user.username}
案例:注册登陆
Day10:购物车案例
自定义标签:
用于移除jsp中的java代码
使用方法:写一个类实现TAG接口(java代码可以直接放到doStartTag()中,this.pageContex可以直接拿到 pageContext对象,进而拿到其他8大对象),编写TLD文件(参考tomcat/wapps/web-inf/exagmals/jsp2参考头尾)
应用时配置好TLD后,要先倒入标签库, uri是TLD中配置的,prefix是Tld文件名
自定义标签接口,分传统标签TAG和简单标签simpleTag,传统标签已过时(实现不同功能要实现不同接口,学习成本高),开发推荐使用简单标签
传统标签内容:
-------------------------------------------------------
TAG类:可继承子类TagSupport
方法:
setPageContext().//服务器(jsp翻译后的servlet)会调用此方法,将pageContext对象传过来
getParent()//获得父标签,服务器会把父标签的类传进来
setParent()
doStartTag()
doEndTag()
Release()//释放标签所占用的资源
标签处理器类中的所有方法都是由服务器翻译JSP后servlet实例化处理器类对象,
调用setPageContext() 方法,把pageContext()传入;
调用setParent(),传入父标签,没有则传入空对象。
遇到开始标签,执行doStartTag()方法
如果有标签体,执行标签体;
遇到结束标签,执行doEndTag()
标签执行完后,服务器,一般回调release(),释放标签运行占用的资源
接着执行后面的servlet 代码。
自定义标签功能扩展:业务逻辑
1.控制 jsp页面某一部分是否执行:把内容放在标签体中,在处理器类中做逻辑判断,是否输出标签体内容
2.控制整个jsp 页面是否输出:在JSP头上插入一个标签,成立则输出下面的JSP内容。否则不输出
3.控制jsp某部分重复输出:在处理器类中让标签体重复输出
4.修改页面内容:在处理器类中根据逻辑判断变化
控制标签体是否执行:
通过标签处理器类的doStartTag中进行逻辑判断,然后根据需要设置不同的返回EVAL_BODAY_INCLUDE或 SKP_BODY
控制整个JSP是否执行:
写jsp头写个标签,通过标签处理器类的doEndTag中进行逻辑判断,然后根据需要设置不同的返回EVAL_PAGE或 SKP_PAGE
控制标签体重复输出:
可以给处理器类定义一个成员变量记录重复次数
用到Tag的子类IterationTag,也是TagSupport 的父类
IterationTag的方法:doAfterBody()如果返回EVAL_BODY_AGAIN, 标签体重复执行。返回SKIP_BODY则不执行标签体
执行步骤:doStartTag---body doAfterBody----EVAL_BODY_AGAIN----body--doAterBody,不断重复,直到doAfterBody返回值为SKIP_BODY
修改JSP页面输出内容:用到bodyTag类 方法setBodyContent()
EVAL_BODY_BUFFERED
处理器类继承实现类BodyTagSupport
写法:在doStartTag中返回EVAL_BODY_BUFFERED ,在doEndTag中this.BodyContent 拿到数据,修改后输出。
执行步骤:如果doStartTag()返回EVAL_BODY_BUFFERED,则标签体执行完后的结果数据不会直接输出到浏览器,而是存储到bodyContent对象中,传给服务器,服务器自动调用setBodyContent()方法修改修改结果数据
TAG接口的4个常量:
EVAL_PAGE
SKIP_PAGE
EVAL_BODY_INCLUDE//执行标签体
SKIP_BODY// 不执行标签体
-------------------------------------------------------------
简单标签:
注意:
TLD中的
simpleTag接口,实现类simpleTagSupport
方法:
doTag()//处理标签
SetJspBody()//自动将标签体作为JspFragment(JSP片段)传入
setParent()//自动传入父标签
sertJspContent()//自动调用,传入jspContext对象
getParent();
控制标签体是否执行:
doTag()中,this.getJspBody().invoke(null);执行标签体。不执行,则不iinvoke 即可。
标签体重复执行:
Jf.invoke(null); 放在 for 循环中。
修改标签体:拿到标签体,不输出浏览器,输出到一个容器中。 拿到容器数据,修改后,获得流输出
Jf.invoke(new StringWriter());
控制整个JSP是否执行:写一个头标签,doTag中,抛一个SkipPageException异常即可。
带属性的标签:
步骤:在处理器类中定义变量,添加属性的set方法。并在TLD中描述属性
服务器会自动将标签的属性值传给处理器类中的变量
自动将标签中的属性的字符串转为响应的类型(8种基本数据类型)
一个标签,一对
案例:
自定义
自定义迭代标签:迭代出来的数据以var为名,存到pageContext域,执行标签体会自动取出(标签体:this.getJspBody().invoke());
可以迭代任意集合的标签:写一个方法逐个判断 items类型,并将它换算为collection,对collection进行迭代即可,数据存到jspContext,执行标签体获得var的值
注意:对象数组可以arrays.asList直接转,基本数据类型则要for循环后,添加到collection(要写8个if)
数组迭代优化:Array.getLength(items)//得到数组长度,Array.get(items,int),得到每个元素。适用于对象数组和基本数据类型数组
自定义HTML转义标签:
输出HTML标签源码.参考tomcat---util 中的转义方法
将标签体存到StringWriter,调用方法转义后,输出到浏览器
TLD中标签体得四种类型:
Jsp,scriptless,tagdepended(标签体默认是JSP页面的一部分,这个属性是让标签体只给标签用),empty
防盗链:JSp头写一个标签,通过jspContext 拿到request域中的referer头,判断头的内容。(定义2个属性,复用性好)
标签打包技术:
新建一个JAVA项目,导入servlet和JSP的JAR包(tomcat---lib)处理器类拷贝到src,项目下新建一个目录META-INF,TLD文件拷贝到META-INF中,项目右键菜单export导出成jar文件。
使用:导入jar文件,导入标签库,在JSP中使用标签
把项目达成exe文件:先打成 jar,然后变可执行jar(参考tomcat启动JAR文件中的meta-inf中的属性文件的main-class属性),通过exe4j变为exe文件
步骤:
打开jar文件META-INF文件夹,修改属性文件,修改Main-class属性为当前项目的主类完整类名。冒号后要加个空格。
打开lib中的exe4j.exe ,生成exe文件。(可配置图标和启动界面)
Exe运行需要JDK
SUN公司标签库:
可参考jar文件总的TLD(stantard.jar)
核心标签库:c.tld(必学)
国际化标签库fmt.tld(必学)
数据库标签库sql.tld
XML标签x.tld
JSTL函数(EL函数)fn.tld(必学)
核心标签库:
应用:转义
<%
10/0
%>
xxxxxxxx
对不起,没有符合要求的记录
符合要求的记录有${count}条
varStatus用于定义一个变量记录迭代信息。${status.count}可以获得迭代次数
Var是集合中的元素名
${list[num]}
Var是开始和结束数字变量名
可用于分页
Url 地址重写
String ab="a,b,c,d";
${c}
字符分割,然后迭代字符串
WEB开发国际化:
国际化internationalization,也称i18n
合格的国际化软件:固定元素和动态数据都国际化
固定文本元素国际化:
将固定文本根据不同语言写到不同的properties文件中。这一组properties文件称为一个资源包。
javaApi 中的 ResourceBundle类用于描述资源包,getBundle可根据来访者的国家自动获取与之对应的资源包文件予以显示
创建资源包和资源文件:
统一个资源包中的资源文件的基名相同,每个资源包有一个默认的资源文件(默认的不带地区标识符)所有资源文件中属性名都一样
资源文件中不能保存中文,要进行编码,使用JDK中的nativ2ascii工具编码后,将码拷贝到资源文件中
基名_语言代码.properties
Myproperties_zh.properties;myproperties_en.properties;
Myproperties.properties(默认) 没有对应的具体资源文件时,使用默认资源文件
常看语言和国家代码:
IE--------Internet选项----常规----语言---添加
[ar-QA]前面2个小写字母是语言代码,后面2个字母是国家代码
编码:
ResourceBundle bundle=ResourceBundle.getBundle("cn.itcast.resource.MyResource",Local.ENGLISH);
String username=bundle.getString("username");
获取特定国家资源属性,家Local参数,默认资源属性则不用加。
自动获取国家信息request.getLocal()
动态数据国际化: Local 类
数值,货币,时间,日期
日期国际化:DateFormat
可按国家格式输出日期并控制样式
样式控制:SHORT MEDIUM LONG FULL
获取DateFormat 实例9种方式:
getDateInstance(int,locale) 只处理日期部分
getTimeInstance(int,locale)只处理时间部分
getDateTimeInstance(int,int,locale)同时处理日期时间,参数分别是日期样式,时间样式
例子:Date d=new Date();
DateFormat df=DateFormat.getDateInstance(DateFormat.MEDIUM,Locale.CHIESE);
String result=df.format(d);
字符串变日期:
DateFormat的parse 方法。样式要和字符串显示的样式一致。
数字国际化:NumberFormat类
getCurrencyInstance(locale)获取处理指定国家货币的实例
回返回对应货币符号的字符串
Int price=56;
NumberFormat nf=NumberFormat.getCurrencyInstance(Local.CHINA);
String p=nf.format(price);//¥56
将带货币符号的字符串转成数字:parse方法,返回Number类型,调用intValue()等方法可转为 int,double等。
getNumberInstance(locale),getIntergerInstance(),
getPercentInstance(locale)这3个方法没有实际意义。
练习:PPT
多个动态数据的批量国际化:MessageFormat(动态文本国际化)
怎样批量国际化?
将文本中需要国际化得数据用占位符替换(须指定类型样式等)。MessageFormat在输出文本时,可以接受一个参数数组替换文本中的占位符
String p="On {0,time,short},a hurricance destoryed {0,date}";
MessageFormat mf=new MessageFormate(p,Local.CHINA);// 参数(要国际化的文本,国家)
Object params[]={new Date(),99};
String res=mf.format(params); //会返回国际化后的文本(先替换,然后格式化输出)
资源文件的国际化:
String message=ResourceBundle.getBundle("cn.beijing.hd.MyProperties",Local.CHINA).getString("mesage");
Object params={};
MessageFormat mf=new MessageFormate(p,Local.CHINA);
String m=mf.format(params);
HttpUrlConnection类:
模拟浏览器向服务器发请求,并解析响应,显示给浏览器。
拿到HttpUrlConnection,通过将URL的opeenConnection()返回的URLConnction转为HttpUrlConnction。
HttpUrlConnection的getInputStream获得数据流
getResponseCode()
getHeaderField()
getOutputStream()//setDoOutput(true);