韩顺平servlet笔记(必看完整版).doc
u 背景知识介绍J2EE的13种技术java->servlet->jsp 技术总是有一个演变过程zip粘贴到word设置u 回顾一下我们现有的技术java 基础(面向对象,集合,界面,线程,文件,网络)jdbc (java 的数据库编程)oracle / mysql / sqlserverhtml 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, cgi )u 动态网页技术的比较(了解)u bs 和 cs的比较(1)BS:browser server 浏览器服务器(2)cs client server 客户服务u 为什么需要的web服务器/web究竟是干什么的?模拟一个web服务器 MyWebServer.javaimport java.io.*;import .*;public class MyWebServerpublic static void main(String args) throws ExceptionServerSocket ss=new ServerSocket(80);Socket s=ss.accept();/提示一句话System.out.println("在 9999 上等待连接.");OutputStream os=s.getOutputStream();BufferedReader br=new BufferedReader(new FileReader("d:hello.html");String buf=""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 文件中修改<Connector connectionTimeout="20000" port="8088" (去修给config->server.xml的端口号)protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443"/>(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 文件中添加配置的代码: <welcome-file-list> <welcome-file>hello1.html</welcome-file> </welcome-file-list>通过http:/localhost:8088/web1来访问hello1.htmlweb-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中添加:<Context path="/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应用/资源名 的方式去访问网站,实际上使用类似 或者 的方式去访问网站,这个又是怎么实现的呢?看看ie浏览器访问一个web站点的流程.实现的步骤如下:(1) 在C:WINDOWSsystem32driversetc 下的host文件 添加127.0.0.1 (2) 在tomcat 的server.xml文件添加主机名 <Host name="" appBase="d:web3”><Context path="/" docBase="d:web3" /></Host>(3) 在d:web3 加入了一个 /WEB-INF/web.xml 把 hello2.html设为首页面如果连端口都不希望带,则可以吧tomcat的启动端口设为80即可.(4) 重启生效u tomcat体系的再说明 图:如何配置默认主机:在tomcat/conf/server.xml 文件<Engine name="Catalina" defaultHost="主机名">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函数,该函数就会去销毁serlvet5. 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) 通过继承 HttpServletu 实现servlet接口的方式需求如下: 请使用实现 接口的方式,来开发一个Servlet ,要求该Servlet 可以显示Hello,world,同时显示当前时间.步骤1. 在webapps下建立一个web应用 hspWeb12. 在hspWeb1 下建立 WEB-INF->web.xml web.xml可以从 ROOT/WEB-INF/web.xml拷贝 3. 在WEB-INF 下建立 classes 目录(我们的Servlet 就要在该目录开发.),建立 lib文件夹4. 开发MyServlet.javapackage com.hsp;import javax.servlet.*;import javax.servlet.http.*; 为了能将servlet-api.jar包引入,需要配置环境变量变量值; E:tomcatapache-tomcat-6.0.20libservlet-api.jar 记得带上文件名import java.io.*;class MyFirstServlet implements Servlet/该函数用于初始化servlet,就是把该servlet装载到内存中/该函数只会被调用一次public void init(ServletConfig config) throws ServletException/得到ServletConfig对象public ServletConfig getServletConfig()return null;/该函数是服务函数,我们的业务逻辑代码就是写在这里/该函数每次都会被调用public void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOException/该函数时得到servlet配置信息public java.lang.String getServletInfo()return null;/销毁该servlet,从内存中清除,该函数被调用一次public void destroy()5. 根据Servlet规范,我们还需要部署Servlet<?xml version="1.0" encoding="ISO-8859-1"?><!- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http:/www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.-><web-app xmlns=" xmlns:xsi="http:/www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" version="2.5"><!-根据serlvet规范,需要将Servlet部署到web.xml文件,该部署配置可以从examples下拷贝-> <servlet><!-servlet-name 给该Servlet取名, 该名字可以自己定义:默认就使用该Servlet的名字-> <servlet-name>MyFirstServlet</servlet-name> <!-servlet-class要指明该Servlet 放在哪个包下 的,形式是 包/包/./类-> <servlet-class>com.hsp.MyFirstServlet</servlet-class> 注意:后面不要带.java </servlet><!-Servlet的映射-> <servlet-mapping><!-这个Servlet-name要和上面的servlet-name名字一样-> <servlet-name>MyFirstServlet</servlet-name><!-url-pattern 这里就是将来访问该Servlet的资源名部分-> <url-pattern>/ABC</url-pattern> </servlet-mapping></web-app>服务器调用流程:http:/localhost:8088/ABC->->->->6. 在浏览器中测试在浏览器中输入http:/localhost:8088/hspweb1/ABC7. 分析一下自己写可能出现的错误(1) <servlet-name>MyFirstServlet</servlet-name> 名字不一样 (启动tomcat错误)(2) <servlet-class>com.hsp.MyFirstServlet</servlet-class> 写成 MyFirstServlet.java,会报告500(3) 资源名自己写错http:/localhost:8088/hspweb1/错误的资源url-pattern404 错误补充: 如果使用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 GenericServletpublic void service(ServletRequest req, ServletResponse res) throws ServletException, java.io.IOExceptionres.getWriter().println("hello,world,i am geneirc servlet");将该Servlet部署到web.xml文件中:<!-根据serlvet规范,需要将Servlet部署到web.xml文件,该部署配置可以从examples下拷贝-> <servlet><!-servlet-name 给该Servlet取名, 该名字可以自己定义:默认就使用该Servlet的名字-> <servlet-name>MyGenericServlet</servlet-name> <!-servlet-class要指明该Servlet 放在哪个包下 的,形式是 包/包/./类-> <servlet-class>com.hsp.MyGenericServlet</servlet-class> </servlet><!-Servlet的映射-> <servlet-mapping><!-这个Servlet-name要和上面的servlet-name名字一样-> <servlet-name>MyGenericServlet</servlet-name><!-url-pattern 这里就是将来访问该Servlet的资源名部分,默认命名规范:就是该Servlet的名字-> <url-pattern>/MyGenericServlet</url-pattern></servlet-mapping>u 使用继承 HttpServlet 的方法来开发Serlvet(1) 在软件公司 90%都是通过该方法开发.(2) 举例说明; 还是显示 hello,world 当前日期代码:package com.hsp;import javax.servlet.*;import javax.servlet.http.*;import java.io.*;public class MyHttpServlet extends HttpServlet/在HttpServlet 中,设计者对post 提交和 get提交分别处理/回忆 <form action="提交给?" method="post|get"/>,默认是getprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOExceptionresp.getWriter().println("i am httpServet doGet()");protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException resp.getWriter().println("i am httpServet doPost() post name="+req.getParameter("username");还有一个login.html<html><body><form action="/hspWeb1/MyHttpServlet" method="post">u:<input type="text" name="username"/><input type="submit" value="login"/></body></html>u 小结 get 提交 和 post的提交的区别 从安全看 get<post 因为get 会把提交的信息显示到地址栏 从提交内容看 get<post get 一般不要大于2k, post理论上无限制,但是在实际 开发中,建议不要大于64k 从速度看 get>post Get可以保留uri中的参数,利于收藏u 使用ide来开发servlet使用ide (eclipsejava se+myeclipse插件 可以支持jsp/servlet/struts/hibernate/spring.)开发servlet需求:使用 ide 开发一个servlet ,该servlet 显示 hello,world, 和当前日期u 开发步骤:(1) 建立web工程(2) 在Src 目录下创建了一个包 com.hsp.servlet(3) 开发一个ServletMySerlvet 的代码:public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException response.setContentType("text/html");PrintWriter out = response.getWriter();out.println("hello "+new java.util.Date().toString() );public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException this.doGet(request, response);(4) 配置tomcat点击add 选择要发布到那个服务器即可:(5) 启动tomcat1. 使用我们的老方法2. 从eclipse 启动 tomcat(6) 在使用eclipse 开发servlet 可能会出现一个很麻烦事情,版本不一致错误.java.lang.UnsupportedClassVersionError: Bad version number in .class file (unable to load class com.hsp.servlet.MyServlet1)原因是因为 tomcat 使用jdk 和 servlet 使用的 jdk不一样,解决方法就是统一即可.请大家使用eclipse 并配置继承 HttpServlet 开发一个servlet, 显示hello, 和当前日期.u Servlet的细节问题 一个已经注册的Servlet可以被多次映射即: <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <!- servlet的注册名 -> <servlet-name>MyServlet1</servlet-name> <!- servlet类的全路径(包名+类名) -> <servlet-class>com.hsp.servlet.MyServlet1</servlet-class> </servlet><!- 对一个已经注册的servlet的映射 -> <servlet-mapping> <!- servelt的注册名 -> <servlet-name>MyServlet1</servlet-name> <!- servlet的访问路径 -> <url-pattern>/MyServlet1</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>MyServlet1</servlet-name> <url-pattern>/hsp</url-pattern> </servlet-mapping> 当映射一个servlet时候,可以多层 比如 <url-pattern>/servlet/index.html</url-pattern> ok从这里还可以看出,后缀名是 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 中的 <load-on-startup> 配置需求: 当我们的网站启动的时候,可能会要求初始化一些数据,(比如创建临时表), 在比如:我们的网站有一些要求定时完成的任务 定时写日志,定时备份数据. 定时发送邮件.解决方法: 可以通过 <load-on-startup> 配合 线程知识搞定.先说明<load-on-startup>: 通过配置<load-on-startup> 我们可以指定某个Servlet 自动创建.我们来模拟一个定时发送电子邮件的功能:实现思路:sendEmailTableidcontent sendtime1“hello”2011-11-11 20:112“hello2”2012-11-11 10:00看看如何线程去完成任务:这里的代码请参考项目:SendMailThread.javapackage com.hsp.model;public class SendEmailThread extends ThreadOverridepublic void run() int i=0;try while(true)/每休眠一分钟,就去扫表sendmail, 看看那份信件应当被发出Thread.sleep(10*1000);System.out.println("发出 第"+(+i)+"邮件");/javamail catch (Exception e) e.printStackTrace();/ TODO: handle exceptionMyInitServlet1.javapublic void init() throws ServletException / Put your code hereSystem.out.println("MyInitServlet1 的init被调用.");/完成一些初始化任务System.out.print