文档版本 | 开发工具 | 测试平台 | 工程名字 | 日期 | 作者 | 备注 |
---|---|---|---|---|---|---|
V1.0 | 2016.04.21 | lutianfei | none |
Servlet开发
Servlet简介
- Servlet是sun公司提供的一门用于开发动态web资源的技术。
- Sun公司在其API中提供了一个servlet接口,用户若想要开发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:
- 编写一个Java类,实现servlet接口。
- 把开发好的Java类部署到web服务器中。
Servlet快速入门
用servlet向浏览器输出“hello servlet”。
- 步骤如下:
- 编写一个类,实现Servlet接口,重写5个方法。
- 编写一个类HelloServlet,继承GenericServlet类,重写一个方法。
- 编写一个类,实现Servlet接口,重写5个方法。
public class TestDemo1 implements Servlet {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
res.getWriter().write("hello Miaolu ...");
}
}
- 配置文件,配置Servlet信息。
<!-- 先配置Servlet信息 -->
<servlet>
<!-- 配置Servlet名称,名称必须唯一 -->
<servlet-name>ServletDemo1</servlet-name>
<!-- 配置Servlet的完全路径(包名+类名) -->
<servlet-class>cn.itcast.servlet.ServletDemo1</servlet-class>
</servlet>
<!-- 配置Servlet映射(访问路径) -->
<servlet-mapping>
<!-- 配置Servlet名称,和上面的名称必须相同 -->
<servlet-name>ServletDemo1</servlet-name>
<!-- 配置虚拟路径(访问路径) -->
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
* 编译(一般用不到)
* `javac -d . HelloServlet.java`
* 问题:`HelloServlet.java: 4 : 软件包 javax.servlet 不存在`
* 解决:`set classpath=%classpath%;servlet-api.jar `设置临时的环境变量,只对当前的窗口有效。
- servlet 执行过程
Servlet的生命周期
生命周期
:实例被创建
,对外提供服务
,销毁
。Servlet
是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。- Servlet实例被创建后,调用
init
方法进行初始化 - Servlet默认情况下什么时候被创建呢?
- 第一次访问的时候,实例才被创建。
- init方法调用几次呢?
- 只被调用一次。
- 注意事项:
- 如果想重写init方法,重写无参数的init方法。
- 对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的
service方法
。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest
请求对象和一个新的HttpServletResponse
响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX
方法。 - 从服务器中移除服务,调用destroy方法。
- Servlet实例什么时候被销毁呢?
- 服务器关闭,手动移除。
- destroy仅调用一次。
- 针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
Servlet的关系
- Servlet接口
- GenericServlet(重写5个方法)
- HttpServlet(继承GenericServlet实现了Servlet接口)
- MyServlet
- HttpServlet(继承GenericServlet实现了Servlet接口)
- GenericServlet(重写5个方法)
* 新建servlet模板工程*
- 新建文件时,选择Servlet
- 将红框中的勾去掉
- 将红框中的名字简化成类名
- 开发步骤(最终)
- 编写一个类,继承HttpServlet
- 重写doGet和doPost方法
- 在doPost方法中调用doGet方法。
- 表单是get方式,调用doGet
- 表单是post方法,调用doPost方法
- doGet和doPost互相调用。代码复用。
- 修改Servlet模板
- 先找到MyEclipse的安装路径。
\myeclipse10.7\Common\plugins\com.genuitec.eclipse.wizards.xxxx.jar
- 找到jar包:
com.genuitec.eclipse.wizards_9.0.0.me201211011550.jar
- 千万别解压,右键–选择压缩工具打开
- 将templates–Servlet.java文件拖到桌面
- 将Servlet.java文件做如下修改后再拖回压缩包。
- 拖回去之前,先把MyEclipse关闭。
- 注:将注释及多余代码全部删掉,并在doPost方法中加入如下doGet方法调用。
- 先找到MyEclipse的安装路径。
Servlet自动加载
- Servlet默认是第一次访问时候创建实例。通过配置,服务器启动,创建实例。
- init做初始化的操作,非常消耗时间的。
- 在
<servlet>
标签下:要放在servlet
标签内的最后位置。<load-on-startup>3</load-on-startup>
- 值是正整数
- 如果值越小,优先级越高。
WEB开发中路径的问题
配置虚拟路径(访问路径)
- 由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个
URL地址
上,这个工作在web.xml
文件中使用<servlet>
元素和<servlet-mapping>
元素完成。 <servlet>
元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name>
和<servlet-class>
,分别用于设置Servlet的注册名称和Servlet的完整类名。- 一个
<servlet-mapping>
元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name>
和<url-pattern>
,分别用于指定Servlet的注册名称和Servlet的对外访问路径。
路径匹配问题
完全路径匹配
- 以
/
开头的。eg:/demo5
- 访问:
http://localhost/day09/demo5
- 以
目录匹配
- 以
/
开头的:/*
,任意后缀都可以访问。 - 访问:
http://localhost/day09/demo5
可以访问
- 以
扩展名匹配
- 不能以
/
开头的, eg:*.do
*.action
- 访问:
http://localhost/day09/demo5.do
- 不能以
- 优先级:
完全路径匹配
>目录匹配
>扩展名匹配
(重点) - 练习题:
相对路径
- 一个文件相对于另一个文件的位置的关系。
- 不能以
/
开头 写法:./demo
当前目录==demo
;../demo
:表示上级目录。 - 访问1.html:
http://localhost/day09/1.html
- 访问demo5:
http://localhost/day09/demo5
- 从1.html中去访问demo5:
./demo5
demo5
- 访问2.html:
http://localhost/day09/html/2.html
- 访问demo5:
http://localhost/day09/demo5
- 从2.html访问demo5:
../demo5
绝对路径(推荐使用)
- 以
/
开头的 - 访问demo5:
http://localhost/day09/demo5
- 从1.html使用绝对路径访问demo5:
http://localhost/day09/demo5
- 简写方式:
/day09/demo5
- 客户端绝对路径
/day09/demo5
需要写项目名
- 服务器绝对路径
/demo5
不能写项目名
- 客户端关于路径问题的编程结论
*.html
*.jsp
: 内都使用绝对路径*.css
:内部使用相对路径—- 背景图片*.js
:中使用绝对路径
ServletConfig对象和配置文件相关
- 当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到
ServletConfig
对象中,并在调用servlet的init
方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。 - 配置初始化参数
- 需要在
<servlet> </servlet>
标签下配置。 - 如果要是配置在某个servlet的标签下,那么只能在该servlet中获取初始化参数。
- 需要在
- 在Servlet的配置文件中,可以使用一个或多个
<init-param>
标签为servlet配置一些初始化参数
。 - String
getServletName
() 获取配置文件中servlet的名称 - String
getInitParameter
(String name) 获取初始化参数 - Enumeration
getInitParameterNames
() 获取初始化参数的所有名称
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
public class ServletDemo6 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 测试ServletConfig对象的api
// 先获取ServletConfig对象
ServletConfig config = getServletConfig();
// 获取配置文件中serlvet的名称
System.out.println("servlet的名称:"+config.getServletName());
// 获取初始化的参数
String username = config.getInitParameter("username");
String password = config.getInitParameter("password");
System.out.println(username+" : "+password);
Enumeration<String> e = config.getInitParameterNames();
while(e.hasMoreElements()){
String name = e.nextElement();
String value = config.getInitParameter(name);
System.out.println(name+" : "+value);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
ServletContext对象(域对象) (重要)
- WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的
ServletContext
对象,它代表当前web应用。- 一个WEB应用对应一个
ServletContext
对象 - 一个WEB应用下有多个
Servlet
程序 - 所有的servlet程序都共享同一个ServletContext对象
- 一个WEB应用对应一个
ServletConfig
对象中维护了ServletContext
对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext
方法获得ServletContext
对象。- 由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为
context域对象
。 - 作用:
- 获取WEB应用全局初始化参数
- String
getInitParameter
(String name) getInitParameterNames
()- 在web.xml中配置全局初始化参数
- String
- 获取WEB应用全局初始化参数
<context-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</context-param>
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 先获取ServletContext对象
ServletContext context = getServletContext();
// 获取初始化参数
String encoding = context.getInitParameter("encoding");
System.out.println("编码:"+encoding);
Enumeration<String> e = context.getInitParameterNames();
while(e.hasMoreElements()){
String name = e.nextElement();
// 通过name获取值
String value = context.getInitParameter(name);
System.out.println(name+" : "+value);
}
}
- 实现数据的共享(重要)
- void
setAttribute
(String name, Object object) : 存入数据 - void
removeAttribute
(String name) : 删除数据 - Object
getAttribute
(String name) : 获取数据
- void
- 读取资源文件(重要)
- InputStream
getResourceAsStream
(String path) 通过文件的地址获取输入流 - String
getRealPath
(String path) 通过文件的地址获取文件的绝对磁盘路径
- InputStream
public class ReadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
read5();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
/**
* 通过ServletContext对象获取文件的绝对磁盘路径
* 获取src目录下文件
* @throws IOException
*/
public void read5() throws IOException{
// 获取对象
String path = getServletContext().getRealPath("/WEB-INF/classes/db.properties");
// System.out.println(path);
// C:\apache-tomcat-6.0.14\webapps\day09\WEB-INF\classes\db.properties
// 获取输入流
InputStream in = new FileInputStream(path);
print(in);
}
/**
* 获取WebRoot目录目录下db.properties文件
* @throws IOException
*/
public void read4() throws IOException{
// ServletContext读取文件
InputStream in = getServletContext().getResourceAsStream("/db.properties");
// 打印方式
print(in);
}
/**
* 获取包目录下db.properties文件
* @throws IOException
*/
public void read3() throws IOException{
// ServletContext读取文件
InputStream in = getServletContext().getResourceAsStream("/WEB-INF/classes/cn/itcast/context/db.properties");
// 打印方式
print(in);
}
/**
* 获取src目录下db.properties文件
* @throws IOException
*/
public void read2() throws IOException{
// ServletContext读取文件
InputStream in = getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
// 打印方式
print(in);
}
/**
* 传统方式读取资源文件
* 交给服务器处理,相对的位置tomcat/bin
* @throws IOException
*/
public void read1() throws IOException{
// 获取输入流
InputStream in = new FileInputStream("src/db.properties");
print(in);
}
/**
* 在控制台打印内容
* @param in
* @throws IOException
*/
public void print(InputStream in) throws IOException{
Properties pro = new Properties();
// 加载
pro.load(in);
// 获取文件中的内容
String username = pro.getProperty("username");
String password = pro.getProperty("password");
String desc = pro.getProperty("desc");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
System.out.println("描述:"+desc);
}
}
//db.properities
username=root33
password=12333
desc=haha33
- 案例:统计显示网站访问次数
- CountServlet.java
public class CountServlet extends HttpServlet {
/**
* 实例被创建,调用init方法进行初始化
* 在域对象存入一个变量,赋值为0
*/
public void init() throws ServletException {
// 获取ServletContext对象
getServletContext().setAttribute("count", 0);
}
/**
* 每一次访问,都会执行该方法。
* 拿出count的变量,值自增,存入到域对象中
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 先获取ServletContext对象
ServletContext context = getServletContext();
// 获取count的值,自增
Integer count = (Integer) context.getAttribute("count");
// 存入到域对象中
context.setAttribute("count", ++count);
// 向页面输出内容
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("<h3>大爷,欢迎再来哦!!</h3>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
- ShowServlet.java
/**
* 显示网站的访问次数
* @author Administrator
*
*/
public class ShowServlet extends HttpServlet {
/**
* 获取网站的访问次数,输出到客户端
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Integer count = (Integer) getServletContext().getAttribute("count");
// 向页面输出
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("<h3>该网站一共被访问了"+count+"次</h3>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
- HTTP的协议
- 响应报头:location 与302 重定向应用
package cn.itcast.http;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 和location和302一起完成重定向
* @author Administrator
*
*/
public class ServletDmo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 向页面输出内容
response.setContentType("text/html;charset=UTF-8");
// response.getWriter().write("向班长借钱...");
// 我没钱
response.setStatus(302);
// 告诉我富班长的地址
response.setHeader("location", "/day09/1.html");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
- 响应头: refresh 页面定时跳转
package cn.itcast.http;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 页面定时跳转
* @author Administrator
*
*/
public class RefreshServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("访问到了...");
// 页面5秒会跳转
response.setHeader("refresh", "5;url=/day09/1.html");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
- 响应报头last-modefied-since 和304状态码 :控制缓存
时间: 2024-10-10 07:12:05