第一章 Servlet
1.1. Servlet简介
Servlet是sun公司提供的一门用于开发动态web资源的技术。
Servlet是一个小的java程序,能接收和响应从客户端发送过来的请求,使用的是HTTP的协议。
Sun公司在其API中提供了一个servlet接口,用户若想要开发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:
编写一个Java类,实现servlet接口。
把开发好的Java类部署到web服务器中。
1.2. Servlet的开发步骤
编写普通的类,实现Servlet接口,重写5个方法。在WEB程序的web.xml文件进行配置
1 2 3 4 5 6 7 8
| <servlet> <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.servlet.ServletDemo1</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/demo1</url-pattern> </servlet-mapping>
|
1.3. 工程目录
1.4. 完成Servlet入门程序
访问流程:
1.5. Servlet生命周期(面试题)
init()方法:服务器调用该方法初始化Servlet
service()方法:初始化完毕,服务器调用该方法响应客户的请求
destroy()方法:服务器调用该方法消灭servlet对象
其中,init()方法只在Servlet第一次被请求加载的时候被调用一次,当有客户再请求Servlet服务时,Web服务器将启动一个新的线程,在该线程中,调用service方法响应客户的请求
总结:
Servlet实例被Tomcat服务器创建,第一次访问时创建(在内存中Servlet是一个单例模式,在开发中要注意,尽量不要定义成员属性),会立即调用init()方法创建,使用service方法对外提供服务,service方法只要有一次请求就会调用一次,当项目被移除,或者tomcat服务器关闭时,会调用destory方法销毁Servlet,destory()也是调用一次,(一般在释放资源是使用)
1.6. 关于Servlet生命周期
Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。
针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doGet或doPost方法。
1.7. Servlet的运行过程
Servlet程序是由WEB服务器调用,web服务器收到客户端的Servlet访问请求后:
1,.Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。
2.装载并创建该Servlet的一个实例对象。
3.调用Servlet实例对象的init()方法。
4创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
5.WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。
第二章 Servlet接口实现类
二.1. 两个实现类
Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet(抽象类)、HttpServlet(继承GenericServlet)。
HttpServlet指能够处理HTTP请求的servlet,它在原有Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。
HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。
2.2. 当继承了HttpServlet的注意事项
Servlet初始化时覆盖init() ,无需覆盖init(config)
根据Http请求的方式,覆盖相应的doGet或者doPost方法,无需覆盖Service方法
当doGet和doPost代码逻辑相同时,可以相互调用,简化编程
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| package cn.yueqian.service;
import java.io.IOException;
import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
public class Servlet2 extends HttpServlet {
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); String method = req.getMethod(); System.out.println(method + "请求:" + "账号是:" + username + "密码是:" + password); }
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp); } }
|
2.3. Web开发中的路径问题分析
Web系统中的相对路径和绝对路径
相对路径:hello ./hello ../myweb/hello
绝对路径:/hello /myweb/hello
服务器端和客户端对于/ 的区别l 客户端关于路径问题的编程结论:
*.html *.jsp 内都使用绝对路径
*.css 内部使用相对路径—- 背景图片
*.js中使用绝对路径
在开发中:前端美工人员用相对路径多我们用绝对路径比较多
2.4. init方法中的ServletConfig对象
在Servlet的配置文件中,可以使用一个或多个标签为servlet配置一些初始化参数。
当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。
阅读ServletConfig API,并举例说明该对象的作用:
获得配置文件,查看struts案例的web.xml文件l
案例:在web.xml文件中配置信息,并读取信息
步骤:
配置web.xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <servlet> <servlet-name>Servlet3222</servlet-name> <servlet-class>cn.yueqian.service.Servlet3</servlet-class> <init-param> <param-name>username</param-name> <param-value>zhangsan</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>aaaaa</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Servlet3222</servlet-name> <url-pattern>/Servlet3</url-pattern> </servlet-mapping>
|
Servlet代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package cn.yueqian.service;
import java.io.IOException; import java.util.Enumeration;
import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
public class Servlet3 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletConfig config = this.getServletConfig(); String servletName = config.getServletName(); System.out.println("servletName=="+servletName); String username = config.getInitParameter("username"); String password = config.getInitParameter("password"); System.out.println("username=="+username+",password=="+password); Enumeration<String> names = config.getInitParameterNames(); while(names.hasMoreElements()) { String name = names.nextElement(); String value = config.getInitParameter(name); System.out.println("name=="+name+",value=="+value); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
}
|
2.5. Web应用对象:ServletContext(重要)
二.6. 域对象的方法
所有域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储数据,下面是ServletContext对象用来操作数据的方法:
void setAttribute(String name, Object value):用来存储一个对象,也可以称之为存储一个域属性,例如:servletContext.setAttribute(“xxx”, “XXX”),在ServletContext中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同;
Object getAttribute(String name):用来获取ServletContext中的数据,当前在获取之前需要先去存储才行,例如:String value = (String)servletContext.getAttribute(“xxx”);,获取名为xxx的域属性;
void removeAttribute(String name):用来移除ServletContext中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做;
Enumeration getAttributeNames():获取所有域属性的名称;
二.7. ServletContext应用
获取WEB应用的全局初始化参数 读取:
通过ServletContext对象实现数据共享
案例— 统计站点访问次数l 代码:是用两个Servlet来模拟的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
public class Servlet5 extends HttpServlet{ @Override public void init() throws ServletException { ServletContext context = this.getServletContext(); context.setAttribute("count", 0); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); Integer count = (Integer)context.getAttribute("count"); count++; context.setAttribute("count", count); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
}
public class Servlet6 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext context = this.getServletContext(); Integer count = (Integer)context.getAttribute("count"); resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().append("<h1>访问量---->"+count+"</h1>");
} @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
}
|