u 背景知识介绍
J2EE的13种技术
java->servlet->jsp [技术总是有一个演变过程]
zip粘贴到word设置
u 回顾一下我们现有的技术
java 基础(面向对象,集合,界面,线程,文件,网络)
jdbc (java 的数据库编程)
oracle / mysql / sqlserver
html css javascript (web 开发) ->网页设计
xml
serlvet+jsp ->java web开发[使用java技术做 web开发]
u java ee 体系的介绍
u servlet项目演示
u web 开发介绍
① 静态页面 (html)
② 动态页面
1. 用户可以输入数据,和页面交互(注册,购物,发帖子,付款...)
2. 不同时间打开页面,内容是变化.
3. 目前比较流行的左动态页面的技术 ( servlet/jsp , php , asp.net , asp, cgi )
u 动态网页技术的比较(了解)
u bs 和 cs的比较
(1)BS:browser server 浏览器服务器
(2)cs client server 客户服务
u 为什么需要的web服务器/web究竟是干什么的?
模拟一个web服务器 MyWebServer.java
import java.io.*;
import java.net.*;
public class MyWebServer
{
publicstatic void main(String []args) throws Exception{
ServerSocketss=new ServerSocket(80);
Sockets=ss.accept();
//提示一句话
System.out.println("在 9999 上等待连接...");
OutputStreamos=s.getOutputStream();
BufferedReaderbr=new BufferedReader(new FileReader("d:\\hello.html"));
Stringbuf="";
while((buf=br.readLine())!=null){
os.write(buf.getBytes());
}
//关闭流
br.close();
os.close();
s.close();
}
}
u 通过tomcat来讲解BS结构
u 安装tomcat服务器
(1) 解压即可
(2) 配置
①在环境变量中添加
JAVA_HOME= 指向你的jdk的主目录(并不是bin文件目录)
② 在不配置JAVAHOME的前提下启动tomcat
在startup.bat的第25行中添加set JAVA_HOME=JKD路劲
(3) 启动tomcat服务器
到 tomcat 主目录下 bin/startup.bat
(4) 验证是否安装成功
http://localhost:8080(8080是默认端口如果该端口已经被占用需要修改端口)
u tomcat安装后问题解决
(1)tomcat无法正常启动的原因分析
1. JAVA_HOME 配置错误,或者没有配置
2. 如果你的机器已经占有了8080 端口,则无法启动,
解决方法
(1) 你可以8080 先关闭
netstat –an
netstat –anb 来查看谁占用该8080
(2) 主动改变tomcat的端口.
到conf/server.xml 文件中修改
(3) 能够正常启动,但是会导航到另外一个页面.
去修改工具->管理加载项,把默认的导航给禁用即可.
(4) 在访问 tomcat时候,一定保证 tomcat 服务器是启动
u tomcat的目录结构文件
bin: 启动和关闭tomcat的bat文件
conf: 配置文件
-->server.xml : 该文件用于配置和 server 相关的信息, 比如 tomcat启动端口后,配置Host, 配置Context 即web应用
-->web.xml : 该文件配置与 web应用(web应用就相当于是一个 web站点)
-->tomcat-users.xml: 该文件用户配置tomcat 的用户密码 和 权限
lib 目录: 该目录放置运行tomcat 运行需要的jar包
logs 目录:存放日志, 当我们需要去查看日志的时候,很有用!,当我们启动tomcat错误时候,可以查询信息.
webapps 目录: 该目录下,放置我们的web应用(web 站点), 比如:
建立 web1 目录 下面放置我们的html 文件 jsp 文件..图片... 则 web1就被当做一个web应用管理起来(☞ 特别说明tomcat 6.0以后支持 tomcat 5 版本 还有别的设置)
work: 工作目录: 该目录用于存放jsp被访问后 生成的对应的 server文件 和.class文件
u 如何去访问一个 web 应用的某个文件
u 首页面设置及目录规范结构
现在我们要求:把hello.html文件设置成该 web应用的首页,则需要把web应用的目录格式做的更加规范:
①在web文件夹下配置WEB-INF文件夹
②在 web.xml 文件中添加配置的代码:
③通过http://localhost:8088/web1来访问hello1.html
web-inf目录下的 classes目录将来是存放 class文件
lib 目录将来时存放 jar文件
web.xml 配置当前这个web应用的信息.
u tomcat如何去管理虚拟目录
需求: 当我们把 web 应用放到 webapps目录,tomcat会自动管理,如果我们希望tomcat可以管理其它目录下的web应用?->虚拟目录配置
我在d 盘有一个web应用.
u 虚拟目录配置步骤:
① 找到server.xml文件
② 编辑host节点 添加Context path
在server.xml中添加:<Contextpath="/myweb2"docBase="d:\web2"/>
myweb2:是访问时输入的web名,实际取出的是web2中的资源
"d:\web2":绝对路径下web2中存放资源如:hello2.html
实际访问时输入的地址:http://localhost:8088/myweb2/hello2.html
绝对路径:从根分区找某个文件
相对路径:从该文件位置去找另一个文件
③ 需要重启tomcat,才能生效.(因为是采用的dom技术讲信息加载到内存中)
u context 的几个属性的说明
path:
docbase:
reloadable ;如果设为ture ,表示 tomcat 会自动更新 web应用,这个开销大,建议在开发过程中,可以设为true, 但是一旦真的发布了,则应当设为false;
upackWAR: 如果设为 ture ,则自动解压,否则不自动解压.
①:打war包 cd:d/web2 然后jar –cvf web2.war *
②:
浏览打好的war包 Deploy发布后会在webapps中自动生存改文件
u 配置域名
我们看和一个如何配置自己的主机名:
我们在实际访问网站的过程中,不可能使用http://localhost:8080/web应用/资源名 的方式去访问网站,实际上使用类似
http://www.sina.com.cn 或者
http://news.sina.com.cn 的方式去访问网站,这个又是怎么实现的呢?
看看ie浏览器访问一个web站点的流程.
实现的步骤如下:
(1)在C:\WINDOWS\system32\drivers\etc 下的host文件添加127.0.0.1 www.sina.com.cn
(2) 在tomcat的server.xml文件添加主机名
(3) 在d:\web3 加入了一个 /WEB-INF/web.xml 把 hello2.html设为首页面
如果连端口都不希望带,则可以吧tomcat的启动端口设为80即可.
(4) 重启生效
u tomcat体系的再说明
图:
如何配置默认主机:
在tomcat/conf/server.xml文件
u 为什么需要servlet技术?
比如需求:我们希望用户可以贴,用户还可以回复 ....这样一些和用户可以交互的功能,用普通的java技术就完成不了, sun 就开发了 servlet技术供程序员使用.
u servlet的介绍
① servlet 其实就是java程序(java类)
② 该 java 程序(java 类)要遵循servlet开发规范
③ serlvet是运行在服务端
④ serlvet 功能强大,几乎可以完成网站的所有功能
⑤ 是学习jsp基础
u tomcat 和 servlet 在网络中的位置
u servlet的生命周期是怎样的/servlet究竟是怎样工作的
UML 时序图帮助大家理解
参看execel
面试题: 请简述servlet的生命周期(工作流程)
答:
标准版本:
①WEB服务器首先会检查是否已经装载并创建了该servlet实例对象。如果是直接进行第④步,否则执行第②步。
②装载并创建该Servlet的一个实例对象。
③调用Servlet实例对象的init()方法。
④创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用service()方法并将请求和响应作为参数传递进去。
⑤WEB应用被停止或重启之前,Servlet引擎将卸载Servlet,在卸载之前调用Servlet的destroy()方法
1. 当serlvet 第一次被调用的时候,会触发init函数,该函数会把servlet实例装载到内存.init函数只会被调用一次
2. 然后去调用servlet 的 service 函数
3. 当第二次后访问该servlet 就直接调用 service 函数.
4. 当 web应用 reload 或者 关闭 tomcat 或者 关机 都会去调用destroy函数,该函数就会去销毁serlvet
5. Servlet的生命周期
当客户端第一次向web服务器发出一个servlet请求时,web服务器将会创建一个该servlet的实例,并且调用servlet的init()方法;如果当服务器已经存在了一个servlet实例,那么,将直接使用此实例;然后再调用service()方法,service()方法将根据客户端的请求方式来决定调用对应的doXXX()方法;当 web应用reload 或者 关闭tomcat 或者关机,web服务器将调用destroy()方法,将该servlet从服务器内存中删除。
生命全过程:
1.加载
2.实例化
3.初始化
4.处理请求
5.退出服务
u 开发servlet有三种方法
(1) 实现 Servlet接口
(2) 通过继承 GenericServlet
(3) 通过继承 HttpServlet
u ①实现servlet接口的方式
需求如下: 请使用实现接口的方式,来开发一个Servlet ,要求该Servlet 可以显示Hello,world,同时显示当前时间.
步骤
1. 在webapps下建立一个web应用 hspWeb1
2. 在hspWeb1 下建立 WEB-INF->web.xml[web.xml可以从ROOT/WEB-INF/web.xml拷贝]
3. 在WEB-INF 下建立 classes目录(我们的Servlet 就要在该目录开发.),建立 lib文件夹
4. 开发MyServlet.java
package com.hsp;
import javax.servlet.*;
import javax.servlet.http.*; 为了能将servlet-api.jar包引入,需要配置环境变量
变量值; E:\tomcat\apache-tomcat-6.0.20\lib\servlet-api.jar 记得带上文件名
import java.io.*;
class MyFirstServlet implements Servlet
{
//该函数用于初始化servlet,就是把该servlet装载到内存中
//该函数只会被调用一次
publicvoid init(ServletConfig config)
throws ServletException{
}
//得到ServletConfig对象
publicServletConfig getServletConfig(){
returnnull;
}
//该函数是服务函数,我们的业务逻辑代码就是写在这里
//该函数每次都会被调用
publicvoid service(ServletRequest req,
ServletResponse res)
throws ServletException,
java.io.IOException{
}
//该函数时得到servlet配置信息
publicjava.lang.String getServletInfo(){
returnnull;
}
//销毁该servlet,从内存中清除,该函数被调用一次
publicvoid destroy(){
}
}
5. 根据Servlet规范,我们还需要部署Servlet
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet-name>MyFirstServlet③ <servlet-class>com.hsp.MyFirstServlet注意:后面不要带.java④ <servlet-mapping> <servlet-name>MyFirstServlet② <url-pattern>/ABC①
服务器调用流程:http://localhost:8088/ABC--->①--->②--->③--->④
6. 在浏览器中测试
在浏览器中输入
http://localhost:8088/hspweb1/ABC
7. 分析一下自己写可能出现的错误
(1)
(2)
(3) 资源名自己写错
http://localhost:8088/hspweb1/错误的资源url-pattern
404 错误
补充: 如果使用javac 去编译一个java文件,则需要带命令参数
javac –d . java文件
补充: 如何不重启tomcat,就指定去 reload 一个web应用,方法:
进入到 tomcat 的 manager:
点击reload即可.
课堂练习
自己使用 实现Servlet接口的方法,开发一个Servlet,该servlet 可以输出自己的名字
在显示当前日期.
u ②使用GenericServlet开发servlet
了解即可:
案例 :
package com.hsp;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class MyGenericServlet extends GenericServlet
{
public void service(ServletRequest req,
ServletResponse res)
throws ServletException,
java.io.IOException{
res.getWriter().println("hello,world,iam geneirc servlet");
}
}
将该Servlet部署到web.xml文件中:
u ③使用继承 HttpServlet 的方法来开发Serlvet
(1) 在软件公司 90%都是通过该方法开发.
(2) 举例说明; 还是显示 hello,world 当前日期
代码:
packagecom.hsp;
importjavax.servlet.*;
importjavax.servlet.http.*;
importjava.io.*;
public class MyHttpServlet extends HttpServlet
{
//在HttpServlet 中,设计者对post 提交和 get提交分别处理
//回忆
protectedvoid doGet(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException,
java.io.IOException{
resp.getWriter().println("iam httpServet doGet()");
}
protectedvoid doPost(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException,
java.io.IOException{
resp.getWriter().println("iam httpServet doPost() postname="+req.getParameter("username"));
}
}
还有一个login.html
u:
u 小结 get 提交 和 post的提交的区别
① 从安全看 get ② 从提交内容看 get ③ 从速度看 get>post ④ Get可以保留uri中的参数,利于收藏 u 使用ide来开发servlet 使用ide (eclipse[java se]+myeclipse[插件 可以支持jsp/servlet/struts/hibernate/spring..])开发servlet 需求:使用 ide 开发一个servlet ,该servlet显示 hello,world, 和当前日期 u 开发步骤: (1) 建立web工程 (2) 在Src 目录下创建了一个包 com.hsp.servlet (3) 开发一个Servlet MySerlvet 的代码: publicvoid doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("hello"+newjava.util.Date().toString() ); } publicvoid doPost(HttpServletRequest request,HttpServletResponse response) throwsServletException, IOException { this.doGet(request,response); } (4) 配置tomcat 点击add 选择要发布到那个服务器即可: (5) 启动tomcat 1. 使用我们的老方法 2. 从eclipse 启动 tomcat (6) 在使用eclipse 开发servlet 可能会出现一个很麻烦事情,版本不一致错误. java.lang.UnsupportedClassVersionError: Bad version number in .class file (unableto load class com.hsp.servlet.MyServlet1) 原因是因为 tomcat 使用jdk 和 servlet 使用的 jdk不一样, 解决方法就是统一即可. 请大家使用eclipse 并配置继承 HttpServlet 开发一个servlet, 显示hello, 和当前日期. u Servlet的细节问题 ① 一个已经注册的Servlet可以被多次映射即: <servlet> <description>This is thedescription of my J2EE componentdescription> <display-name>This is thedisplay name of my J2EE componentdisplay-name> <servlet-name>MyServlet1servlet-name> <servlet-class>com.hsp.servlet.MyServlet1servlet-class> servlet>
<servlet-mapping> <servlet-name>MyServlet1servlet-name> <url-pattern>/MyServlet1url-pattern> servlet-mapping> <servlet-mapping> <servlet-name>MyServlet1servlet-name> <url-pattern>/hspurl-pattern> servlet-mapping> ② 当映射一个servlet时候,可以多层 比如 从这里还可以看出,后缀名是 html 不一定就是 html,可能是假象. ③ 使用通配符在servlet映射到URL中 有两种格式: 第一种格式 *.扩展名 比如 *.do *.ss 第二种格式 以 / 开头 同时以 /* 结尾 比如 /* /news/* 通配符练习题: l Servlet1映射到 /abc/* l Servlet2映射到 /* l Servlet3映射到 /abc l Servlet4映射到 *.do 问题(面试题): l 当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应 Servlet引擎将调用Servlet1。 l 当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应 Servlet引擎将调用Servlet3。 l 当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应 Servlet引擎将调用Servlet1。 l 当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应 Servlet引擎将调用Servlet2。 l 当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应 Servlet引擎将调用Servlet2。 在匹配的时候,要参考的标准: (1) 看谁的匹配度高,谁就被选择 (2) *.do 的优先级最低 ④ Servlet单例问题 当Servlet被第一次访问后,就被加载到内存,以后该实例对各个请求服务.即在使用中是单例. 因为 Servlet是单例,因此会出现线程安全问题: 比如: 售票系统. 如果不加同步机制,则会出现问题: 这里我给大家一个原则: (1) 如果一个变量需要多个用户共享,则应当在访问该变量的时候,加同步机制 synchronized(对象){ //同步代码 } (2)如果一个变量不需要共享,则直接在 doGet() 或者 doPost()定义.这样不会存在线程安全问题 ⑤ servlet中的 需求: 当我们的网站启动的时候,可能会要求初始化一些数据,(比如创建临时表), 在比如: 我们的网站有一些要求定时完成的任务[ 定时写日志,定时备份数据.. 定时发送邮件..] 解决方法: 可以通过 先说明 我们来模拟一个定时发送电子邮件的功能: 实现思路: sendEmailTable id content sendtime 1 “hello” 2011-11-11 20:11 2 “hello2” 2012-11-1110:00 看看如何线程去完成任务: 这里的代码请参考项目: SendMailThread.java package com.hsp.model; publicclass SendEmailThread extends Thread{ @Override publicvoid run() { int i=0; try { while(true){ //每休眠一分钟,就去扫表sendmail, 看看那份信件应当被发出 Thread.sleep(10*1000); System.out.println("发出第"+(++i)+"邮件");//javamail } } catch (Exceptione) { e.printStackTrace(); // TODO: handle exception } } } MyInitServlet1.java publicvoid init() throwsServletException { // Put yourcode here System.out.println("MyInitServlet1 的init被调用.."); //完成一些初始化任务 System.out.println("创建数据库,表,读取参数"); //创建一个线程 SendEmailThread sendEmailThread=new SendEmailThread(); sendEmailThread.start(); } 说明:
<load-on-startup>1load-on-startup> u ServletConfig对象 该对象主要用于 读取 servlet的配置信息. 案例: <servlet> <servlet-name>ServletConfigTestservlet-name> <servlet-class>com.hsp.servlet.ServletConfigTestservlet-class> <init-param> <param-name>encodingparam-name> <param-value>utf-8param-value> init-param> servlet> 如何使用 Stringencoding=this.getServletConfig().getInitParameter("encoding"); 补充说明:这种配置参数的方式,只能被某个Servlet独立使用.如希望让所有的Servlet都去读取某个参数,这样配置:
u 如果要把所有的参数都读取,则使用 如下方法 : Enumeration while(names.hasMoreElements()){ String name=names.nextElement(); System.out.println(name); System.out.println(this.getServletConfig().getInitParameter(name)); } 补充,如何去修改Servlet的配置模板. u 编写项目 1. 先完成用户登录 2. 添加在主界面,添加一个超链接,可以返回登录界面重写登录 u http协议的再介绍 ① http协议是建立在tcp/ip协议基础上 ② http协议全称 超文本传输协议 ③ http协议1.0 , 1.1版本 ,目前通用的是1.1版本 http1.0 称为短连接 http1.1 称为长连接. 所谓长,和短指的是 持续时间的 长连接 1.1 30s ,短连接是发送完数据就断掉. u http的请求部分: 基本结构: GET /test/hello.html HTTP/1.1 [请求行] Accept: */* [消息名] 消息名:内容 Referer: http://localhost:8080/test/abc.html Accept-Language: zh-cn User-Agent: Mozilla/4.0 Accept-Encoding: gzip, deflate Host: http://www.sohu.com:80 Connection: Keep-Alive [消息头格式 (消息名: 内容 ) 特别说明: 并不是每一次请求的消息头都一样.] 空行 发送的内容 [格式 : 内容名字=内容体] u 请求方式 请求行中的GET称之为请求方式,请求方式有:POST,GET,HEAD,OPTIONS,DELETE,TRACE,PUT 常用的有:POST,GET u get和post 参看ppt,和以前的笔记 GET News/abc.jsp u http请求消息头 1) Accept: text/html,image/* [告诉服务器,我可以接受文本,网页,图片] 2. Accept-Charset: ISO-8859-1 [接受字符编码 iso-8859-1] 3. Accept-Encoding: gzip,compress [可以接受 gzip,compress压缩后数据.] 4. Accept-Language: en-us,zh-cn [浏览器支持中,英文] 5. Host: www.sohu.com:80 [我要找主机是www.sohu.com:80] 6. If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT [ 告诉服务器,我的缓冲中有这个资源文件,该文件的时间是。。。] 7. Referer: http://www.sohu.com/index.jsp [告诉服务器,我来自哪里,该消息头,常用于防止盗链] 8. User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)[告诉服务器,浏览器内核] 9. Cookie [cookie??] 10. Connection:close/Keep-Alive [保持连接,发完数据后,我不关闭连接] 11. Date: Tue, 11 Jul 2000 18:23:51 GMT [浏览器发送该http请求的时间] 关于Referer的实际案例: //获取用户浏览器Referer String referer=request.getHeader("Referer"); if(referer==null||!referer.startsWith("http://localhost:8088/servletPro")){ response.sendRedirect("/servletPro/Error"); return; } 红色的部分可以根据实际情况来修改. u http的响应 基本结构: 状态行: 格式:HTTP版本号 状态码 原因叙述 举例:HTTP/1.1200 OK 状态码 含义 100-199 表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程 200-299 表示成功接收请求并完成整个处理过程,常用200 300-399 为完成请求,客户需要进行一步细化请求。例如:请求的资源已经移动一个新的地址,常用302,307 400-499 客户端的请求有错误404 500-599 服务器端出现错误,常用500 u http响应的状态行举例说明 200 就是整个请求和响应过程没有发生错误,这个最常见. 302: 表示当你请求一个资源的时候,服务器返回302 表示,让浏览器转向到另外一个资源,比如: response.sendRedirect(“/web应用/资源名”) 案例: response.setStatus(302); response.setHeader("Location", "/servletPro/Servlet2"); // 上面两句话等价 response.sendRedirect("/servletPro/Servlet2"); 404: 找不到资源 500: 服务器端错误 u http响应消息头详解 n Location: http://www.baidu.org/index.jsp 【让浏览器重新定位到url】 n Server:apache tomcat 【告诉浏览器我是tomcat】 n Content-Encoding: gzip 【告诉浏览器我使用 gzip】 n Content-Length: 80 【告诉浏览器会送的数据大小80节】 n Content-Language: zh-cn 【支持中文】 n Content-Type: text/html;charset=GB2312 [内容格式text/html; 编码gab2312] n Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 【告诉浏览器,该资源上次更新时间】 n Refresh: 1;url=http://www.baidu.com 【过多久去,刷新到 http://www.baidu.com】 n Content-Disposition: attachment; filename=aaa.zip 【告诉浏览器,有文件下载】 n Transfer-Encoding: chunked [传输的编码] n Set-Cookie:SS=Q0=5Lb_nQ; path=/search[后面详讲] n Expires: -1[告诉浏览器如何缓存页面IE] n Cache-Control: no-cache [告诉浏览器如何缓存页面火狐] n Pragma: no-cache [告诉浏览器如何缓存页面] n Connection: close/Keep-Alive [保持连接 1.1是Keep-Alive] n Date: Tue, 11 Jul 2000 18:23:51 GMT ①定时刷新Refresh使用 response.setHeader("Refresh","5;url=/servletPro/Servlet2"); ②文件下载Content-Disposition publicvoid doGet(HttpServletRequest request, HttpServletResponseresponse) throwsServletException, IOException { response.setContentType("text/html"); //PrintWriterout = response.getWriter(); //演示下载文件 response.setHeader("Content-Disposition", "attachment; filename=winter.jpg"); //打开文件.说明一下web 站点下载文件的原理 //1.获取到要下载文件的全路径 String path=this.getServletContext().getRealPath("/images/Winter.jpg"); //System.out.println("path="+path); //2创建文件输入流 FileInputStream fis=new FileInputStream(path); //做一个缓冲字节数组 byte buff[]=newbyte[1024]; int len=0;//表示实际每次读取了多个个字节 OutputStreamos=response.getOutputStream(); while((len=fis.read(buff))>0){ os.write(buff, 0, len); } //缺点: 没有进度条./图标/ //关闭 os.close(); fis.close(); } ③缓存讲解 提出问题:浏览器默认情况下,会缓存我们的页面,这样出现一个问题:如果我们的用户习惯把光标停留在地址栏,然后回车来取页面,就会默认调用cache中取数据。 (1) 有些网站要求及时性很高,因此要求我们不缓存页面 代码: //指定该页面不缓存 Ie response.setDateHeader("Expires", -1);【针对IE浏览器设置不缓存】 //为了保证兼容性. response.setHeader("Cache-Control", "no-cache");【针对火狐浏览器等】 response.setHeader("Pragma", "no-cache");【其他浏览器】 (2) 有些网站要求网页缓存一定时间,比如缓存一个小时 response.setDateHeader("Expires", System.currentTimeMillis()+3600*1000*24);后面一个参数表示设置的缓存保持时间,-1表示永远缓存 练习: 加入防止盗链下载. u HttpServletResponse的再说明 getWriter() getOutputStream(); 区别 1. getWriter() 用于向客户机回送字符数据 2. getOutputStream() 返回的对象,可以回送字符数据,也可以回送字节数据(二进制数据) OutputStream os=response.getOutputStream(); os.write("hello,world".getBytes()); 如何选择: 如果我们是回送字符数据,则使用 PrintWriter对象 ,效率高 如果我们是回送字节数据(binarydate) ,则只能使用 OutputStream ☞ 这两个流不能同时使用. 比如: OutputStreamos=response.getOutputStream(); os.write("hello,world".getBytes()); PrintWriter out=response.getWriter(); out.println("abc"); 就会报错: 不能同时使用printWriter和outputstream的原因 Web服务器会自动检查并关闭流 从该图,我们也可以看出. 为什么我们没有主动关闭流,程序也没有问题的原因. 当然:你主动关闭流,更好. u 参数的传递方式sendRedirect()和session() 需求: 当用户登录成功后,把该用户名字显示在登录成功页面; ①使用sendRedirect()来传递字符参数 解决思路: 1. 使用java基础 static 2. 使用sendRedirect() 代码: response.sendRedirect("/UsersManager/MainFrame?uname="+username+"&pwd="+password); 3. 使用session 传递[后面讲] 这里,我们先预热. 说明: 基本格式: response.sendRedirect(“servlet的地址?参数名=参数值&参数名=参数值...”); ☞ 参照值是String , 参数名应当使用 字母组合 在接受数据的Servlet中: String 参数=request.getParameter(“参数名”); ②使用session()来传递字符参数和对象 A.传递字符串 放入session request.getSession.setAttribute("loginUser",username); 取出session 在JSP中通过session取出request.getSession.getAttribute("loginUser"); B.传递对象 User user= new User(); user.setName(“xiaoli”); user.setPassWord(“123”); 放入session request.getSession.setAttribute("userObj",userObj); 取出session User user=(User)request.getSession.getAttribute(“userObj”); 上机练习: 1. 实际运用到项目: 在wel页面中显示登录用户的姓名,就可以使用该方法.让我们动手一起来做做吧! 2. 请写一篇关于HTTP协议的笔记,要求: • 描述清楚HTTP请求头、响应头的格式 • 请求头和响应头中各个头字段的含义 l 如果浏览器传递给WEB服务器的参数内容超过1K,应该使用那种方式发送请求消息? l 请描述200、302、304、404和500等响应状态码所表示的意义。 l 请列举三种禁止浏览器缓存的头字段,并写出相应的 u 中文乱码处理 发生中文乱码有三种情况 ① 表单form (1) post 在服务器端设置成浏览器端的编码方式。 解决方法: request.setCharacterEncoding("utf-8"); //gbk gb2312big5 (2) get 写一个工具类: package com.hsp.utils; publicclass MyTools { publicstatic String getNewString(String str) { String newString=""; try { newString=newString(str.getBytes("iso-8859-1"),"utf-8"); } catch (Exceptione) { e.printStackTrace(); // 把iso-8859-1 转换成 utf-8 } return newString; } } ② 超链接 该方法和get处理方法一样. ③ sendRedirect() 发生乱码 response.sendRedirect(“servlet地址?username=顺平”); ☞版本低导致的乱码 特别说明,如果你的浏览器是 ie6 或以下版本,则我们的 ② 和 ③中情况会出现乱码(当中文是奇数的时候) 解决方法是 : Stringinfo=java.net.URLEncoder.encode("你好吗.jpg", "utf-8"); response.sendRedirect(“servlet地址?username=”+info); 说明: 我们应当尽量使用post 方式提交; ☞返回浏览器显示乱码 在服务端是中文,在response的时候,也要考虑浏览器显示是否正确,一般我们通过 response.setContentType(“text/html;charset=utf-8”); ok ☞下载提示框中文乱码 补充一个知识点: 当我们下载文件的时候,可能提示框是中文乱码 String temp=java.net.URLEncoder.encode("传奇.mp3","utf-8"); response.setHeader("Content-Disposition","attachment;filename="+temp); u HttpServletRequest对象的详解 该对象表示浏览器的请求(http请求), 当web 服务器得到该请求后,会把请求信息封装成一个HttpServletRequest 对象 • getRequestURL方法返回客户端发出请求时的完整URL。 • getRequestURI方法返回请求行中的资源名部分。 • getQueryString 方法返回请求行中的参数部分(参数名+值)。 该函数可以获取请求部分的数据比如 http://localhost/web名?username=abc&pwd=123 request.getQueryString(); 就会得到 username=abc&pwd=123 getRemoteAddr方法返回发出请求的客户机的IP地址 getRemoteHost方法返回发出请求的客户机的完整主机名 getRemotePort方法返回客户机所使用的网络端口号 客户机的端口号是随机选择的,web服务器的端口号是一定的 getLocalPort方法返回web服务器所使用的网络端口号 getLocalAddr方法返回WEB服务器的IP地址。 getLocalName方法返回WEB服务器的主机名 u url 和 uri 的区别 比如: Url=http://localhost:8088/servletPort3/GetinfoServlet完整的请求 Uri=/servletPort3/GetinfoServletweb应用的名称+资源的名称 练习题: 请在服务器这端,给浏览器回送该浏览器发送的具体请求内容是什么? 韩顺平 http://localhost:8088/web名/GetInfoServlet?abc=123&uu=90&iio=中国 大龙 http://localhost:8088/web名/GetInfoServlet?kkk=你好[email protected] 你的请求是 kkk=你好 u 如何获取用户提交的内容(通过表单提交的内容) 代码: 界面: packagecom.hsp; importjava.io.IOException; importjava.io.PrintWriter; importjavax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; publicclass MyInfoForm extends HttpServlet { public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out =response.getWriter(); out.println(" out.println(" out.println("用户名: out.println("密 码: out.println("性 别:男女 out.println("你的爱好:音乐 体育 旅游 out.println("所在城市: out.println("你的介绍: out.println("提交照片: //什么时候使用hidden传输数据 1.不希望用户看到该数据 2. 不希望影响节目,同时使用该数据 out.println(" out.println(""); } public void doPost(HttpServletRequestrequest, HttpServletResponse response) throws ServletException,IOException { this.doGet(request, response); } } 接受信息的Servlet: package com.hsp; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; publicclass RegisterCl extends HttpServlet{ publicvoid doGet(HttpServletRequest request,HttpServletResponse response) throwsServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); String u=request.getParameter("username"); String p=request.getParameter("pwd"); String sex=request.getParameter("sex"); //如果接受复选框的内容,则使用getparameterValues String []hobbies=request.getParameterValues("hobby"); String city=request.getParameter("city"); String intro=request.getParameter("intro"); String hidden1=request.getParameter("hidden1"); out.println("用户名="+u+" out.println("密 码="+p+" out.println("性 别="+sex+" if(hobbies!=null){ for(int i=0;i out.println("爱好:"+hobbies[i]); } }else{ out.println("你没有爱好"); } out.println(" out.println(" out.println(" } publicvoiddoPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException { this.doGet(request,response); } } 练习题:请大家自己写一个表单,提交数据(个人名字:电子邮件: 性别:你喜欢的城市 select(可以选多个): 你的特长 (checkbox) 你的个人签名, 用hidden传输重要数据) u 请求转发requeset.getRequestDispatcher(资源地址).forward(request,response); 资源地址:不需要项目名。因为它只是在WEB服务器内部转发。 Request.getRequestDispatcher(资源地址).forward(request,response); 我们现在使用请求转发的方法来实现上次我们使用 response.sendRedirect() 实现效果 使用 request提供的转发方法. Request中的Attribute在一次请求有效。一次请求:没有返回到浏览器,就为一次请求。 u 请求转发的的(uml)图 这里我们画图说明(uml) 1. 使用 forward 不能转发到该web应用外的 url 2. 因为 forward 是发生在web服务器,所以 Servlet1 和 Servlet 2使用的是用一个request 和response. l 使用sendRedirect() 方法不能通过request.setAttribute() 把 属性传递给下一个Servlet u 比较sendRedirect()和request.getRequestDispatcher().forward(request,response) 请问 sendRedirect() 和 forward 的区别是什么 答: (1) 叫法sendRedirect() 重定向,转发 forward() 叫转向 (2) 实际发生的位置不一样 sendRedirect发生 浏览器 forward 发生 web服务器 (3) 用法不一样 request.getRequestDispatcher(“/资源URI”).forward(request,response) response.sendRedirect(“/web应用/资源URI”); (4) 能够去URL范围不一样 sendRedirect可以去 外边URL forward 只能去当前的WEB应用的资源 ☞ 什么是一次 http请求: 只要没有停止,也没有回到浏览器重定向,就算一次 比如; ☞ 如果转发多次,我们的浏览器地址栏,保留的是第一次 转向的那个ServletUrl 小练习: 使用uml 软件,画出 forward 和sendRedirect() 的流程. u 用户管理系统的继续开发 u 用户管理系统的框架图 用户管理框架图.xls ① 增加到数据库去验证用户功能 (1) 在oracle 数据库中创建一张表 users createtable users (idnumber primary key, usernamevarchar2(32) not null, emailvarchar2(64) not null, gradenumber default 1, passwdvarchar2(32) not null) 初始化一些数据 insertinto users values(1,’aaaaa1’,’[email protected]’,1,’123’); insertinto users values(2,’aaaaa2’,’[email protected]’,1,’123’); insertinto users values(3,’aaaaa3’,’[email protected]’,1,’123’); insertinto users values(4,’aaaaa4’,’[email protected]’,1,’123’); insertinto users values(5,’aaaaa5’,’[email protected]’,5,’123’); (2) 在LoginClServlet 中添加到数据库验证用户的功能. ok: //到数据库中取验证 Connection ct=null; ResultSet rs=null; PreparedStatement ps=null; try { //1加载驱动 Class.forName("oracle.jdbc.driver.OracleDriver"); //2.得到连接 ct=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:ORCLHSP","scott","tiger"); //3.创建PreparedSatement ps=ct.prepareStatement("select * from users where id=? andpasswd=?"); //给? 赋值 ps.setObject(1, id); ps.setObject(2, password); //4.执行操作 rs=ps.executeQuery(); //5.根据结果左处理 if(rs.next()){ //说明该用户合法 request.getRequestDispatcher("/MainFrame").forward(request, response); }else{ request.getRequestDispatcher("/LoginServlet").forward(request, response); } } catch (Exceptione) { e.printStackTrace(); // TODO: handle exception }finally{ //关闭资源 if(rs!=null){ try { rs.close(); } catch(SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } rs=null; } if(ps!=null){ try { ps.close(); } catch(SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } ps=null; } if(ct!=null){ try { ct.close(); }catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } ct=null; } } ② 如果输入的用户id 密码不正确,则给出提示. 课后练习; 参看给出的用户管理开发文档,完成 1, 2, 3 页面功能[分页和安全性暂时不考虑.] ③ 用户管理系统的界面添加图片 ④ 用户管理系统添加分页功能 思路: 定义四个分页变量 pageNow 表示第几页,该变量是由用户来决定,因此变化 pageSize 每页显示几条记录,由程序指定,也可以由用户定制 pageCount 表示共有多少页, 该变量是计算出来->思考 怎样确定 rowCount 共有多少条记录,该变量是查询数据库得到 如何确定pageCount (1) if(rowCount% pageSize==0){ pageCount=rowCount/pageSize; }else{ pageCount=rowCount/pageSize+1; } 试试: 比如 users表 9 条记录 pageSize=3 =>pageCount=3 比如 users表 10 条记录 pageSize=3 =>pageCount=4 (2) 上面的算法等价于 pageCount=rowCount% pageSize==0 ?rowCount/pageSize: rowCount/pageSize+1; 该运算称为三目运算 (3) 更简单的算法是: pageCount=(rowCount-1)/pageSize+1; 试试: 比如 users表 9 条记录 pageSize=3 =>pageCount=3 比如 users表 11 条记录 pageSize=3 =>pageCount=4 回忆: oracle 分页的select 特别说明:如果某个web应用你不需要,请把该web应用从 webapps目录下移走,否则tomcat启动的速度会越来越慢. 上机练习题: 1. 完成自己项目的分页 2. 再做一个 上一页 1 2 3 4 5 6 下一页 当前页/总页数 跳转到 [ ] 页 跳 【如何在servlet中使用js技术】 3. 思考题: 如何控制我们的超链接只显示10页, << 1 2 3 4 5 6 7 8 9 10 >> >> 显示后面的10页 << 显示前10页 如何控制直接输入跳转页的时候,pageNow的值过大的问题? java.lang.IllegalStateException: getOutputStream() has already been called for this response
");
");
");
");
");
");
");
");
");
");
");
所在城市:"+city);
个人介绍:"+intro);
隐藏控件数据:"+hidden1);