首页 > 代码库 > Servlet
Servlet
servlet 是运行在 Web 服务器中的小型 Java 程序(即:服务器端的小应用程序)。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
先写一个java 类,实现Servlet 接口
下面配置下web.xml
访问地址:
http://locahost:8080/day08_servlet/demo1
Servlet 的生命周期
、实例化-->初始化-->服务->销毁
出生:(实例化-->初始化)第一次访问Servlet就出生(默认情况下)
活着:(服务)应用活着,servlet就活着
死亡:(销毁)应用卸载了servlet就销毁。
init第一次访问的时候被调用,service 多次被调用
小知识:让servlet在服务器启动的时候就被调用
servlet 创建的三种方式
1.
实现javax.servlet.Servlet接口(参见:编写一个servlet程序:)
2.
继承javax.servet.GenericServlet类(适配器模式)
例子:
public class ServletDemo2 extends GenericServlet{
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("servletDemo2");
}
}
3.
继承javax.servlet.http.HttpServlet类(模板方法设计模式)开发中常用的方式
public class ServletDemo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("************ServletDemo4************");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
它们之间的关系:
Servlet --> GenericServlet --> HttpServlet (继承HttpServlet)
Servlet的线程安全
单实例:每次访问多线程
解决线程安全问题的最佳办法,不要写全局变量,而写局部变量。
当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。
这样做的好处是:如果将数据库信息、编码方式等配置信息放在web.xml中,如果以后数据库的用户名、密码改变了,则直接很方便地修改web.xml就行了,避免了直接修改源代码的麻烦。
主要方法:
- String getServletName() -- 获取当前Servlet在web.xml中配置的名字
- String getInitParameter(String name) -- 获取当前Servlet指定名称的初始化参数的值
- Enumeration getInitParameterNames() -- 获取当前Servlet所有初始化参数的名字组成的枚举
- ServletContext getServletContext() -- 获取代表当前web应用的ServletContext对象
在Web.xml中配置信息
<servlet>
<servlet-name>ServletConfigDemo1</servlet-name>
<servlet-class>com.itcast.servletConfig.ServletConfigDemo1</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</servlet>
有三种方式获取:
第一
private ServletConfig config;
public void init(ServletConfig config) throws ServletException {
this.config = config;
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String encoding = config.getInitParameter("encoding");//获得配置文件中的信息的
System.out.println(encoding);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
第二种方式
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String encoding = this.getServletConfig().getInitParameter("encoding");
System.out.println(encoding);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
第三种方式
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String encoding = super.getInitParameter("encoding");
System.out.println(encoding);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
二、ServletContext:代表当前web应用(非常重要)
WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。
由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。
ServletContext的应用:
1.做为域对象可以在整个web应用范围内共享数据。
这里涉及到一些概念:
- 域对象:在一个可以被看见的范围内共享数据用到对象
- 作用范围:整个web应用范围内共享数据
- 生命周期:当服务器启动web应用加载后创建出ServletContext对象后,域产生。当web应用被移除出容器或服务器关闭,随着web应用的销毁域销毁。
常用方法:
void setAttribute(String name,object value);//向ServletContext对象的map中添加数据
Object getAttribute(String name);//从ServletContext对象的map中取数据
void rmoveAttribute(String name);//根据name去移除数
举例: servletDemo1
public class ServletDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//通过调用GenericServlet的getServletContext方法得到ServletContext对象
ServletContext application = this.getServletContext();
//向ServletContext添加一个键值对
application.setAttribute("name", "tom");
System.out.println(application.getClass().getName());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
ServletDemo2
public class ServletDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String name = (String) this.getServletContext().getAttribute("name");
if(name==null){
System.out.println("你不能直接访问这个类");
}
System.out.println(name);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
我们在ServletDemo1中给Context加一个参数name,然后就能在ServletDemo2中得到这个参数了
代码部分:
<!-- 配置当前应用的全局信息 -->
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String encoding = this.getServletContext().getInitParameter("encoding");
System.out.println(encoding);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
获取多个配置
<!-- 配置当前应用的全局信息 -->
<context-param>
<param-name>username</param-name>
<param-value>lily</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123</param-value>
public class ServletDemo7 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext s = this.getServletContext();
Enumeration e = s.getInitParameterNames();
while (e.hasMoreElements()) {
String name = (String) e.nextElement();
String value = http://www.mamicode.com/s.getInitParameter(name);
System.out.println(name + " " + value);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
结果:
username lily
password 123
获取资源路径:
创建配置文件a.properties 中key=abc
String getRealPath(String path);//根据资源名称得到资源的绝对路径.
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
test1();
}
private void test1() throws IOException, FileNotFoundException {
String path = this.getServletContext().getRealPath("a.properties");//参数一定要以/开头
//创建一个Properties
Properties pro = new Properties();
pro.load(new FileInputStream(path));
System.out.println(pro.getProperty("key"));
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
结果为:abc
三、实现Servlet的转发
这里涉及到一些概念要区分:
- 请求重定向:302+Location(两次请求两次响应)
- 请求转发:服务器内不进行资源流转 (一次请求一次响应,来实现资源流转)
注:上方括号中的内容是二者的区别。打个比方,假如你找我借钱,如果是请求重定向的话,那你再去找别人借;如果是请求转发的话,那我去找别人借,然后再借给你。
例子;ServletDemo5 请求转发
public class ServletDemo5 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("我要办事");
System.out.println("你的事我办不了,我可以帮你找人办");
ServletContext application = this.getServletContext();
RequestDispatcher rd = application.getRequestDispatcher("/servlet/demo6");
rd.forward(request, response);
System.out.println("事办完了");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
ServletDemo6接收
public class ServletDemo6 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("这个事我能办!。。。。");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
Servlet