21.Servlet 技术
作者:mmseoamin日期:2023-12-19

JavaWeb应用的概念

在Sun的Java Servlet规范中,对Java Web应用作了这样定义:“Java Web应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的 Servlet容器 中运行。”

Java Web应用中可以包含如下内容:

• Servlet

• JSP

• 实用类

• 静态文档如HTML、图片等

• 描述Web应用的信息(web.xml)

Servelt 与 Servlet 容器

21.Servlet 技术,在这里插入图片描述,第1张

Servlet容器的概念

Servlet容器为JavaWeb应用提供运行时环境,它负责管理Servlet和JSP的生命周期,以及管理它们的共享数据。Servlet容器也称为JavaWeb应用容器,或者Servlet/JSP容器。

目前最流行的Servlet容器软件括:

• Tomcat

• Resin

• J2EE服务器(如Weblogic)中也提供了内置的Servlet容器

Servlet 简介

Java Servlet是和平台无关的服务器端组件,它运行在Servlet容器中。Servlet容器负责Servlet和客户的通信以及调用Servlet的方法,Servlet和客户的通信采用“请求/响应”的模式。

Servlet可完成如下功能:

• 处理请求;

• 发出响应

Servlet容器响应客户请求的过程

21.Servlet 技术,在这里插入图片描述,第2张

ServletAPI

21.Servlet 技术,在这里插入图片描述,第3张

Servlet 创建的三种方式

实现 Servlet 接口

21.Servlet 技术,在这里插入图片描述,第4张

继承 HttpServlet 类

21.Servlet 技术,在这里插入图片描述,第5张

继承 GenericServlet 类(几乎不用)

21.Servlet 技术,在这里插入图片描述,第6张

Servlet的注册与运行

• Servlet程序必须通过Servlet容器来启动运行,并且储存目录有特殊要求,通需要存储在\WEB-INF\classes\目录中。

• Servlet程序必须在WEB应用程序的web.xml文件中进行注册和映射其访问路径,才可以被Servlet引擎加载和被外界访问。

• 一个元素用于注册一个Servlet,它包含有两个主要的子元素:和,分别用于设置Servlet的注册名称和Servlet的完整类名。

• 一个元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:和,分别用于指定Servlet的注册名称和Servlet的对外访问路径。

21.Servlet 技术,在这里插入图片描述,第7张

Servlet映射的细节

• 同一个Servlet可以被映射到多个URL上,即多个元素的子元素的设置值可以是同一个Servlet的注册名。

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

Servlet容器响应客户请求的过程

• ①Servlet引擎检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。

• ②装载并创建该Servlet的一个实例对象:调用该 Servlet 的构造器

• ③调用Servlet实例对象的init()方法。

• ④创建一个用于封装请求的ServletRequest对象和一个代表响应消息的ServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。

• ⑤WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

Servlet对象生命周期

Servlet对象什么时候生,什么时候死.

生命周期相关的三个方法, init,service,destroy

• init(ServletConfig config)Servlet对象的初始化方法,对象被创建的时候调用

• service(request,response)客户端访问一次,执行一次

• destory()Servlet对象销毁之前调用

