一、servlet简介
servlet是一种动态web资资源开发技术,用于开发动态web页面;
二、servlet的运行过程
servlet程序是由web服务器调用,web服务器收到客户端的servlet访问请求后;
1、web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第4步,否则执行第2步,
2、装载并创建一个Servlet的一个实例对象。
3、调用servlet实例对象的init()方法。
4、创建一个用于封装http请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet对象service方法并将请求和响应作为参数传递进去。
5、web应用程序被停止或启动之前,servlet引擎将卸载servlet,并在卸载之前调用servlet的destroy()方法。
三、一个完整的servlet组成部分
1、首先我们会定义一个Java类,重写doGet(),doPost()方法;
2、在web.xml文件下配置servlet;
3、一个servlet的组成分为servlet-name和servlet-class都是成对的标签,servlet-name表示servlet的注册码,servlet-class
表示servlet的完整类名(全包名)
4、还需要配置一个servlet-mapping 一个servlet-mapping 包括 servlet-name和url-pattern两对标签,servlet-name表示servlet的注册名,url-pattern表示对外的绝对访问路径。
需要注意的是一个servlet可以对应多个servlet-mapping
<servlet>
<servlet-name>ServletDemo1</servlet-name>
<servlet-class>gacl.servlet.study.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/servlet/ServletDemo1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/1.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/2.jsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/3.php</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/4.ASPX</url-pattern>
</servlet-mapping>
四、Servlet访问通配符的一些匹配规则
在Servlet映射到的URL中也可以使用通配符,但是只能有两种固定的格式:一种格式是”.扩展名”,另一种格式是以正斜杠(/)开头并以”/*”结尾。例如:
五、servlet的启动装载
创建一个servlet,使得它只有当web服务器关闭时才销毁。
<servlet>
<servlet-name>invoker</servlet-name>
<servlet-class>
org.apache.catalina.servlets.InvokerServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。
六、servlet线程安全问题
当多个客户端并发访问同一个servlet时,web服务器会为每一个客户端的访问创建一个线程,并在这个线程上调用service方法,因此导致了一些线程安全问题。
不存在线程安全问题的(将i作为成员变量)
package gacl.servlet.study;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 当多线程并发访问这个方法里面的代码时,会存在线程安全问题吗
* i变量被多个线程并发访问,但是没有线程安全问题,因为i是doGet方法里面的局部变量,
* 当有多个线程并发访问doGet方法时,每一个线程里面都有自己的i变量,
* 各个线程操作的都是自己的i变量,所以不存在线程安全问题
* 多线程并发访问某一个方法的时候,如果在方法内部定义了一些资源(变量,集合等)
* 那么每一个线程都有这些东西,所以就不存在线程安全问题了
*/
int i=1;
i++;
response.getWriter().write(i);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
存在线程安全问题的(将i作为成员变量便会存在线程安全问题)
package servlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 测试线程安全问题
*/
public class ServletThredDemo1 extends HttpServlet {
public int i;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
//将i定义为成员变量 将不存在线程安全问题
i++;
try {
Thread.sleep(1000*4);
} catch (InterruptedException e) {
e.printStackTrace();
}
response.getWriter().write(i+"");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException{
doGet(request,response);
}
}
七、ServketCnfig讲解
7.1配置servlet初始化参数
在servlet的配置文件web.xml中,可以使用一个或多个
当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,我们通过ServletConfig对象就可以得到当前servlet的初始化参数信息。
<servlet>
<servlet-name>ServletConfigDemo1</servlet-name>
<servlet-class>gacl.servlet.study.ServletConfigDemo1</servlet-class>
<!--配置ServletConfigDemo1的初始化参数 -->
<init-param>
<param-name>name</param-name>
<param-value>gacl</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123</param-value>
</init-param>
<init-param>
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
7.2获取初始化参数
package servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/**
*通过ServletConfig 配置一些默认参数
*/
public class ServletConfigDemo1 extends HttpServlet {
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
this.config=config;
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
//必须设置响应头 不然会将html 解析为字符串
response.setContentType("text/html;charset=utf-8");
//通过config对象获取初始化servlet初始化参数
String name = config.getInitParameter("name");
response.getWriter().print(name);
response.getWriter().print("<hr/>");
//获取全部的初始化参数
Enumeration<String> e = config.getInitParameterNames();
while (e.hasMoreElements()){
String key = e.nextElement();
String value = config.getInitParameter(key);
response.getWriter().write(key+":"+value+"<br/>");
}
}
public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException{
doGet(request,response);
}
}
八、servletContext对象
8.1ServletContext对象简介
WEB容器在启动时,它会为每个web应用程序都创建一个对应的serlvetContext对象,它代表当前的web应用。
ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过servletConfig.getServletContext方法获得ServletContext对象。
由于一个web应用中的所有Serlvet共享一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。SerlvetContext对象也被称之为域对象。
8.2多个Servlet通过ServletContext对象实现数据共享
通过servletConfig对象获取servletContext对象设置值
package servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* ServletContext域对象实现共享
*/
public class ServletContextDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response){
ServletContext servletContext = getServletConfig().getServletContext();
servletContext.setAttribute("name","lisi");
}
public void doPost(HttpServletRequest request, HttpServletResponse response){
doGet(request,response);
}
}
通过servletContext对象获取值
package servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* ServletContext域对象实现共享
*/
public class ServletContextDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
ServletContext servletContext =getServletContext();
String name = servletContext.getAttribute("name").toString();
response.getWriter().write(name);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException{
doGet(request,response);
}
}
注意:需要配置两个servlet,先设置值,再获取值
8.3用servletContext实现转发
访问的是ServletContextDemo3,浏览器显示的却是ServletContextDemo4的内容,这就是使用ServletContext实现了请求转发
package servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 通过ServletContext对象实现转发
*/
public class ServletContextDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String data = "<h1><font color='red'>abcdefghjkl</font></h1>";
response.getOutputStream().write(data.getBytes());
//获取Context对象
ServletContext servletContext = getServletContext();
//获取转发的对象 RequestDispatcher
RequestDispatcher rd = servletContext.getRequestDispatcher("/servlet/ServletContext4");
//实现转发
rd.forward(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
doGet(request,response);
}
}
package servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 通过ServletContext对象实现转发
*/
public class ServletContextDemo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.getOutputStream().write("ServletContext4".getBytes());
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
doGet(request,response);
}
}