一、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

  1. <servlet>
  2. <servlet-name>ServletDemo1</servlet-name>
  3. <servlet-class>gacl.servlet.study.ServletDemo1</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>ServletDemo1</servlet-name>
  7. <url-pattern>/servlet/ServletDemo1</url-pattern>
  8. </servlet-mapping>
  9. <servlet-mapping>
  10. <servlet-name>ServletDemo1</servlet-name>
  11. <url-pattern>/1.htm</url-pattern>
  12. </servlet-mapping>
  13. <servlet-mapping>
  14. <servlet-name>ServletDemo1</servlet-name>
  15. <url-pattern>/2.jsp</url-pattern>
  16. </servlet-mapping>
  17. <servlet-mapping>
  18. <servlet-name>ServletDemo1</servlet-name>
  19. <url-pattern>/3.php</url-pattern>
  20. </servlet-mapping>
  21. <servlet-mapping>
  22. <servlet-name>ServletDemo1</servlet-name>
  23. <url-pattern>/4.ASPX</url-pattern>
  24. </servlet-mapping>

四、Servlet访问通配符的一些匹配规则

在Servlet映射到的URL中也可以使用通配符,但是只能有两种固定的格式:一种格式是”.扩展名”,另一种格式是以正斜杠(/)开头并以”/*”结尾。例如:
image.png

五、servlet的启动装载

创建一个servlet,使得它只有当web服务器关闭时才销毁。

  1. <servlet>
  2. <servlet-name>invoker</servlet-name>
  3. <servlet-class>
  4. org.apache.catalina.servlets.InvokerServlet
  5. </servlet-class>
  6. <load-on-startup>1</load-on-startup>
  7. </servlet>

用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。

六、servlet线程安全问题

当多个客户端并发访问同一个servlet时,web服务器会为每一个客户端的访问创建一个线程,并在这个线程上调用service方法,因此导致了一些线程安全问题。

不存在线程安全问题的(将i作为成员变量)

  1. package gacl.servlet.study;
  2. import java.io.IOException;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. public class ServletDemo3 extends HttpServlet {
  8. public void doGet(HttpServletRequest request, HttpServletResponse response)
  9. throws ServletException, IOException {
  10. /**
  11. * 当多线程并发访问这个方法里面的代码时,会存在线程安全问题吗
  12. * i变量被多个线程并发访问,但是没有线程安全问题,因为i是doGet方法里面的局部变量,
  13. * 当有多个线程并发访问doGet方法时,每一个线程里面都有自己的i变量,
  14. * 各个线程操作的都是自己的i变量,所以不存在线程安全问题
  15. * 多线程并发访问某一个方法的时候,如果在方法内部定义了一些资源(变量,集合等)
  16. * 那么每一个线程都有这些东西,所以就不存在线程安全问题了
  17. */
  18. int i=1;
  19. i++;
  20. response.getWriter().write(i);
  21. }
  22. public void doPost(HttpServletRequest request, HttpServletResponse response)
  23. throws ServletException, IOException {
  24. doGet(request, response);
  25. }
  26. }

存在线程安全问题的(将i作为成员变量便会存在线程安全问题)

  1. package servlet;
  2. import javax.servlet.http.HttpServlet;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. import java.io.IOException;
  6. /**
  7. * 测试线程安全问题
  8. */
  9. public class ServletThredDemo1 extends HttpServlet {
  10. public int i;
  11. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
  12. //将i定义为成员变量 将不存在线程安全问题
  13. i++;
  14. try {
  15. Thread.sleep(1000*4);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. response.getWriter().write(i+"");
  20. }
  21. public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException{
  22. doGet(request,response);
  23. }
  24. }

七、ServketCnfig讲解

7.1配置servlet初始化参数

在servlet的配置文件web.xml中,可以使用一个或多个标签为servlet配置一些初始化参数.
当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,我们通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

  1. <servlet>
  2. <servlet-name>ServletConfigDemo1</servlet-name>
  3. <servlet-class>gacl.servlet.study.ServletConfigDemo1</servlet-class>
  4. <!--配置ServletConfigDemo1的初始化参数 -->
  5. <init-param>
  6. <param-name>name</param-name>
  7. <param-value>gacl</param-value>
  8. </init-param>
  9. <init-param>
  10. <param-name>password</param-name>
  11. <param-value>123</param-value>
  12. </init-param>
  13. <init-param>
  14. <param-name>charset</param-name>
  15. <param-value>UTF-8</param-value>
  16. </init-param>
  17. </servlet>