• Servlet对象什么时候被创建

  • Servlet默认第一次访问的时候,对象被创建
  • Tomcat服务器启动的时候创建对象,需要修改web.xml (一般不配置)(5)

    • Servlet对象什么时候被销毁

    • 停止Tomcat服务器
    • WEB项目从服务器移除

      ServletConfig 接口

      • Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外部的资源,所以,Serlvet引擎需要将表示Servlet容器的对象传递给Servlet。另外,在web.xml文件中为某个Servlet设置的友好名称和初始化参数等信息也需要传递给该Servlet

      • Servlet引擎将代表Servlet容器的对象(ServletContext)和Servlet的配置参数信息一并封装到一个称为ServletConfig的对象中,并在初始化Servlet实例对象时传递给该Servlet。ServletConfig接口则用于定义ServletConfig对象需要对外提供的方法,以便在Servlet程序中可以调用这些方法来获取有关信息。

      • Servlet引擎调用Servlet的实例对象的init(ServletConfig config)方法将ServletConfig对象传递给Servlet。Servlet.getServletConfig()方法必须返回init(ServletConfig config)方法传递进来的这个ServletConfig对象的引用。

      配置 Serlvet 的初始化参数
      
      		helloServlet
      		com.javaweb.HelloServlet
      		
      		
      			
      			user
      			
      			root
      			
      		
      			password
      			1230
      			
      		-1	
      	
      

      ServletConfig接口的方法

      • getInitParameterNames() 获取某servlet中所有参数名字,返回值为Enumeration 对象

      • getInitParameter(String name) 根据某参数名字获取对应的值

      • getServletName(): 获取servlet名字

      • getServletContext: 获取ServletContext对象

      获取初始化参数
      	String user = servletConfig.getInitParameter("user");
      	System.out.println("user: " + user);
      	
      	Enumeration names = servletConfig.getInitParameterNames();
      	while(names.hasMoreElements()){
      		String name = names.nextElement();
      		String value = servletConfig.getInitParameter(name);
      		System.out.println(name + ": " + value);
      	}
      

      ServletContext接口

      • Servlet引擎为每个WEB应用程序都创建一个对应的ServletContext对象,ServletContext对象被包含在ServletConfig对象中,调用ServletConfig.getServletContext方法可以返回ServletContext对象的引用。

      • 由于一个WEB应用程序中的所有Servlet都共享同一个ServletContext对象,所以,ServletContext对象被称之为 application 对象(Web应用程序对象)。

      • 可以认为 SerlvetContext 是当前 WEB 应用的一个大管家. 可以从中获取到当前 WEB 应用的各个方面的信息.

      • 功能:

      • 获取WEB应用程序的初始化参数
      • 记录日志
      • application域范围的属性
      • 访问资源文件
      • 获取虚拟路径所映射的本地路径
      • WEB应用程序之间的访问
      • ServletContext的其他方法
        配置WEB应用程序的初始化参数

        在web.xml文件的根元素中增加子元素,如下所示:

        
        	driver
        	com.mysql.jdbc.Driver
        
        
        获取WEB应用程序的初始化参数
        	//getInitParameter
        	//getInitParameterNames
        ServletContext servletContext = servletConfig.getServletContext();
        		
        String driver = servletContext.getInitParameter("driver");
        System.out.println("driver:" + driver);
        Enumeration names2 = servletContext.getInitParameterNames();
        while(names2.hasMoreElements()){
        	String name = names2.nextElement();
        	System.out.println("-->" + name); 
        }
        
        ServletContext接口其他方法

        获取当前 WEB 应用的某一个文件在服务器上的绝对路径, 而不是部署前的路径:

        String realPath = servletContext.getRealPath(“/note.txt”);

        System.out.println(realPath);

        获取当前 WEB 应用的名称:

        String contextPath = servletContext.getContextPath();

        ServletContext对象是一个容器,可以存储数据.

        对象有个作用域问题,ServletContext作用域是整个WEB应用程序。

        • 向域对象存储数据: setAttribute(String key, Object value)

        • 取出域对象数据: Object getAttribute(String key)

        • 移除域对象数据: removeAttribute(String key)

        ServletContext context =servletConfig.getServletContext();

        //域对象存储数据,键值对

        context.setAttribute(“hello”,“java”);

        //取出域对象存储的键值对

        Object value = context.getAttribute(“hello”);

        统计访问的次数

        • 练习域对象ServletContext的使用

        • 第一次访问Servlet的时候,数据1存储到域对象

        • 第二次访问,从域中取出数据++,存储回去

        	public void init() throws ServletException {
            	ServletContext context = getServletContext();
            	context.setAttribute("count",1);
        	}
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            ServletContext context = getServletContext();
            Integer count = (Integer) context.getAttribute("count");
            response.getWriter().print("welcome "+count);
            count++;
            context.setAttribute("count",count);
        }
        
        注解开发取代web.xml

        @WebServlet,注解添加到自己定义的Servlet中的类声明上即可

        注解的属性 urlPatterns,属性值就是浏览器的访问地址.

        @WebServlet(urlPatterns = “/test”)

        Request对象概述

        Request对象获取客户端的请求数据, 接口ServletRequest,子接口HttpServletRequest继承ServletRequest.

        HttpServletRequest接口的实现类是Tomcat引擎提供.

        servlet请求方式GET/POST
        Request对象获取请求行

        • String getMethod() 获取提交的方式 (GET,POST)

        • String getRequestURI() 获取请求的参数,请求服务器路径

        • StringBuffer getRequestURL() 获取请求的参数,请求服务器路径

        • String getQueryString()获取请求行 问号后面的参数 (GET)

        • String getContextPath() 获取WEB应用名称

        	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //request对象方法 getMethod()获取客户端的请求方式
            String method = request.getMethod();
            System.out.println(method);
            //方法 String getRequestURI() 获取请求服务器路径
            //方法 StringBuffer getRequestURL() 获取请求服务器路径
            String URI = request.getRequestURI();
            StringBuffer URL = request.getRequestURL();
            System.out.println("URI=="+URI); 
            System.out.println("URL=="+URL);
            //方法 String getQueryString()获取请求行,?后面的所有参数
            String query = request.getQueryString();
            System.out.println(query);
            //获取WEB应用名称  String getContextPath()
            String path = request.getContextPath();
            System.out.println(path);
        }
        
        Request对象获取请求头

        请求头数据格式键值对, k:v

        指导性信息,指导服务器

        • String getHeader(String key)返回对应键的值

        • Enumeration getHeaderNames()

        	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            /*
             * request获取请求头
             */
             //方法  String getHeader(String key)
            String key = request.getHeader("Referer");
            System.out.println(key);
            /*
             * Enumeration getHeaderNames() 获取所有的请求头的键
             * 返回值Enumeration接口 (向量枚举)
             * 集合:1.0-1.1 Enumeration    集合1.2  迭代器
             * Iterator迭代器接口:  hasNext()   next()
             * Enumeration接口:  hasMoreElement()  nextElement()
             */
            Enumeration enums  = request.getHeaderNames();
            while (enums.hasMoreElements()){
                 key = enums.nextElement();
                 String value = request.getHeader(key);
                System.out.println(key+"=="+value);
            }
        }
        
        Request获取请求参数

        • String getParameter(“表单中的name值”)获取指定的请求参数

        • String[] getParameterValues(“表单中的name值”)获取参数中的一键多值

        • Map getParameterMap()获取提交的所有参数

        	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            /*
             * request 获取客户端提交数据
             */
            //方法getParameter(String key)指定表单中的参数
            String username = request.getParameter("username");
            String password = request.getParameter("pass");
            System.out.println(username+"=="+password);
            //方法getParameterValues()获取一键多值  checkbox  radio
            String[] hobby = request.getParameterValues("hobby");
            System.out.println(Arrays.toString(hobby));
            System.out.println("=============");
            //方法 getParameterMap()获取提交的所有参数
            Map map = request.getParameterMap();
            for (String key : map.keySet()){
                String[] value = map.get(key);
                System.out.println(key+"="+Arrays.toString(value));
            }
        }
        
        Request域对象

        作用域: Request域对象的作用域比较小,范围是一次请求有效.

        • 域对象存储数据: setArratibute(String key, Object value)

        • 取出域对象数据: Object getAttribute(String key)

        • 移除域对象数据: removeAttribute(String key)

        	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //向域对象 ,request 存储数据
            request.setAttribute("hello","java");
            //取出域对象数据
            Object value = request.getAttribute("hello");
            System.out.println("servlet1="+value);
        }
        
        Response对象概述

        • 负责对浏览器进行响应的对象

        • ServletResponse接口,HttpServletResponse接口继承自ServletResponse

        • 使用的是子接口HttpServletResponse,此接口对象由Tomcat引擎提供

        • 可以实现对客户端的响应, 响应行,响应头,响应体

        Response设置响应行

        • 设置状态码: setStatus(int 状态码)

        response.setStatus(500);

        Response设置响应头

        HTTP协议的响应头,数据格式键值对 k:v

        包含指导性信息,指导客户端

        • addHeader(String key,String value)

        • addIntHeader(String key,int value)

        • addDateHeader(String key,long l)

        • setHeader(String key,String value)

        • setIntHeader(String key,int value)

        • setDateHeader(String key,long l)

        	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            /*
             * response对象设置响应头
             */
            response.addHeader("hello","java");
          /*  response.addIntHeader("good",5);
            response.addDateHeader("date",System.currentTimeMillis());*/
            /*
             * addHeader() 添加,实现一个键对应多个值
             * setHeader() 设置,原来的键覆盖
             */
            response.setHeader("hello","java2222");
        }
        
        Response设置响应体

        HTTP的响应体,就是页面的正文部分.

        • getWriter() 返回值是打印流PrintWrite.

        	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              /*
               * response对象方法getWriter()
               * 打印流的响应体
               * write() 使用字符串数据,没有差别, 输出是整数,查询编码表
               * print() 无论是什么,原样打印
               */
               PrintWriter pw =  response.getWriter();
               pw.write(100);
               pw.print(100);
          }
        
        响应中的中文乱码问题

        产生乱码原因: 编码和解码不一致.

        response.setContentType(“text/html;charset=UTF-8”);