Servlet是一个程序,它运行在服务器端,接收和处理用户请求,并做出响应
需要直接或间接的实现Servlet接口(需要继承HttpServlet类)
需要重写doGet()/doPost()方法
需要在web.xml配置文件中配置Servlet的url映射
public class Actionclass extends HttpServlet{
//构造方法
public Actionclass(){
super();
}
//初始化方法
public void init() throws ServletException{
System.out.println("初始化时,init()方法被调用");
}
//doGet()方法
public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IoException{
System.out.println("处理请求时,doGet()方法被调用");
}
//doPost()方法
public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IoException{
System.out.println("处理请求时,doPost()方法被调用");
}
//用于释放资源
public void destroy(){
super.destroy();
System.out.println("释放系统资源时,destroy()方法被调用");
}
}
Servlet生命周期:
|-----生命周期
Servlet的生命周期是通过Servlet接口中的 init(),service()和destroy()方法来表示的。即Servlet从创建到销毁的过程,包括如何加载和实例化,处理请求以及如何被销毁。
|------加载和实例化
Servlet不能独立运行,它必须被部署到Servlet容器中,由容器实例化和调用Servlet的方法,Servlet容器在Servlet的生命周期内管理Servlet。当Servlet容器启动或者当客户端发送一个请求时,Servlet容器内会查找内存中是否存在该Servlet的实例,如果不存在,就创建一个Servlet实例。如果存在该Servlet的实例,就直接从内存中取出该实例响应请求。
|-----初始化
在Servlet容器完成Servlet实例化后,Servlet容器将调用Servlet的init()方法进行初始化,初始化的目的是让Servlet对象在处理客户端请求前完成一些准备或资源预加载工作,如设置数据库连接参数,建立JDBC连接,或者是建立对其他资源的引用。(对于每一个Servlet实例,init()方法只被调用一次)
|-----服务
Servlet被初始化后,就处于能响应请求的就绪状态。当Servlet容器接收客户请求时,调用Servlet的service()方法处理客户请求时,HttpServlet的service()方法会根据GET或POST请求转调doGet()或doPost()方法。Servlet实例通过ServletRequest对象获得客户端的请求,通过调用ServletResponse对象的方法设置响应信息。
|-----销毁
Servlet的实例是由Servlet容器创建的,所以实例的销毁也是由容器来完成的。Servlet容器判断一个Servlet是否应当被释放时(容器关闭或需要回收资源),容器就会调用Servlet的destroy()方法,该方法指明哪些资源可以被系统回收,而不是由destroy()方法直接回收Servlet实例。
Servlet生命周期 | 执行方法 | 执行次数 |
新建(创建) | 构造方法 | 1 |
初始化 | init() | 1 |
服务阶段 | service() | 多次 |
销毁 | destory | 1 |
运行原理对比:
jsp:
1.编写源代码
2.翻译 xxx.jsp ---> xxx_jsp.java
3.编译 xxx.java ---> xxx.class
4.运行 xxx.class
java:
1.编写源代码
2.编译 xxx.java ---> xxx.class
3.运行 xxx.class
配置Servlet
配置Servlet时,可以对Servlet设置初始化参数,通过初始化参数可以更灵活的控制Servlet的运行时行为。设置初始化参数需要修改web.xml文件,在<servlet>元素中增加<init-param>元素
<web-app>
<servlet>
<servlet-name>servlet名字,唯一</servlet-name>
<servlet-class>servlet的url路径</servlet-class>
<init-param>
<param-name>定义初始化参数的名字</param-name>
<param-value>指定初始化参数的值</param-value>
</init-param>
<servlet-mapping>
<servlet-name>对应servlet名字</servlet-name>
<url-pattern>外界访问的url,前一定要加一个'/'</url-pattern>
</servlet-mapping>
</servlet>
</web-app>
初始化参数在Servlet的初始化环节被加载,并可以通过ServletConfig实例的getInitParameter(String name)方法进行访问。
String initparam = getInitParameter("定义初始化参数的名字");
为某个Servlet定义的初始化参数只能被该Servlet访问,如果该参数需要被更多的web组件访问,可以使用上下文参数定义。要定义上下文参数同样需要对web.xml文件进行修改
<web-app>
<context-param>
<param-name>指定参数的名字</param-name>
<param-value>指定参数的值</param-value>
</context-param>
<!-- 省略其他配置 -->
</web-app>
那么在对应的服务中,在一个方法中编写聂荣,另一个方法调用即可,不需要重复编写
//doGet()方法 public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IoException{ System.out.print("处理请求时,doGet()方法被调用"); String initparam = getInitParameter("定义初始化参数的名字"); String contextparam = this.getServletContext().getInitParameter("指定参数的名字"); System.out.print("Servlet初始化参数"+initparam); System.out.print("上下文参数"+contextparam); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //调用doGet doGet(request,response); System.out.println("处理请求时,doPost()方法被调用"); }
一个servlet只能处理一个请求,而在实际业务中,我们希望在一个servlet中可以有多个请求处理方法。客户端发出请求时,必须给出一个参数,老说明要调用哪个方法。
这时我们定义一个BaseServlet,来处理多个请求
原理: 获取用户发出请求的url,通过“/”截取url最后的方法名,可以使用反射来完成
package BaeseServlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BaseServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) {
//获取用户发出请求的url
String url = request.getRequestURI();
//获取url / 最后的indx
int indx = url.lastIndexOf("/");
//通过‘/’截取url最后的【方法名】
String method = url.substring(indx+1);
//获取类的描述符
Class cls = this.getClass();
try {
//获取对应用户的方法
Method mtd = cls.getDeclaredMethod(method,HttpServletRequest.class,HttpServletResponse.class);
try {
//反射
mtd.invoke(this,request,response);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
在创建servlet时继承BaseServlet而不是HttpServlet,并可以在其中定义对应表中各个方法
package com.d.servlet;
import BaeseServlet.BaseServlet;
public class MyServlet extends BaseServlet{
public void method1(){
}
public void method2(){
}
}