7.2获取初始化参数

  1. package servlet;
  2. import javax.servlet.ServletConfig;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.http.HttpServlet;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.util.Enumeration;
  9. /**
  10. *通过ServletConfig 配置一些默认参数
  11. */
  12. public class ServletConfigDemo1 extends HttpServlet {
  13. private ServletConfig config;
  14. @Override
  15. public void init(ServletConfig config) throws ServletException {
  16. this.config=config;
  17. }
  18. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
  19. //必须设置响应头 不然会将html 解析为字符串
  20. response.setContentType("text/html;charset=utf-8");
  21. //通过config对象获取初始化servlet初始化参数
  22. String name = config.getInitParameter("name");
  23. response.getWriter().print(name);
  24. response.getWriter().print("<hr/>");
  25. //获取全部的初始化参数
  26. Enumeration<String> e = config.getInitParameterNames();
  27. while (e.hasMoreElements()){
  28. String key = e.nextElement();
  29. String value = config.getInitParameter(key);
  30. response.getWriter().write(key+":"+value+"<br/>");
  31. }
  32. }
  33. public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException{
  34. doGet(request,response);
  35. }
  36. }

八、servletContext对象

8.1ServletContext对象简介

WEB容器在启动时,它会为每个web应用程序都创建一个对应的serlvetContext对象,它代表当前的web应用。
ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过servletConfig.getServletContext方法获得ServletContext对象。
由于一个web应用中的所有Serlvet共享一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。SerlvetContext对象也被称之为域对象。

8.2多个Servlet通过ServletContext对象实现数据共享

  1. 通过servletConfig对象获取servletContext对象设置值
  1. package servlet;
  2. import javax.servlet.ServletConfig;
  3. import javax.servlet.ServletContext;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. /**
  9. * ServletContext域对象实现共享
  10. */
  11. public class ServletContextDemo1 extends HttpServlet {
  12. public void doGet(HttpServletRequest request, HttpServletResponse response){
  13. ServletContext servletContext = getServletConfig().getServletContext();
  14. servletContext.setAttribute("name","lisi");
  15. }
  16. public void doPost(HttpServletRequest request, HttpServletResponse response){
  17. doGet(request,response);
  18. }
  19. }
  1. 通过servletContext对象获取值
  1. package servlet;
  2. import javax.servlet.ServletConfig;
  3. import javax.servlet.ServletContext;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. /**
  10. * ServletContext域对象实现共享
  11. */
  12. public class ServletContextDemo2 extends HttpServlet {
  13. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
  14. ServletContext servletContext =getServletContext();
  15. String name = servletContext.getAttribute("name").toString();
  16. response.getWriter().write(name);
  17. }
  18. public void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException{
  19. doGet(request,response);
  20. }
  21. }

注意:需要配置两个servlet,先设置值,再获取值

8.3用servletContext实现转发

访问的是ServletContextDemo3,浏览器显示的却是ServletContextDemo4的内容,这就是使用ServletContext实现了请求转发
image.png

  1. package servlet;
  2. import javax.servlet.RequestDispatcher;
  3. import javax.servlet.ServletContext;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. /**
  10. * 通过ServletContext对象实现转发
  11. */
  12. public class ServletContextDemo3 extends HttpServlet {
  13. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
  14. String data = "<h1><font color='red'>abcdefghjkl</font></h1>";
  15. response.getOutputStream().write(data.getBytes());
  16. //获取Context对象
  17. ServletContext servletContext = getServletContext();
  18. //获取转发的对象 RequestDispatcher
  19. RequestDispatcher rd = servletContext.getRequestDispatcher("/servlet/ServletContext4");
  20. //实现转发
  21. rd.forward(request,response);
  22. }
  23. public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
  24. doGet(request,response);
  25. }
  26. }
  1. package servlet;
  2. import javax.servlet.RequestDispatcher;
  3. import javax.servlet.ServletContext;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.IOException;
  9. /**
  10. * 通过ServletContext对象实现转发
  11. */
  12. public class ServletContextDemo4 extends HttpServlet {
  13. public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
  14. response.getOutputStream().write("ServletContext4".getBytes());
  15. }
  16. public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
  17. doGet(request,response);
  18. }
  19. }