1.Catalina_home 环境变量设置问题
该环境变量是用来指定启动服务器程序路径的。
2.get和post请求的区别
如请求方式为get方式,则可以在请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间以&
进行分隔,例如:
GET /mail/1.html?name=abc&password=xyz HTTP/1.1
GET方式的特点:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K。
如请求方式为POST方式,则可以在请求的实体内容中向服务器发送数据,其特点是:传送的数据量是无限制的。
例如用户名和密码就不能用get提交,否在在地址栏可以看到用户名和密码就不安全了。当然可以加密。
在网页开发中,有很多超链接,如果希望点击超链接的同时传递点数据,因为超链接是GET提交,所以可以在超链接后
加?然后后面写上数据,例如要在1.html后面传递用户名和密码。如下:
没有传递数据: <a href="1.html"></a>
传递数据: <a href="1.html?username=abc&password=xyz"></a>
3.http请求头
Accept:用于告诉服务器客户机支持的数据类型。
Accept-Charset:用于告诉服务器客户机采用的编码。
Accept-Encoding:用于告诉服务器客户机支持的数据压缩格式。
Accept-Language:客户机的语言环境。
Host:客户机通过这个告诉服务器想访问的主机名。
If-Modified-Since:客户机通过这个告诉服务器资源的缓存时间。
Referer:客户机通过这个告诉服务器它是从哪个资源来访问服务器的(防盗链)
User-Agent:客户机通过这个头告诉服务器客户机的软件环境。
Connection:请求完后的请求链接状态。
4.http实用头字段
何为断点续传:也就是一次只能传送一部分资源,当资源下载断开,再次下载时,资源会从上次下载
完的地方开始下载。
HTTP请求头字段
Range头指示服务器只传输一部分Web资源。这个头可以用来实现断点续传功能。Range字段可以通过三种
格式设置要传输的字节范围:
Range:bytes=1000-2000 传输范围从1000到2000字节
Range:bytes=1000- 传输Web资源中第1000个字节以后的所有内容
Range:bytes=1000 传输最后1000个字节
5.HTTP响应消息头字段
Accept-Ranges:这个字段说明Web服务器是否支持Range;支持则返回Accept-Ranges:bytes;
如果不支持,则返回Accept-Ranges:none;
Content-Range:指定了返回的Web资源的字节范围。这个字段值的格式是:
例子:Content-Range:1000-3000/5000
Http响应
HTTP/1.1 200 OK //状态行(用于描述服务器对请求的处理结果)
Server:Microsoft-IIS/5.0 //响应头(
Date:Thu,13 Jul 2000 05:46:53 GMT //响应头 响应消息头用于描述服务器的基本信息,
Content-Length:2291 //响应头 以及数据的描述,服务器通过这些数据的
Content-Type:text/html //响应头 描述信息,可以通知客户端如何处理等一会儿它回送的数据
Cache-control:private //响应头)
//一个空行
<HTML>-----------------------------//实体内容(代表服务器向客户端回送的数据)
<BOOY>
.........--------------------------//实体内容(代表服务器向客户端回送的数据)
状态行
格式:HTTP版本号 状态码 原因叙述
响应状态码分为5类:
状态码 含义
100-199 ---------表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程
200-299 ---------表示成功接收请求并已完成整个处理过程,常用200
300-399 ---------为完成请求,客户需进一步细化请求。例如,请求的资源已经移动一个新地址,常用302、307和304,302服务器会返回一个新的地址供客户端去请求,307和304要求客户端去请求缓存。
400-499 ---------客户端的请求有错误,常用404;403客户端没有权限访问资源
500-599 ---------服务器端出现错误,常用500
响应头:
Location:这个头配合302状态码使用,用于告诉客户找谁
Server:服务器通过这个头,告诉浏览器服务器的类型
Content-Encoding:服务器通过这个头,告诉浏览器数据的压缩格式
Content-Length:服务器通过这个头,告诉浏览器回送数据的长度
Content-Type:服务器通过这个头,告诉浏览器回送数据的类型
Last-Modified:服务器通过这个头,告诉浏览器当前资源的缓存时间
Refresh:服务器通过这个头,告诉浏览器隔多长时间刷新一次
Content-Disposition:服务器通过这个头,告诉浏览器以下载方式打开数据
Transfer-Encoding:服务器通过这个头,告诉浏览器数据的传送格式
ETag:缓存相头的头,(实时更新)
Expires:服务器通过这个头,告诉浏览器把回送的资源缓存多长时间,-1或0则是不缓存
Cache-Control:no-cache:
Pragma:no-cache:
服务器通过以上两个头,也是控制浏览器不要缓存数据。
6.常见WEB服务器
WebLogic是目前应用最广泛的Web服务器。Java编程的十三种技术都支持,收费。
Tomcat,该服务器支持全部JSP以及Servlet.
7.什么是WEB服务器
当Ie等浏览器需要访问我们编写的程序时,它必须通过一个网络程序来访问,这个网络程序
就是WEB服务器。
一台电脑上安装了服务程序,就成了服务器。
8.如何减少http请求数减缓服务器压力
可以将几个css文件合并成一个,将几个javascript文件合并成一个等
9.图片如何减少http请求数
在做网站中,假设网页上有7张图片,则至少发起8次请求。如何减少图片请求呢?
可以将图片合成一张大图片,然后显示图片的某一部分就可以了。可以用texturepacker纹理打包
工具,它可以自动将图片合成一张图,并生成一个标注每张图片位置的xml文件。
10.HttpServlet介绍和用法
Servlet接口SUN公司定义了两个默认实现类,分别为:
GenericServlet、HttpServlet
1.HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet
接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。
2.HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内会自动判断用户的请求方式,如为GET请求,则调用
HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或
doPost方法,而不要去覆写service方法。
11.java开发动态网页注册页面添加验证码并点击后刷新验证码
<html>
<head>
<title>register.html</title>
<script>
function changeImage(img){
img.src=img.src+"?"+new Date().getTime();
}
</script>
</head>
<body>
<form action="">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
认证码:<input type="text" name="checkcode"><image src="/day06/servlet/ResponseDemo4" onclick=""http://blog.51cto.com/viewpic.php?refimg=" + this.src=changeImage(this)" style="cursor:hand">//(最后一个style样式是为了当鼠标移动到验证码上时鼠标箭头就变成了小手)
<br/>//src指的是在项目中验证码程序类所在的具体位置。
</form>
</body>
</html>
12.request和response
Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象和代表响应的response对象。
request和response对象既然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了;要向客户机
输出数据,只需要找response对象就行了。
字节流可以写任何类型的数据,字符流只能写字符串
下面代码的问题是:当获取到要输出的内容后,显示在客户机是乱码,原因是当程序运行后,数据先以UTF-8的编码格式将数据编码,
而如果客户端浏览器编码不是UTF-8,而是其他编码则会出现乱码。
public class ResponseDemo1 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setHeader("Content-type","text/html";charset=UTF-8);//解决办法是在响应头里指定打开的编码格式为UTF-8;
String data="中国";
OutputStream out=response.getOutputStream();
out.write(data.getBytes("UTF-8"));//这里是什么编码格式,上面就指定以什么编码打开。
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
在html中有个<meta></meta>标签,这个标签可以模拟http响应头来控制浏览器的行为。
public class ResponseDemo1 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setHeader("Content-type","text/html";charset=UTF-8);
String data="中国";
OutputStream out=response.getOutputStream();
out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());//这句话告诉浏览器以UTF-8的编码格式打开
out.write(data.getBytes("UTF-8"));
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
下面的代码输出1,但是浏览器默认是gb2312编码格式,如果直接是数字1,则按照该编码格式输出的是别的字符:
如下:
public class ResponseDemo1 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
OutputStream out=response.getOutputStream();
out.write(1+"").getBytes();//这里只要将数字变成字符串1就可以正常输出1了。
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
下面是模板代码,以及如何使用?
response.setCharacterEncoding();//该方法可以设置response使用的编码表
response.setHeader("content-type","text/html;charset=UTF-8");//这是告诉浏览器以什么编码打开
上面两行代码可以用下面一行代码替代:response.setContentType("text/html;charset=UTF-8");这行代码内部实现了上面两行代码,但是建议以下写,因为
思路更清晰:
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
13.request简介
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。
Uri可以标识任何资源,URL只能标识互联网资源,下例:
URL:http://www.sina.com/news/1.html
URI:c:\abc\a.txt ;http:/www.sina.com/news/1.html
所以URI是爸爸,URL是儿子。
request常用方法:
获取客户机信息:
getRequestURL方法返回客户端发出请求时的完整URL
getRequestURI方法返回请求行中的资源名部分
(上面的可以设置用户的访问权限,比如根据URL或URI看到访问者要访问的地址,从而设置权限)
getQueryString方法返回请求行中的参数部分
getRemoteAddr方法返回发出请求的客户机的IP地址
getRemoteHost方法返回发出请求的客户机的完整主机名(必须在DNS上注册,否则返回的仍是访问者的IP)
getRemotePort方法返回客户机所使用的网络端口号
getLocalAddr方法返回WEB服务器的IP地址
getLocalName方法返回WEB服务器的主机名
getMethod方法得到客户机请求方式
14.request乱码
<html>
<head>
<title>中文乱码</title>
</head>
<body>
<form action="/day06/servlet/RequestDemo4" method="post">
用户名:<input type="text" name="username" value="">
<input type="submit" name="submit" value="提交">
</form>
<!--超链接提交的中文,服务器想不乱码,也只能手工处理--->
<a href="/day06/servlet/RequestDemo4?username=中国">点点</a>//注意超链接提交方式都是get,所以在中文乱码上应用get乱码解决方式
</body>
</html>
当在上面的输入框中输入中文的时候,发布到服务器,就会显示的是乱码。
request内部用的编码表是Iso8859.
public class RequestDemo4 extends HttpServlet{
public void doGet(HttpSetvletRequest request,HttpServletResponse response)
throws ServletException,IOException{
request.setCharacterEncoding("UTF-8");//解决post提交乱码
String username=request.getParameter("username");
上面的第一行代码只有表单是post提交方式才有效,如果是get提交就无效。
如何解决get出现乱码的问题?先根据乱码,查Iso8859码表,获取到对应数字,最后查UTF-8码表显示数字对应的中文就行了。
new String(username.getByte("iso8859-1"),"UTF-8");//解决get提交乱码(手工处理)
}
public void doPost(HttpSetvletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
15.request实现请求转发和mvc设计模式
request对象实现请求转发:请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。
请求转发的应用场景:MVC设计模式
request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward
方法可以实现请求转发。
request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其它web资源处理。
setAttribute方法
getAttribute方法
removeAttribute方法
getAttributeNames方法
//请求转发,以及使用request域对象把数据带给转发资源
public class RequestDemo5 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
String data="aaaaa";
//request也可实现转发
request.getRequestDispatcher("/messsage.jsp").forward(request,response);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
MVC:M-model,V-view,C-controller
请求转发的细节:
1.forward方法用于将请求转发到RequestDispatcher对象封装的资源。
2.如果在调用forward方法之前,在Servlet程序中写入的部分内容已经被真正地传送到了客户端,
forward方法将抛出IllegalStateException异常。
3.如果在调用forward方法之前向Servlet引擎的缓冲区(response)中写入了内容,只要写入到缓冲区
中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区中的内容
将被清空,但是,已写入到HttpServletResponse对象中的响应头字段信息保持有效。
16.response实现请求重定向和response的一些实现细节
请求重定向:一个web资源收到客户端请求后,通知客户端去访问另外一个web资源
应用场景:用户登录
实现方式:1.response.sendRedirect()
2.实现原理:
302状态码和location头即可实现重定向
public class ResponseDemo7 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setStatus(302);//设置状态码为302
response.setHeader("location","/day06/index.jsp");//定向到该项目下的首页
上面两句代码可以用下面一句代码实现:
response.sendRedirect("/day06/index.jsp");//直接在里面写重定向的地址就可以了。
//重定向向服务器发送两次请求,这会增加服务器负担,所以能不用请求重定向就不用请求重定向。
登录页面要请求重定向的原因是:让地址栏显示登录地址,让用户知道自己登录的位置。
第二个,一个购物网站,假设用户购物后跳到购物车页面,如果用转发的话,当用户刷新页面时,刷新一次
所购买的货物就多购买一次,而这个不是我们所想要的,所以可以用重定向解决这个问题。
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
1.getOutputStream和getWriter方法分别用于得到输出二进制数据、输出文本数据的ServletOutputStream、Printwriter对象。
2.getOutputStream和getWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。
3.Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据
当做响应消息的正文,然后再与响应状态行和响应头组合后输出到客户端。
4.Servlet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,
Servlet引擎将调用close方法关闭该输出流对象。
17.response实现文件下载
public class ResponseDemo3 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
String path=this.getServletContext().getRealPath("/download/1.jpg");
//上面的文件名是数字的,如果文件名是中文的,则文件名需要经过url编码,也就是需要下面一行代码:
// response.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(filename,"UTF-8"));
String filename=path.substring(path.substring(path.lastIndexOf("\\")+1);
response.setHeader("content-disposition","attachment:filename="+filename);
InputStream in=null;
OutputStream out=null;
try{
in=new FileInputStream(path);
int len=0;
byte buffer[]=new byte[1024];
out=response.getOutputStream();
while((len=in.read(buffer))>0){out.write(buffer,0,len);}
} finally{
if(in!=null){
try{
in.close();
}catch(Exception e){
e.printStackTrace();
}
}
if(out!=null){
try{
out.close();
}catch(Exception e){e.printStackTrace();}
}
}
}
}
18.Servlet
publi void service(ServletRequest req,ServletResponse res)这个方法是服务器调用的,
如果调用客户端,则用req;如果向客户端输出,则调用res.将Servlet api.jar所在的路径添加到classpath
19.ServletContext介绍和详细用法
ServletContext就是指本项目的本应用
由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,所以多个Servlet通过ServletContext对象实现数据共享。
ServletContext对象通常也被称为context域对象。
域也就是作用的范围。
注意在项目的src里的文件,通过下面路径获取是错误的,因为编译后src文件夹是不存在的,src里的文件全部在项目对应的文件夹里
错误写法: this.getServletContext().getResourceAsStream("/src/db.properties");
正确写法: this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
上面路径中的第一个/代表当前的项目
假设一个db.properties文件在WebRoot下,路径是"/db.properties".
什么属性用xml文件,什么属性用properties文件来配置保存?
答:xml文件一般用于保存具有关联性的属性,例如:
<中国>
<安徽>
<池州>
</池州>
</安徽>
</中国>
而properties用来保存没有关联的属性,也就是属性之间是独立的关系。
properties文件的读取(下面是模板代码)?
InputStream in=this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties props=new Properties();
props.load(in);
String url=props.getProperty("url");
String username=props.getProperty("username");
String url=props.getProperty("password");
为什么在javaweb里不用FileInputStream读资源文件?
String path="classes/db.properties";
FileInputStream in=new FileInputStream(path);
原因:因为使用的相对路径,当Java虚拟机运行时,其指向的是虚拟机所在的文件夹,也就是说上面的路径指向了
Java虚拟机所在文件夹下的classes/db.properties,因为这个目录下不存在"classes/db.properties"所以出错。
Properties props=new Properties();
props.load(in);
改正:String path="/WEB-INF/classes/db.properties";
String realpath=this.getServletContext().getRealPath(path);//这里获取绝对路径就可以了
FileInputStream in=new FileInputStream(realpath);//这里可以用FileInputStream读取文件了。
Properties props=new Properties();
props.load(in);
两种读取资源文件特征?
InputStream in=this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
Properties props=new Properties();
props.load(in);
上面获取的是资源的流,无法获取资源的文件名。
String path="/WEB-INF/classes/db.properties";
String realpath=this.getServletContext().getRealPath(path);
String filename=realpath.substring(realpath.lastIndexOf("\\")+1);
这里获取到资源的完整路径,可以从完整路径中读到文件名,一般用在文件下载中。
FileInputStream in=new FileInputStream(realpath);
Properties props=new Properties();
props.load(in);
20.web工程中各类地址的写法
项目文件结构:
day06-|
|-src
|-webRoot-|
|-public-|-head.jsp
| |-foot.jsp
|-form1.html
|-form2.html
|-form3.html
|-index.jsp
|-message.jsp
|-register.html
public class ServletDemo1 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
1.所有的地址前都加一个"/"
request.getRequestDispatcher("/form1.html").forward(request,rresponse);
response.sendRedirect("/day06/form1.html");
this.getServletContext().getRealPath("/form1.html");
this.getServletContext().getResourceAsStream("/public/foot.jsp");
<a href="/day06/form1.html">点点</a>
<form action="/day06/form1.html">
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
}
}
获取硬盘资源用反斜杠:"\\",如果是url地址就用"/"
21.WEB应用中的普通java程序如何读取资源文件
假设在src文件夹里有一个UserDao.java和一个db.properties;如何在UserDao类里面读取资源文件?
模板:
public class UserDao{
public void update(){
//用类装载器来读取,但是资源文件不能太大,否则导致内存溢出。
InputStream in=UserDao.class.getClassLoader().getResourceAsStream("db.properties");
Properties prop=new Properties();
prop.load(in);
//以上代码虽然可以读取资源文件的数据,但是无法获取更新后的数据。
}
}
如果资源更新,刷新浏览器后读取到的还是原始的文件,如何资源更新后读取到更新后的内容?
public class UserDao{
public void update() throws IOException{
String path=UserDao.class.getClassLoader().getResource("db.properties").getPath();
FileInputStream in=new FileInputStream(path);
Properties prop=new Properties();
prop.load(in);
//以上代码可以读取到更新后的资源文件。
}
}
22.类继承Servlet后实现的service方法里不显示req和res只显示arg0和arg1的解决办法
在进行服务器开发时,当继承GenericServlet后实现的service(ServletRequest arg0,ServletResponse arg1)让
arg0和arg1变成req和res的解决办法是:从网上先下载tomcat src,然后将其放置到需要的目录中,最后右击项目,
选择buidpath-add external archives-选择tomcat src;最后删除实现的方法重新实现即可
23.类名错误后如何修改
当有类名出现错误时,一般的改法是直接在类上删除错误的类名然后修改,这样的缺点是只能修改本类的
错误,而其它引用该类的则无法修改。
解决办法是:右击该类,选择Refactor-Rename,然后写正确的类名。
这样假设这个类被别人引用了,其它引用的所有类都随之更新。
24.利用referer防盗链
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<a href="/day06/servlet/ResponseDemo6">查看图书</a>
<a href="/day06/servlet/ResponseDemo9">看凤姐</a>
</body>
</html>
public class RequestDemo9 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
String referer=request.getHeader("referer");
if(referer==null || !referer.startsWith("http://localhost")){
response.sendRedirect("/day06/index.jsp");
return;//直接返回到调用处,下面两行代码就不执行了
}
String data="凤姐日记";
response.getWriter().write(data);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
25.输出随机认证码图片
随机图片是用来防止恶意注册的;当我通过浏览器知道输出数据时,就可以编写一个程序用来无限循环达到恶意注册的目的。
图片的识别在计算机领域还是个难点,故可以用来防止恶意注册。
public class ResponseDemo4 extends HttpServlet{
public static final int HEIGHT=35;
public static final int WIDTH=120;
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
BufferedImage image=new BufferedImage(WIDTH,HEIGHT,BufferedImage.Type_INT_RGB);
Graphics g=image.getGraphics();
//1.设置背景色
setBackGround(g);
//2.设置边框
setBorder(g);
//3.画干扰线
drawRandomLine(g);
//4.写随机数
drawRandomNum((Graphics2D)g);
//5.图形写给浏览器
response.setContentType("image/jpeg");//告诉浏览器打开格式
//告诉浏览器不要缓存,因为浏览器默认是缓存的,如果缓存的话,浏览器刷新并不能让验证码刷新。
response.setDateHeader("expries",-1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
ImageIO.write(image,"jpg",response.getOutputStream());
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
public void setBackGround(Graphics g){
g.setColor(Color.WHITE);//设置颜色为白色
g.fillRect(0,0,WIDTH,HEIGHT);//设置白色填充多大范围面积
}
public void setBorder(Graphics g){
g.setColor(Color.BLUE);//重新设置颜色为蓝色
g.drawRect(1,1,WIDTH-2,HEIGHT-2);//解释这样就可以画出一个蓝边框的矩形,矩形应该内缩1这样才能形成蓝边框,而右边应该缩2,因为矩形向右和下移动1个距离后就突出了1距离,要想减掉突出就要减1同时要内缩1才能显示出蓝色。
}
public void drawRandomLine(Graphics g){
g.setColor(Color.GREEN);
for(int i=0;i<5;i++){
int x1=new Random().nextInt(WIDTH);
int y1=new Random().nextInt(HEIGHT);
int x2=new Random().nextInt(WIDTH);
int y2=new Random().nextInt(HEIGHT);
g.drawLine(x1,y1,x2,y2);
}
}
public void drawRandomNum(Graphics2D g){
g.setColor(Color.RED);
g.setFont(new Font("宋体",Font.BOLD,20));
String changyonghanzi="u96d5\u864e\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u9ec4\u4e94\u7b2c\u4f7f\u5199\u519b\u6728\u73cd\u5427\u6587\u8fd0\u518d\u679c\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u6885\u65e5\u51b3\u767e\u539f\u62ff\u7fa4\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u97f3\u7b54\u54e5\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5\u9876\u6025\u6234\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6\u8273\u4f50";
//汉字编码区间[\u4e00-\u9fa5]
int x=5;
for(int i=0;i<4;i++){
int degree=new Random().nextInt()%30;//保证图片旋转角度在-30度到30度之间。当除数大于30则余数为负
String ch=changyonghanzi.charAt(new Random().nextInt(changyonghanzi.length()));
g.rotate(degree*Math.PI/180,x,20);//设置字体旋转的弧度
g.drawString(ch,x,18);//花定义好的文字。
g.rotate(-degree*Math.PI/180,x,20);
x+=30;
}
}
}
26.刷新按钮的作用
刷新按钮的其中一个作用是将上一次执行的程序再执行一次,所以刷新验证码可以得到不同的
27.通过表单收集客户机数据
<html>
<head>
<title>form.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
</head>
<body>
<a href="/day06/servlet/RequestDemo2?username=aaa">点</a>
<form action="/day06/servlet/RequestDemo3" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
性别:<input type="radio" name="gender" value="male">男
<input type="radio" name="gender" value="famale">女<br/>
<select name="city">
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="changsha">合肥</option>
</select><br/>
爱好:<input type="checkbox" name="like" value="sing">唱歌
<input type="checkbox" name="like" value="dance">跳舞
<input type="checkbox" name="like" value="basketball">打篮球
<input type="checkbox" name="like" value="football">踢足球
<br/>
简介:<textarea rows="6" cols="60" name="description"></textarea>
图片:<input type="file" name="image"><br/>
<input type="hidden" name="id" value="123456">
<input type="submit" value="提交"><br/>
</form>
</body>
</html>
public class RequestDemo3 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
request.getParameter("username");
request.getParameter("password");
request.getParameter("gender");
request.getParameter("city");
String likes[]=request.getParameter("likes");
for(int i=0;likes!=null&&i<likes.length;i++){
}
request.getParameter("description");
request.getParameter("id");
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
28.用dos如何进入D盘
1.直接键入 d:即可
先键入cd \
29.用Expires头控制浏览器缓存
假设现在有一个图书的jsp页面,当点击刷新的时候其还在该页面上,那么这就没有必要继续向服务器发送请求了,而是
设置缓存,从缓存中读取是最好的解决办法。
查看缓存:工具-Internet选项-设置-查看文件
public class ResponseDemo6 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setDateHeader("expires",System.currentTimeMillis()+1000*3600);//后面一个是设置缓存的时间
String data="aaaaaaaaaaa";
response.getWriter().write(data);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
30.用refresh控制浏览器定时刷新
public class ResponseDemo5 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setHeader("refresh","3");//这个头是每隔三秒刷新执行一次
String data=new Random().nextInt(1000000)+"";
response.getWriter().write(data);
//假设这是一个用于处理登录的servlet
//假设程序运行到此,用户登录成功
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.setHeader("refresh","3;url='/day06/index.jsp'");//指定刷新时间和执行的页面代码
response.getWriter().write("恭喜你,登陆成功,本浏览器将在3秒后跳到首页")
//上面代码执行后会先输出最后一行字符,然后3秒后跳转到url指向路径所在的页面。
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
31.session对象
1.在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).
因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它
程序可以从用户的session中取出该用户的数据,为用户服务。
2.session和cookie的主要区别在于:
cookie是把用户的数据写给用户的浏览器。
session技术把用户的数据写到用户独占的session中。
3.session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。
当关闭浏览器后,session并没有死,而是30分钟没有人用了才死去。
当浏览器没有关闭后,30分钟没人使用后session也死了。
如果希望控制session的时间,可以在web.xml里添加这样一句代码:
<session-config>
<session-timeout>10</session-timeout>//这里的时间是10分钟,也就是10分钟没有使用,session就销毁了
</session-config>
在程序代码里如何摧毁session?用下面一行代码:
HttpSession session=request.getSession();//这句代码是如果有session就获取session,如果没有session就创建session
request.getSession(false);//这里用false代表我只获取session而不创建session,这句代码一般用在购物车应用上。
//购物车代码只需要获取客户的购买session,而不能帮用户创建session,否则获取不到用户购买的商品了
session.setAttribute("name","洗衣机");
session.invalidate();//用该句代码销毁session.
session实现原理:
浏览器访问服务器,这时服务器创建session,同时为这个session创建一个id,并将这个id以cookie的形式传给浏览器,下次访问服务器的
时候,浏览器会将保存在cookie中session的id号传给服务器,这样服务器就知道浏览器要调用哪一个session了。
但是,这个cookie是没有设置有效期的,这是个问题,当浏览器关闭后,这个cookie就销毁了,再次打开浏览器就创建了新的session;如何解决?
给这个cookie设置个有效期;
public class SessionDemo1 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
HttpSession session=request.getSession();
String sessionid=session.getId();
Cookie cookie=new Cookie("JSESSIONID",sessionid);创建一个与保存session的Id同名的cookie,这样就覆盖掉了原来的cookie
cookie.setPath("/day07");//项目名
cookie.setMaxAge(30*60);//设置cookie的有效时间,这里是想要的
response.addCookie(cookie);
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
32.会话技术全面介绍
什么是会话?会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程
称之为一个会话。
会话过程中要解决的一些问题?
1.每个用户与服务器进行交互过程中,各自会有一些数据,程序要想办法保存每个用户的数据.
例如:用户点击超链接通过一个Servlet购买了一个商品,程序应该保存用户购买的商品,以便于用户点结账servlet时,结账
servlet可以得到用户商品为用户结账。
保存会话数据的两种技术:
1.Cookie
Cookie是客户端技术,程序把每个用户数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的
web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。
2.Session
Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于
session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器
中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
33.session工作原理
如果用户将cookie给禁用了,那客户保存的商品就无法显示和传递,这个问题要解决,否则就流失客户,如何解决呢?
不同的用户在访问首页的时候,给其创建一个session,在每个超链接后给每个用户带上session的id,当点击超链接后,将session的id就带到别的
页面上了。
//首页
public class WelcomeServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out=response.getWriter();
request.getSession();//创建session
String url1=response.encodeURL("/day07/servlet/SessionDemo1");//将其编码后,会自动带上session的id
String url2=response.encodeURL("/day07/servlet/SessionDemo2");//将其编码后,会自动带上session的id
//因为是同一个session,所以url1和url2里后面跟的session的id号相同
out.print("<a href='>"+url1+"'>购买</a>");
out.print("<a href='"+url2+"'>结账</a>");
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
当浏览器不禁用cookie后,用上面的代码后,超链接后面就不会跟session的id了,因为浏览器识别
到有session被带过来了。
34.session的一些细节问题
一个浏览器开启一个网站,假设开启该网站的多个页面,则其共享的是同一个session
但不同的浏览器有不同的做法。
35.客户端防表单重复提交和服务器端session防表单重复提交
<html>
<head>
<title>form.html</title>
<script type="text/javascript">
var iscommitted=false;
function dosubmit(){
if(!iscommitted){
iscommitted=true;
return true;
}else{ return false;}
}
//表单提交后,将提交按钮设置为不能点击
function dosubmit(){
var input=document.getElementById("submit");
input.disabled='disabled';
return true;//让表单提交一下
}
</script>
</head>
<body>
<form action="/day06/servlet/DoFormServlet" method="post" onsubmit="dosubmit()">//onsubmit通过绑定的函数提供的布尔值来控制是否提交表单(通过
//在某个绑定的函数中返回false来防止触发浏览器的默认行为)
用户名:<input type="text" name="username">
<input id="submit" type="submit" value="提交">
</form>
</body>
</html>
//处理表单请求
public class DoFormServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
String usrname=request.getParameter("username");
//由于网络延迟,当表单提交后,数据不是立即就提交的,这时用户就以为表单没有提交,于是重复点击提交按钮,这样实际上提交了很多次,该服务器中的代码也将
//会被执行很多次;如何解决重复提交?第一种是用javascript;但是这种提交有很多问题,当有人通过查看源代码知道提交路径后,其将js代码删除再提交后,可以达到他想要的结果。
//用js,用户刷新页面也可以重复提交,可以后退再次提交;虽然防不死,但是还是用js防止重复提交,因为这样给用户的体验好
System.out.println("向数据库中注册...");
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
//服务器端如何防止表单重复提交
public class DoFormServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
//产生随机数(表单号)
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
class TokenProcessor{//令牌,用来识别;为了保证唯一,令牌必须设置成单例的
//一个对象产生随机数的唯一的概率高于多个对象产生随机数的唯一的概率
}
36.利用session完成用户登录
<html>
<head>
<title>login.html</title>
</head>
<body>
<form action="/day07/servlet/LoginServlet" method="post">
用户名:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
public class LoginServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out=response.getWriter();
String username=request.getParameter("username");
String password=request.getParameter("password");
List<User> list=DB.getAll();
for(User user:list){
if(user.getUsername().equals(username) && user.getPassword().equals(password)){
//登录成功
request.getSession().setAttribute("user",user);//登录成功,向session中存入登录标记
//跳转到首页,用重定向要用户知道其所在的位置
response.sendRedirect("/day07/index.jsp");
return;
}
}
out.write("用户名或密码不对!!");
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
//模拟数据库
class DB{
public static List list=new ArrayList();
static{
list.add(new User("aaa","123"));
list.add(new User("bbb","123"));
list.add(new User("ccc","123"));
}
public static List getAll(){
return list;
}
}
//模型
public class User{
private String username;
private String password;
public User(){super();}//无参构造
public User(String username,String password){//有参构造
super();
this.username=username;
this.password=password;
}
public String getUsername(){return username;}
public void setUsername(String username){this.username=username;}
public String getPassword(){return password;}
public void setPassword(String password){this.password=password;}
}
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
欢迎您:$(user.username)//后面的是取出session中的username
<a href="/day07/servlet/LogoutServlet">退出登录</a>
</body>
</html>
//LogoutServlet
//完成用户注销
public class LogoutServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
HttpSession session=request.getSession(false);
if(session==null){
response.sendRedirect("/day07/index.jsp");
return;
}
session.removeAttribute("user");
response.sendRedirect("/day07/index.jsp");
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
37.利用session校验图片认证码
1.在提交表单之前做验证,首先从客户端获取输入的验证码内容
2.在生成验证码的代码里,生成验证码的同时将验证码保存到session中;
最后将客户端输入的验证码内容与保存在session中的验证码内容比较,如果相同就提交
38.用session实现简单的购物
在实际开发中用cookie比较多,因为如果用session的话,假设网站访问量很大的话,则网站则需要针对每个访问者创建一个
session,这样服务器就面临着巨大的压力。大型的购物网站用的是cookie做。
在实际开发中,不是将用户购买的商品一次次的加到session中,而是将用户购买的商品添加到一个集合中,然后将集合添加到
session中
public class ButServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
String id=request.getParameter("id");
Book book=(Book)Db.getAll().get(id);
HttpSession session=request.getSession();
//从session得到用户用于保存所有书籍的集合(购物车)
List list=(List)session.getAttribute("list");
if(list==null){
list=new ArrayList();
session.setAttribute("list",list);
}
list.add(book);
//转发,就是当点击刷新的时候将上次做的事情重做了一遍,也就是将购买的书再购买一次
//request.getRequestDispatcher("/servlet/ListCartServlet").forward(request,response);
//重定向
response.sendRedirect(request.getContextPath()+"/servlet/ListCarServlet");//里面的request.getContextPath()是将路径定义到项目的根目录
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
//显示用户购买的商品
public class ButServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;chatset=UTF-8");
PrintWriter out=response.getWriter();
HttpSession session=request.getSession(false);
if(session==null){
out.write("您没有购买任何商品");
return;//若return了下面的代码就不执行了。
}
out.write("您购买了如下商品:<br/>");
List list=(List)session.getAttribute("list");
for(Book book:list){
out.write(book.getName());
}
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
39.cookie细节
1.一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE).
2.一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie.
3.浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
4.如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),
用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位
的时间。将最大时效设为0则是命令浏览器删除该cookie.
5.注意,删除cookie时,path必须一致,否则不会删除。
40.cookie案例-显示用户上次访问网站的时间
javax.servlet.http.Cookie类用于创建一个Cookie,response接口中也定义了一个addCookie方法,它用于在其响应头中增加一个相应的
Set-Cookie头字段。同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie.
public class CookieDemo1 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out=response.getWriter();
out.print("您上次访问时间是:<br/>");//浏览器只认识html语言,所以换行用html的换行语言
//获得用户的时间cookie
Cookie cookies[]=request.getCookies();
for(int i=0;cookies!=null&&i<cookies.length;i++){
if(cookies[i].getName().equals("lastAccessTime")){
long cookieValue=Long.parseLong(cookies[i].getValue);
Date date=new Date(cookieValue);
out.print(date.toLocalString());//将时间转为我们认识的时间,而不是外国人认识的时间
}
}
//给用户回送最新的访问时间
Cookie cookie=new Cookie("lastAccessTime",System.currentTimeMillis()+"");
cookie.setMaxAge(1*30*24*3600);//设置cookie的有效时间
cookie.setPath("/day07");//如果不设的话,默认是保存在当前服务器下
response.addCookie(cookie);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
41.cookie显示用户上次浏览过的商品
以后会学过滤器的,只要设置了过滤器,就可以解决乱码问题了。
//代表首页的servlet
public class CookieDemo3 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out=response.getWriter();
1.输出网站所有商品
out.write("本网站有如下商品:");
Map<String,Book> map=Db.getAll();
for(Map.Entry<String,Book> entry:map.entrySet()){
Book book=entry.getValue();
out.print("<a href='/day06/servlet/CookieDemo4?id="+book.getId()+"' target='_blank'>"+book.getName()+"</a><br/>");
}
2.显示用户曾经看过的商品
out.print("<br/>您曾经看过如下商品:<br/>");
Cookie cookies[]=request.getCookies();
for(int i=0;cookies!=null&&i<cookies.length;i++){
if(cookies[i].getName().equals("bookHistory")){
String ids=cookies[i].getValue();
String ids[]= ids.split("\\,");//以逗号分割,前面的两个斜杠是防止歧义的。
for(String id: ids){
Book book =(Book) Db.getAll().get(id);
}
}
}
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
class Db{
private static Map<String,Book> map=new LinkedHashMap();//LinkedHashMap()保证了按照顺序将数据添加进map中,如果没有Linked则数据的顺序是随机的
static{
map.put("1",new Book("1","javaweb开发","老张","一本好书!!"));
map.put("2",new Book("2","jdbc开发","老张","一本好书!!"));
map.put("3",new Book("3","spring开发","老张","一本好书!!"));
map.put("4",new Book("4","struts开发","老张","一本好书!!"));
map.put("5",new Book("5","android开发","老张","一本好书!!"));
}
public static Map getAll(){return map;}
}
class Book{
private String id;
private String name;
private String author;
private String description;
public Book(){super();}
public Book(String id,String name,String author,String description){
super();
this.id=id;
this.name=name;
this.author=author;
this.description=description;
}
public String getId(){return id;}
public void setId(String id){this.id=id;}
public String getName(){return name;}
public void setName(String name){this.name=name;}
public String getAuthor(){return author;}
public void setAuthor(String author){this.author=author;}
public String getDescription(){return description;}
public void setDescription(String description){this.description=description;}
}
//显示商品详细信息的servlet
public class CookieDemo4 extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out=response.getWriter();
//根据用户带过来的id,显示相应商品的详细信息
String id=request.getParameter("id");
Book book=(Book)Db.getAll.get(id);
out.write(book.getId()+"<br/>");
out.write(book.getAuthor()+"<br/>");
out.write(book.getName()+"<br/>");
out.write(book.getDescription()+"<br/>");
//构建cookie,回写给浏览器
String cookieValue=buildCookie(id,request);
Cookie cookie=new Cookie("bookHistory",cookieValue);
cookie.setMaxAge(1*30*24*60*60);
cookie.setPath("/day06");
response.addCookie(cookie);
}
private String buildCookie(String id,HttpServletRequest request){
//bookHistory=null
//bookHistory=2,5,1
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doGet(request,response);
}
}
42.MyEclipse如何生成get和set方法
右击--选择source--generrate getter and setter
43.div和css
控制边框粗细:border-top;border-right;border-bottom;border-left
控制内容和盒子的距离:padding-top;padding-right;padding-bottom;padding-left
控制两个盒子之间的距离:margin-top;margin-right;margin-bottom;margin-left
两种定位技术:float和position
如果前面的div float了,则下一行的div也会受其影响跟着浮动,要使其不受影响,应该清除掉浮动。
下面是没有清除前实例:
<html>
<head>
<title>div浮动引发的问题</title>
</head>
<style>
body{margin:0px 1px 2px 3px;}
#father{background-color:#ffff99;width:100%;height:100px;border:1px dashed green;}
#son1{float:left;}
#son2{float:left;}
#son3{float:left;}
#clear{clear:both;}
</style>
<body>
<div id="father">
<div id="son1">aaaaaa</div>
<div id="son2">bbbbbb</div>
<div id="son3">cccccc</div>
<div id="clear"></div><!--如果要消除上面div对son4块的影响,这里需要清除一下浮动影响,这样下面的块区就不会受到上面的影响了-->
<div id="son4">dddddd</div><!--son4没有浮动,但它会受上面浮动的影响,也跟着浮动了-->
</div>
</body>
</html>
相对定位规定的是绝对定位的父亲,绝对定位规定的是子相对于父亲的位置。
假如在一张图片的右下角显示四个字----芙蓉姐姐
如果用浮动技术的话太麻烦,所以最好用绝对定位
下示例代码:
<html>
<head>
<title>绝对定位</title>
</head>
<style>
#image{position:relative;background-image:url(girl.jpg);width:600px;height:480px;}
#name{position:absolute;right:30px;bottom:30px;font-size:30px;color:red;font:bold;}//只有父容器有了相对定位,子才有绝对定位
</style>
<body>
<div id="image">
<div id="name">芙蓉姐姐</div>
</div>
</body>
</html>
display:inline;表示几个div内容显示成一行
display:none;表示隐藏该区块内容,比如点击某个按钮后下列内容消失
<style>
body{margin:0px;padding:0px;}//模板
</style>
overFlow:hidden;//去掉页面滚动条
网页的宽度最好设置在960-1002之间
44.EL表达式和JSTL标签快速入门
EL表达式用于获取数据,在JSP页面中可使用${标识符}的形式,通知JSP引擎调用pageContext.findAttribute()方法,以标识符
为关键字从各个域对象中获取对象。如果域对象中不存在标识符所对应的对象,则返回结果为""(注意,不是null).
EL表达式中也可以使用$(customerBean.address)的形式来访问JavaBean对象的属性。
结合JSTL标签,EL表达式也可轻松获取各种集合中的元素。
EL表达式也可使用类如${1==1}的形式进行简单的逻辑判断。
<html>
<head>
<title>EL表达式</title>
</head>
<body>
<%
String data="abcd";
request.setAttribute("data",data);
%>
${data} <!--相当于pageContext.findAttribute("data") page request session application-->
-----------如何操作对象属性---------
<%
Person p=new Person();
p.setName("aaa");
request.setAttribute("person",p);
%>
&{person.name}
-----------如何操作对象中的一个类属性的属性------
<%
Person p1=new Person();
Address a=new Address();
a.setCity("上海");
p1.setAddress(a);
request.setAttribute("p1",p1);
%>
${p1.address.city}
--------------如何操作一个集合-----------
<%
List list=new ArrayList();
list.add(new Person("aaa"));
list.add(new Person("bbb"));
list.add(new Person("ccc"));
request.setAttribute("list",list);
%>
${list[1].name}
-------------如何操作Map-------------
<%
Map map=new HashMap();
map.put("aa",new Person("aaa"));
map.put("bb",new Person("bbb"));
map.put("cc",new Person("ccc"));
map.put("dd",new Person("ddd"));
map.put("1111",new Person("eeeee"));//注意这里的key是数字
request.setAttribute("map",map);
%>
${map.aa.name}
${map.1111.name}<%!--这里会报异常,所以map的key最好不要用数字,如果要用最好在前面带字母--%>
${map['1111'].name}<%!--如果非要数字,需呀这么写--%>
-------------得到项目的根目录-----------------
${pageContext.request.contextPath}<%!--得到/day09--%>
作用:在编写项目时项目名称可能是一个,但是到项目发布后又是另一个名称,如果项目里有很多链接,则链接的所有路径的
根目录都得修改,这样太麻烦了,所以根路径最好动态获取:
<a href="${pageContext.request.contextPath}/index.jsp">点点</a>
</body>
</html>
JSTL标签库
使用JSTL可以在页面中实现一些简单的逻辑,从而替换页面中的脚本代码。
在页面中使用JSTL标签需完成以下2个步骤:
1.导入jstl.jar和standerd.jar这两个JSTL的jar文件。
2.在JSP页面中使用<%@ tablib url="" prifix=""%>元素导入标签库
JSTL标签库中常用标签:
<c:foreach var="" items="">
<c:if test="">
将JSTL两个jar文件拷贝到WebRoot-WEB_INF-lib中,最后打开standard.jar的最后一个找到c.tld
在里面找到uri;假设uri="http://java.sun.com/jsp/jst1/core"
则在jsp页面中:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page import="cn.itcast.domain.Person"%>
<html>
<head>
<title>使用jstl+el完成集合迭代</title>
</head>
<body>
<%
List list=new ArrayList();
list.add(new Person("aaa"));
list.add(new Person("bbb"));
list.add(new Person("ccc"));
request.setAttribute("list",list);
%>
--------------迭代--------------------------
<c:forEach var="person" items="${list}">
${person.name}<br/>
</c:forEach>
----------------map---------------------------
<%
Map map=new HashMap();
map.put("a",new Person("aaa"));
map.put("b",new Person("bbb"));
map.put("c",new Person("ccc"));
map.put("d",new Person("ddd"));
map.put("111",new Person("eee"));
request.setAttribute("map",map);
%>
<c:forEach var="entry" items="${map}">
${entry.key}: ${entry.value.name}<br/>
<c:forEach>
--------------------if---------------
<c:if test="${user!=null}">//如果用户对象不为空,也就是用户登录了,执行标签内代码
欢迎您:${user.username}
</c:if>
<c:if test="${user==null}">
如果用户没有登录,则在这里应该跳出登录页面
</c:if
</body>
</html>
45.include指令
1.include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet.所以include指令引入通常也称之为静态引入。
语法:
<%@ include file="relativeURL"%>
其中的file属性用于指定被引入文件的路径。路径以"/"开头,表示代表当前web应用。
细节:
1.被引入的文件必须遵循JSP语法。
2.倍引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见名知意,JSP规范建议使用.jspf作为静态引入
文件的扩展名。
3.由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外).
在WebRoot里新建一个名为public的文件夹,用来存放一些所有jsp页面公共的东西,比如页头或页脚;
<html>
<head>
<title>include指令</title>
</head>
<body>
<%@ include file="/public/head.jsp" %>
aaaaaaaaaa<br/>
<%@ include file="/public/foot.jsp" %>
</body>
</html>
在head.jsp里:
这是页头<br/>
在foot.jsp里:
这是页脚<br/>
46.jsp入门和jsp运行原理
jsp技术允许在页面中编写java代码,并且允许开发人员在页面中获取request、response等
web开发常用对象,实现与浏览器的交互,所以jsp也是一种动态web资源的开发技术。
当写好jsp文件,在浏览器访问该jsp文件时,服务器会自动将jsp文件翻译成一个servlet.
不管是jsp还是servlet,虽然都可以用于开发动态web资源,但由于这2门技术各自的特点,在
长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把jsp技术作为
数据显示模板来使用。
原因:
1.让jsp既用java代码生成动态数据,又做美化会导致页面难以维护.
2.让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。
3.因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,
并把数据通过转发技术带给jsp,数据的显示jsp来做。
47.jsp语法
jsp脚本表达式用于将程序数据输出到客户端
语法:<%=变量或表达式 %>
举例:当前时间:<%= new java.util.Date() %>
JSP脚本表达式中的变量或表达式后面不能有分号(;).
JSP脚本片段用于在JSP页面中编写多行Java代码。
语法:
<%
多行java代码
%>
1.注意:JSP脚本片断中只能出现java代码,不能出现其它模板元素,
JSP引擎在翻译JSP页面中,会将JSP脚本片断中的Java代码将被原封不动
地放到Servlet的_jspService方法中。
2.JSP脚本片断中的Java代码必须严格遵循Java语法,例如,每执行语句后面
必须用分号(;)结束。
JSP脚本片断
1.在一个JSP页面中可以有多个脚本片断,在两个或多个脚本片断之间可以嵌入
文本、HTML标记和其他JSP元素。
举例:
<%
int x=10;
out.println(x);
%>
<p>这是JSP页面文本</p>
<%
int y=20;
out.println(x);
%>
2.多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况。
如:
out.println(x);
3.单个脚本片断中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须
是完整的Java语句,例如:
<%
for(int i=1;i<5;i++)
{
%>
<h1>www.it315.org</h1>
<%
}
%>
JSP声明
1.JSP页面中编写的所有代码,默认会翻译到servlet的service方法中,而Jsp声明中的Java
代码被翻译到Service方法的外面。
语法:
<%!
java代码
%>
例如:
<%!
public void run(){}//这样JSP代码就可以自己写方法了。如果没有!,则是JSP代码片段,其会
//被翻译到Service方法中
%>
2.所以,JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法。
3.多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明
中。
4.JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式
对象。
JSP注释
JSP注释的格式:
<%--注释信息--%>
JSP引擎在将JSP页面翻译成Servlet程序时,忽略JSP页面中被注释的内容。
48.jsp常用标签
<body>
<jsp:forward page="/servlet/ServletDemo1">
<jsp:param name="username" value="xxxxxx">
</jsp:forward>
</body>
跳转到ServletDemo1并且带去一个名为username,值为xxxxxx的参数
在servlet中可以通过getPara("username")获取到该参数的值。
映射:
在web.xml里
<servlet>
<servlet-name>xxx</servlet-name>
<jsp-file>/14.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>xxx</servlet-name>
<url-pattern>15.html</url-pattern>
</servlet-mapping>
49.jsp的page语法
如何修改myEclipse中代码的模板?
先找到myEclipse安装位置,然后在左下角的【全部或部分文件名】里输入【servlet.java】,
然后查看servlet所在的目录,进到该目录下后会发现一个【Jsp.vtl】,新建项目后的模板就是根据该
文件创建的。进去后将【pageEncoding="UTF-8"】,其它不需要的可以根据自己的需要来修改。
JSP指令是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。
在JSP 2.0规范中共定义了三个指令:
1.page指令
2.include指令
3.taglib指令<%--用来导入标签库的--%>
JSP指令的基本语法格式:
<%@ 指令 属性名="值" %>
举例:<%@ page contentType="text/html,charset=gb2312"%>
如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。
例如:
<%@ page contentType="text/html,charset=gb2312"%><%--告诉tomcat如何处理jsp页面--%>
<%@ page import="java.util.Date"%>
也可以写作:
<%@ page contentType="text/html;charset=gb2312" import="java.util.Date"%>
page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个
JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
可以在一条page指令的import属性中引入多个类或包,其中的每个包或类之间使用逗号分隔:
<%@ page import="java.util.Date,java.sql.*,java.io.*"%>
如果在JSP页面中指定session="true",则当jsp被翻译成servlet时会自动创建一个session
<%@ page language="java" import="java.util" pageEncoding="UTF-8" session="true"%>
<%@ page [errorPage="relative_url"]>
1.errorPage属性的设置值必须使用相对路径,假设在WebRoot下新建一个文件夹叫errors里面有一个error.jsp文件,
如果指定当程序出错时跳转到该页面,则<%@ page [errorPage="/errors/error.jsp"]>
2.可以在web.xml文件中使用<error-page>元素为整个WEB应用程序设置错误处理页面,其中的<exception-type>子元素
指定异常类的完全限定名,<location>元素指定以"/"开头的错误处理页面的路径。
3.如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用
一个WEB应用可能有很多的jsp页面,如果给所有的jsp页面指定错误处理太麻烦,所以可以在web.xml里为所有的jsp文件指定一个
全局的错误处理:
<error-page>
<exception-type>java.lang.ArithmeticException</exception-type>//指定异常
<location>/errors/error.jsp<location>//该异常产生后执行的jsp
<error-page>
当用户访问网站时,其可能会在地址栏输入一堆乱七八糟的东西,这时最好提醒用户您访问的资源不存在
<error-page>
<error-code>404</error-code>//指定错误代码数字
<location>/errors/404.jsp</location>//在404.jsp中写入【对不起,您访问的资源不存在!】
//500.jsp【对不起,服务器内部出现问题】
<error-page>
<%@ page isErrorPage="true"%>//指定是错误处理页面。当这个属性置为true时,异常错误信息就会传递到错误处理页面
使用page指令解决JSP中文乱码
1.Jsp程序存在有与Servlet程序完全相同的中文乱码问题
输出响应正文时出现的中文乱码问题
读取浏览器传递的参数信息时出现的中文乱码问题
2.Jsp引擎将JSP页面翻译成Servlet源文件时也可能导致中文乱码问题
jsp引擎将Jsp源文件翻译成的Servlet源文件默认采用UTF-8编码,而JSP开发人员可以采用各种字符集编码来编写JSP源文件,
因此,JSP引擎将JSP源文件翻译成Servlet源文件时,需要进行字符编码转换。
如果JSP文件中没有说明它采用的字符集编码,JSP引擎将它当做默认的ISO8859-1字符集编码处理。
3.如何解决JSP引擎翻译JSP页面时的中文乱码问题?
1.通过page指令的contentType属性说明JSP源文件的字符集编码
2.page指令的pageEncoding属性说明JSP源文件的字符集编码。
tomcat6后基本上没有乱码问题了,
<%@ page pageEncoding="gb2312" contentType="text/html;charset="gb2312""%>
//前一个属性告诉服务器以什么码表编译jsp文件,后一个告诉浏览器以什么码表打开。两者码表是一致的
50.jsp九大隐式对象
request\response\session\application\config\page\out\exception\pageContext
1.out隐式对象用于向客户端发送文本数据
2.out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法
返回的PrintWriter对象非常相似
3.JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page
指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
4.只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过
该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
设置page指令的buffer属性关闭了out对象的缓存功能
out对象的缓冲区已满
整个JSP页面结束
下面的代码,先输出response.getWriter().write("wowowo");的内容;然后输出out.write("hahaha");的内容;原因是out.
write()先要输入缓冲中才输出。
<%
out.write("hahahahah");
response.getWriter().write("wowowowo");
%>
jsp中的文本都是以out.write()输出的,因为有缓冲所以先输出response.getWriter().write("wowowowo");然后输出aaaaaa
<body>
aaaaaaaaaaa//jsp中的文本以out.write()输出
<%
response.getWriter().write("wowowowo");
%>
</body>
51.jsp开发模式和web计算器案例
SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一种是JSP+JavaBean模式,一种是Servlet+JSP+JavaBean模式。
JSP+JavaBean模式适合开发业务逻辑不太复杂的web应用程序,这种模式下,JavaBean用于封装业务数据,JSP即负责处理用户请求,又显示
数据。
Servlet+JSP+JavaBean(MVC)模式适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp负责数据显示,javabean负责封装
数据。
Servlet+JSP+JavaBean模式程序各个模块之间层次清晰,web开发推荐采用此种模式。
在做小数的精确运算时,不适合运用double,因为运算结果有所省略;例如银行存款的运算,运用这种显然不合适;这时Java api提供了一个BigDecimal类
来做精确运算。
例:public class Demo1{
public static void main(String[] args){
/* double a=0.1;
double b=0.006;
System.out.println(a+b);*/
---------------输出可能是:0.1060000001等
--------如果用上面浮点运算来计算,得到的结果并不是精确的---解决办法是用BigDecimal类
BigDecimal a=new BigDecimal("0.01");
BigDecimal b=new BigDecimal("0.013243454556564");
System.out.println(a.add(b).toString());
---------------输出结果是:0.023243454556564
System.out.println(a.divide(b));----这句输出假设输出的是无限小数则抛出异常,所以最好限制小数的范围。
a.divide(b,10,BigDecimal.ROUND_HALF_UP);---后两个参数第一个是保留小数点后10位有效数字,最后一个参数是当第十一个数字超过五时第十位数就加1
}
}
如何判断下拉列表的值:
<select name="one">
<option value="+"></option>
<option value="-"></option>
<option value="*"></option>
<option value="/"></option>
</select>
当表单提交后,显示在下拉列表框中的值就会传递出去成为该下拉选项的值,当然应该有一个名为one的属性来接收该
下拉的值,也就是select的name.
52.jsp与javabean
什么是javaBean?
JavaBean是一个遵循特定写法的Java类,它通常具有如下特点:
1.这个Java类必须具有一个无参的构造函数
2.属性必须私有化
3.私有化的属性必须通过public类型的方法暴露给其它程序,并且方法
的命名也必须遵守一定的命名规范。
JavaBean在J2EE开发中,通常用于封装数据,对于遵循以上写法的JavaBean组件,其它程序
可以通过反射技术实例化JavaBean对象,并且通过反射那些遵守命名规范的方法,从而获知JavaBean
的属性,进而调用其属性保存数据。
在JSP中使用JavaBean
JSP技术提供了三个关于JavaBean组件的动作元素,即JSP标签:
1.<jsp.useBean>标签:用于在JSP页面中查找或实例化一个JavaBean组件。
用于在指定的域范围内查找指定名称的JavaBean对象:
1.如果存在则直接返回该JavaBean对象引用。
2.如果不存在则实例化一个新的JavaBean对象并将它以指定的名称存储到指定的域范围中。
常用语法:
<jsp:useBean id="beanName" class="package.class"
scope="page|request|session|application">
id属性用于指定JavaBean实例对象的引用名称和其存储在域范围中的名称。
class属性用于指定JavaBean的完整类名(即必须带有包名);
scope属性用于指定JavaBean实例对象所存储的域范围,其取值只能是page、request、session和application等
四个值中的一个,其默认值是page.
day09-|
|-src-|
|-cn.itcast.domain-|-Person.java
public class Person{
private String name;
private int age;
public String getName(){ return name;}
public void setName(String name){this.name=name;}
public int getAge(){ return age;}
public void setAge(int age){this.age=age;}
}
<html>
<head>
<title>jsp:usebean标签的使用</title>
</head>
<body>
<jsp:useBean id="person" class="cn.itcast.domain.Person" scope="page"></jsp:useBean>
<%= person.getName() %>
</body>
</html>
2.<jsp:setProperty>标签:用于在JSP页面中设置一个JavaBean组件的属性。
语法格式:
<jsp:setProperty name="beanName"
property="propertyName" value="{string | <%=expression%>}"|
property="propertyName" [param="parameterName"] |
property="*"
/>
name属性用于指定JavaBean对象的名称。
property属性用于指定JavaBean实例对象的属性名。
value属性用于指定JavaBean对象的某个属性的值,value的值可以是字符串,也可以是表达式。为字符串时,该值会自动
转化为JavaBean属性相应的类型,如果value的值是一个表达式,那么该表达式的计算结果必须与所要设置的JavaBean属性
的类型一致。
param属性用于将JavaBean实例对象的某个属性值设置为一个请求参数值,该属性同样会自动转换成要设置的JavaBean属性的类型。
day09-|
|-src-|
|-cn.itcast.domain-|-Person.java
public class Person{
private String name;
private int age;
private Date birthday;
public String getName(){ return name;}
public void setName(String name){this.name=name;}
public int getAge(){ return age;}
public void setAge(int age){this.age=age;}
}
<html>
<head>
<title>jsp:setProperty标签</title>
</head>
<body>
<jsp:useBean id="person" class="cn.itcast.domain.Person"/>
<jsp:setProperty name="person" property="name" value="xxxxx"/>
<%=person.getName()%>
<!--用请求参数给bean的属性赋值 请求参数:http://localhost:8080/day09/2.jsp?name=uuuuuu-->
<jsp:setProperty name="person" property="name" param="name">//后面一个是以请求参数为name赋值
<%=person.getName()%><!--请求参数是name=uuuuu,所以这里输出的也是uuuuuu-->
<jsp:setProperty name="person" property="age" param="age"><!--请求参数提交的是字符串,其在这里会自动将字符串数据转换成8种基本的数据类型附加到属性上-->
//但是日期不是基本的数据类型,该如何通过请求参数附加到属性上呢?
<jsp:setProperty name="person" property="birthday" value="<%=new Date()%>">//如果获取请求参数用request.getParameter();
//<!--用所有的请求参数为bean赋值-->
<jsp:setProperty name="person" property="*"/>
</body>
</html>
3.<jsp:getProperty>标签:用于在JSP页面中获取一个JavaBean组件的属性。
53.pageContext对象
pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境。
1.这个对象不仅封装了对其它8大隐式对象的引用。
通过pageContext获得其它对象
getException()返回exception隐式对象
getPage()返回page隐式对象
getRequest()返回request隐式对象
getResponse()返回response隐式对象
getServletConfig()返回config隐式对象
getServletContext()返回application隐式对象
getSession()返回session隐式对象
getOut()返回out隐式对象
pageContext的这些方法获取对象用在自定义标签开发技术里面。
2.它自身还是一个域对象,可以用来保存数据。
3.并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转
其它资源、检索其它域对象中的属性等。
54.sun公司jstl标签库
由于MVC架构,数据库处理,XML处理都是在servlet里处理的,所以这两个的标签库不用学了。
只学:核心标签库、国际化标签、JSTL函数(EL函数)
c.tld核心标签
fnt.tld国际化标签
fn.tld el函数标签
sql.tld sql标签
x.tld xml标签
55.标签简介和第一个标签
自定义标签主要用于移除jsp页面中的java代码
要使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤:
1. 编写一个实现Tag接口的java类,把页面java代码移到这个java类中(标签处理器类);
2.编写标签库描述符(tld)文件,在tld文件中对标签处理器类描述成一个标签。
1.创建一个包【web.tag】,然后新建一个类来继承 【TagSupport】,然后在类里右击--选择【Override/Implement Methods】---选择需要覆盖或实现的方法即可
public class ViewIPTag extends TagSupport{
public int doStartTag() throws JspException{
HttpServletRequest request=(HttpServletRequest)this.pageContext.getRequest();
JspWriter out=this.pageContext.getOut();
String ip=request.getRemoteAddr();
try{
out.print(ip);
}catch(IOException e){
throw new RuntimeException(e);
}
return super.doStartTag();
}
}
在WEB-INF目录下新建一个文件【itcast.tld】,然后打开tomcat所在目录\webapps\examples\WEB-INF\jsp2\jsp2-example-taglib.tld*
打开该文件,然后从头抄到第一个tag标签。
<taglib>
<description>A tag library exercising SimpleTag handlers.</description>
<tlib-version>1.0</tlib-version>
<short-name>itcast</short-name>//给个简称
<uri>/itcast</uri>//给个uri
<tag>
<name>ViewIP</name>
<tag-class>cn.itcast.web.tag.ViewIPTag</tag-class>
<body-content>empty</body-content>
</tag>
</taglib>
最后在需要引用上面java代码的jsp文件里导入标签:
<%@ taglib uri="/itcast" prefix="itcast"%>//prefix最好与标签文件名相同
<html>
<head>
<title>one</title>
</head>
<body>
您的ip是:<itcast:ViewIP/>//给个该简称里的名为ViewIP的标签
</body>
</html>
56.传统标签库JSP2.0之前
JSP与javascript是两种语言
JSP引擎在遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法。
1、public void setPageContext(PageContext pc),JSP引擎实例化标签处理器后,将调用setPageContext方法将JSP页面
的pageContext对象传递给标签处理器,标签处理器以后可以通过这个pageContext对象与JSP页面进行通信。
2、public void setParent(Tag t),setPageContext方法执行完后,WEB容器接着调用的setParent方法将当前标签的父标签
传递给当前标签处理器,如果当前标签没有父标签,则传递给setParent方法的参数值为null.
3、public int doStartTag(),调用了setPageContext方法和setParent方法之后,WEB容器执行到自定义标签的开始标记时,就会
调用标签处理器的doStartTag方法。
4、public int doEndTag(),WEB容器执行完自定义标签的标签体后,就会接着去执行自定义标签的结束标记,此时,WEB容器
会去调用标签处理器的doEndTag方法。
5、public void release(),通常WEB容器执行完自定义标签后,标签处理器会驻留在内存中,为其它请求服务器,直至停止web 应用时,
web容器才会调用release方法。
开发人员在编写Jsp页面时,经常还需要在页面中引入一些逻辑,例如:
控制jsp页面某一部分内容是否执行。
控制整个jsp页面是否执行。
控制jsp页面内容重复执行。
修改jsp页面内容输出。
自定义标签除了可以移除jsp页面中的java代码外,它也可以实现以上功能。
控制jsp页面某一部分内容是否执行。
只需要在doStartTag()里返回不同就可以控制某部分输出;当返回SKIP_BODY则不执行;当返回EVAL_BODY_INCLUDE则执行
public class TagDemo1 extends TagSupport{
public int doStartTag() throws JspException{
return Tag.EVAL_BODY_INCLUDE;
}
}
tld文件中添加描述:
<tag>
<name>tagdemo1</name>
<tag-class>web.tag.TagDemo1</tag-class>
<body-content>JSP</body-content>//标签体是一段jsp内容
</tag>
在jsp中:
<%@ taglib uri="/itcast" prefix="itcast"%>
<html>
<head>
<title>使用标签控制页面内容是否输出</title>
</head>
<body>
<itcast:tagdemo1>aaaaaaa</itcast:tagdemo1>
</body>
</html>
控制整个jsp页面是否执行。
用doEndTag()方法;return Tag.EVAL_PAGE则余下的页面将继续被计算执行;return Tag.SKIP_PAGE则余下的部分不执行;
public class TagDemo2 extends TagSupport{
public int doEndTag() throws JspException{
return Tag.EVAL_PAGE;//余下将继续被执行计算
}
}
tld文件中描述:
<tag>
<name>demo2</name>
<tag-class>web.tag.TagDemo2</tag-class>
<body-content>empty</body-content>
</tag>
jsp页面中:
<%@ taglib uri="/itcast" prefix="itcast"%>
<itcast:demo2>
<html>
<head>
<title>使用标签控制页面是否输出</title>
</head>
<body>
</body>
</html>
控制jsp页面内容重复执行。
public class TagDemo3 extends TagSupport{
int x=5;
public int doStartTag() throws JspException{
return Tag.EVAL_BODY_INCLUDE;
}
public int doAfterBody() throws JspException{
x--;
if(x>0){
return IterationTag.EVAL_BODY_AGAIN;
}else{
return IterationTag.SKIP_BODY;
}
}
tld描述文件里:
<tag>
<name>demo3</name>
<tag-class>web.tag.TagDemo3</tag-class>
<body-content>JSP</body-content>
</tag>
在jsp文件中:
<%@ taglib uri="/itcast" prefix="itcast"%>
<html>
<head>
<title>two</title>
</head>
<body>
<itcast:demo3>
This is my JSP page.<br/>
</itcast:demo3>
</body>
</html>
修改jsp页面内容输出
public class TagDemo4 extends BodyTagSupport{
public int doStartTag() throws JspException{
return BodyTag.EVAL_BODY_BUFFERED;
}
public int doEndTag() throws JspException{
BodyContent bc=this.getBodyContent();
String content=bc.getString();
content=content.toUpperCase();
try{
this.pageContext.getOut().write(content);
}catch(IOException e){
throw new RuntimeException(e);
}
return Tag.EVAL_PAGE;
}
}
tld文件中:
<tag>
<name>demo4</name>
<tag-class>web.tag.TagDemo4</tag-class>
<body-content>JSP</body-content>
</tag>
jsp页面中:
<%@ taglib uri="/itcast" prefix="itcast"%>
<html>
<head>
<title>5.jsp</title>
</head>
<body>
<itcast:demo4>
aaaaaa
</itcast:demo4>
</body>
</html>
tld文件中的四种标签体类型
EMPTY JSP scriptless tagdepentend
上面的内容是JSP2.0之前的内容,在JSP2.0之后提供了SimpleTag接口来完成传统标签的功能;学习传统标签库是因为后期很多框架的编写
用到了传统标签库来编写的,所以学习后对后期学习框架很有帮助。
57.打包自己的标签库
自己开发的标签有很多,可能在这个项目中使用,也可能在别的项目中使用,如何将这些标签打包成一个库,然后可以在
想要使用的项目中使用?
建一个java工程----->将所有的标签处理器类都拷贝src下包里去(报错不用理睬,继续)---->新建一个META-INF文件夹将tld文件拷贝进去
---导出----Java--jar文件--选择项目---项目右边的配置文件全部不能选----JAR file(打成jar包文件保存路径和名)----finish--ok---ok就行了
如果某个项目想用:将jar包复制到Lib下,最后在jsp文件中导入就可以了
58.简单标签库功能详解
1.控制标签体是否执行
public class SimpleTagDemo1 extends SimpleTagSupport{
public vid doTag() JspException,IOException{//当doTag方法里不写一行代码,也就是方法里什么也不干,就可以实现标签体不执行;当标签体有代码时标签体就执行了
JspFragment jf=this.getJspBody();
jf.invoke(this.getJspContext().getOut());
}
}
在simpleitcast.tld描述文件中:
<taglib>
<description>A tag library exercising SimpleTag handlers.</description>
<tlib-version>1.0</tlib-version>
<short-name>itcast</short-name>//这个标签里的内容改不改无所谓
<uri>/simpletag</uri>//要改
<tag>//里面标签都要改
<name>demo1</name>
<tag-class>cn.itcast.web.simpletag.SimpleTagDemo1</tag-class>
<body-content>scriptless</body-content>//简单标签有标签体不能写JSP,而要写scriptless
</tag>
</taglib>
jsp页面中:
<%@ taglib uri="/simpletag" prefix="sitcast"%>
<html>
<head>
<title>用简单标签控制是否执行标签体</title>
</head>
<body>
<sitcast:demo1>
aaaaaaa
</sitcast:demo1>
</body>
</html>
2.标签体重复执行:
public class SimpleTagDemo2 extends SimpleTagSupport{
public void doTag() throws JspException,IOException{
JspFragment jf=this.getJspBody();
for(int i=0;i<5;i++){
jf.invoke(null);//默认写给浏览器,相当于jf.invoke(this.getJspContext().getOut())
}
}
simpleitcast.tld文件中:
<tag>
<name>demo2</name>
<tag-class>cn.itcast.web.simpletag.SimpleTagDemo2</tag-class>
<body-content>scriptless</body-content>
</tag>
在jsp页面中:
<%@ taglib uri="/itcast" prefix="simcast"%>
<html>
<head>
<title>two</title>
</head>
<body>
<simcast:demo2>This is my JSP page.</simcast:demo2>
</body>
</html>
3.修改标签体内容
public class SimpleTagDemo3 extends SimpleTagSupport{
public void doTag() throws JspException,IOException{
JspFragment jf=this.getJspBody();
StringWriter sw=new StringWriter();
jf.invoke(sw);
String content=sw.toString();
content=content.toUpperCase();
this.getJspContext().getOut().write(content);
}
}
在simpleitcast.tld文件中:
<tag>
<name>demo3</name>
<tag-class>cn.itcast.web.simpletag.SimpleTagDemo3<tag-class>
<body-content>scriptless</body-content>
</tag>
在Jsp页面中:
<%@ taglib uri="/itcast" prefix="simitcast"%>
<html>
<head>
<title>3</title>
</head>
<body>
<simitcast:demo3>aaaaaaaaa</simitcast:demo3>
</body>
</html>
4.控制余下JSP内容不执行:
public class SimpleTagDemo4 extends SimpleTagSupport{
public void doTag() throws JspException,IOException{
throw new SkipPageException();//只要抛出这个异常余下的Jsp内容就不执行了
}
}
在simpleitcast.tld文件中:
<tag>
<name>demo4</name>
<tag-class>cn.itcast.web.simpletag.SimpleDemo4</tag-class>
<body-content>empty</body-content>
</tag>
在Jsp页面中:
<%@ taglib uri="/itcast" prefix="simitcast"%>
<simitcast:demo4/>
<html>
<head>
<title>4.jsp</title>
</head>
<body>
aaaaaaaaa
</body>
</html>
jsp在遇到简单标签,先实例化标签处理器类,然后用该实例化标签处理器类去调用setJspContext将pageContext传递给标签处理器类,然后调用
setParent(),然后调用setJspBody()返回标签体,最后执行doTag()方法执行标签体内容
简单标签体与传统标签体区别在于:传统标签在执行完标签后对象不摧毁驻留在内存中为下一次请求服务;而简单标签在标签执行完后就摧毁了。
59.开发foreach标签
只能迭代list:
public class ForeachTag extends SimpleTagSupport{
private Object items;
private String var;
public void setItems(Object items){this.items=items;}
public void setVar(String var){this.var=var;}
public void doTag() throws JspException,IOException{
List list=(List)items;
Iterator it=List.iterator();
while(it.hasNext()){
Object value=it.next();
this.getJspContext().setAttribute(var,value);
this.getJspBody().invoke(null);
}
}
}
在tld文件中描述:
<tag>
<name>foreach</name>
<tag-class>web.tag.example.ForeachTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
在Jsp页面中导入标签:
<%@ taglib uri="/example" prefix="c"%>
<body>
<%
List list=new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
%>
<c:foreach var="str" items="${list}">${str}</c:foreach>
</body>
可以迭代list,map等集合:
public class ForeachTag2 extends SimpleTagSupport{
private Object items;
private String var;
private Collection collection;
public void setItems(Object items){this.items=items;
if(itmes instanceof Collection){collection=(Collection) items;}
if(items instanceof Map){Map map=(Map) items;
collection=map.entrySet();
}
if(items instanceof Object[]){
Object obj[]=(Object[]) items;
collection=Arrays.asList(obj);
}
if(items.getClass().isArray()){
this.collection=new ArrayList();
int length=Array.getLength(items);
for(int i=0;i<length;i++){
Object value=Array.get(items,i);
this.collection.add(value);
}
}
}
public void setVar(String var){this.var=var;}
public void doTag() throws JspException,IOException{
Iterator it= this.collection.iterator();
while(it.hasNext()){
Object value=it.next();
this.getJspContext().setAttribute(var,value);//获取Jsp内容,在Jsp内容中设置属性
this.getJspBody().invoke(null);
}
}
}
<tag>
<name>foreach2</name>
<tag-class>web.tag.example.ForeachTag2</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>items</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
60.开发if-else标签
第一个标签处理器类:
public class ChooseTag extends SimpleTagSupport{
private boolean isDo;
public boolean isDo(){ return isDo;}
public void setDo(boolean isDo){this.isDo=isDo;}
public void doTag() throws JspException,IOException{
this.getJspBody().invoke(null);
}
}
第二个标签处理器类:
public class WhenTag extends SimpleTagSupport{
private boolean test;
public void setTest(boolean test){this.test=test;}
public void doTag() throws JspException,IOException{
ChooseTag parent=(ChooseTag)this.getParent();//获取父标签
if(test && !parent.isDo()){
this.getJspBody().invoke(null);
parent.setDo(true);
}
}
}
第三个标签处理器:
public class OtherWiseTag extends SimpleTagSupport{
public void doTag() throws JspException,IOException{
ChooseTag parent=(ChooseTag)this.getParent();
if(!parent.isDo()){this.getJspBody().invoke(null);
parent.setDo(true);
}
}
}
在tld描述文件中:
<tag>
<name>choose<name>
<tag-class>web.tag.example.ChooseTag</tag-class>
<body-content>scriptless</body-content>
</tag>
<tag>
<name>when<name>
<tag-class>web.tag.example.WhenTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>otherwise<name>
<tag-class>web.tag.example.otherwiseTag</tag-class>
<body-content>scriptless</body-content>
</tag>
Jsp页面中:
<%@ taglib uri="/example" prefix="c"%>
<body>
<c:choose>
<c:when test="${user!=null}">aaaaa</c:when>
<c:otherwise>bbbbb</c:otherwise>
</c:choose>
</body>
61.开发if标签
public class IfTag extends SimpleTagSupport{
private boolean test;
public void setTest(boolean test){
this.test=test;
}
public void doTag() throws JspException,IOException{
if(test){
this.getJspBody().invoke(null);
}
}
}
在tld描述文件中
<tag>
<name>if</name>
<tag-class>web.tag.example.IfTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>test</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
在Jsp中:
<%@ taglib uri="/example" prefix="c"%>
<body>
<c:if test="${user==null}">aaaaaaa</c:if>
</body>
62.开发带属性的标签
1.自定义标签可以定义一个或多个属性,这样,在JSP页面中应用自定义标签时就可以设置这些属性的值,通过这些属性为标签处理器传递
参数信息,从而提高标签的灵活性和复用性。
2.要想让一个自定义标签具有属性,通常需要完成两个任务:
2.1在标签处理器中编写每个属性对应的setter方法
public class SimpleTagDemo5 extends SimpleTagSupport{
private int count;
privvate Date date;
public void setCount(int count){
this.count=count;
}
public void setDate(Date date){
this.date=date;
}
public void doTag() throws JspException,IOException{
JspFragment jf=this.getJspBody();
this.getJspContext().getOut().write(date.toLocaleString()+"<br/>");
for(int i=0;i<count;i++){
jf.invoke(null);
}
}
}
2.2在TLD文件中描述标签的属性
<tag>
<name>demo5</name>
<tag-class>cn.itcast.web.simpletag.SimpleTagDemo5</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>count</name>//属性名
<required>true</required>//该属性是必须的吗
<rtexprvalue>true</rtexprvalue>//这个标签是用来指定count的值类型的,如果是false则值只能是数字;如果是
//true可以是数字可以是各种表达式
</attribute>
<attribute>
<name>date</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
在Jsp页面中:
<%@ taglib uri="/simpletag" prefix="simitcast"%>
<html>
<head>
<title>5.jsp</title>
</head>
<body>
<simitcast:demo5 count="3" date="<%=new Date() %>">//count的值会传给标签处理器,仅支持八种基本数据类型,八种基本数据类型可以自动转为标签处理器需要的八种类型
//,如果是日期则需要是表达式
aaaaaa
</simitcast:demo5>
</body>
</html>
3.为自定义标签定义属性时,每个属性都必须按照JavaBean的属性命名方式,在标签处理器中定义属性名对应的setter方法,用来
接收JSP页面调用自定义标签时传递进来的属性值。例如属性url,在标签处理器类中就要定义相应的setUrl(String url)方法。
4.在标签处理器中定义相应的set方法后,JSP引擎在解析执行开始标签前,也就是调用doStartTag方法前,会调用set属性方法,为
标签设置属性。
tld中描述标签属性attribute:
description 不是必须指定 用于描述属性的描述信息
name 必须指定 用于指定属性名称。属性名称是大小写敏感的,并且不能以jsp、_jsp、java和sun开头
required 不是必须指定 用于指定在JSP页面中调用自定义标签时是否必须设置这个属性;默认是false,
表示可以设置也可以不设置;true表示必须设置
rtexprvalue 不是必须指定 默认值是false,表示只为该属性指定静态文本值;true表示可以为该属性指定一个JSP动态元素
动态元素的结果作为属性值,例如JSP表达式<%=value%>
type 不是必须的 用于指定属性值的Java类型//该属性不用
63.开发防盗链标签
public class RefererTag extends SimpleTagSupport{
private String site;
private String page;
public void setSite(String site){
this.site=site;
}
public void setPage(String page){
this.page=page;
}
public void doTag() throws JspException,IOException{
// 1.得到来访者referer
PageContext pageContexgt=(PageContext)this.JspContext();
HttpServletRequest request=(HttpServletRequest)pageContext.getRequest();
HttpServletResponse response=(HttpServletResponse)pageContext.getResponse();
//1.得到来访问者的referer
String referer=request.getHeader("referer");
if(referer==null|| !referer.startWith(site)){
if(page.startsWith(request.getContextPath())){
response.sendRedirect(page);
}else if(page.startsWith("/")){
response.sendRedirect(request.getContextPath()+page);
}else{
response.sendRedirect(request.getContextPath()+"/"+page);
}
throw new SkipPageException();
}else{
}
}
}
在example.tld描述文件中:
<taglib>
<description>11</description>
<tlib-version>1.0</tlib-version>
<short-name>new</short-name>
<uri>/example</uri>
<tag>
<name>referer</name>
<tag-class>web.simpletag.RefererTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>site</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>page</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
在Jsp页面中:
<%@ taglib uri="/example" prefix="e"%>
<e:referer site="http://localhost" page="index.jsp"/>
<html>
<head>
<title>11</title>
</head>
<body>
xxxxxxxxxxxxxxxxxx
</body>
</html>
64.开发转义标签
转义技术用在:论坛(输出原始的东西,防止注入)
<%@ taglib uri="/example" prefix="c"%>
<body>
<c:htmlfilter>//输出<a href="">点点</a>
<a href="">点点</a>
</c:htmlfilter>
</body>
public class HtmlFilterTag extends SimpleTagSupport{
public void doTag() throws JspException,IOException{
StringWriter sw=new StringWriter();
JspFragment jf=this.getJspBody();
jf.invoke(sw);
String content=sw.getBuffer().toString();
content=filter(content);
this.getJspContext().getOut().write(content);
}
public static String filter(String message) {
if (message == null)
return (null);
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuffer result = new StringBuffer(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());
}
}
在tld文件中描述
65.转义标签使用的方法
tomcat-webapps-examples-WEB-INF-classes-util-HTMLFilter.java