美文网首页
四、Servlet介绍

四、Servlet介绍

作者: 艾特小师叔 | 来源:发表于2020-03-13 22:56 被阅读0次

    Servlet入门

    前言:

    在前面的学习过程中,JavaWeb开发,其实是利用网络和HTTP协议,将服务端的数据,发送给客户端,且可以接收客户端的请求,并且对这个请求作出响应。基于这个原理,早期制定了一套根据这样的逻辑与客户端进行交互的接口,而各个服务器,则根据这个接口作出具体的实现。这样,在服务器端,就运行了一套程序,一套用于接收客户端请求,向客户端作出响应程序,这个程序就被称之为Servlet。

    Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。根据这点,Servlet本身也是一套规范(接口),也是一个具体运行在服务端程序。

    狭义的Servlet是指Java语言实现的一个接口。

    广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。

    由于,Servlet生成Web内容,都是使用Java代码生成,所以,开发WEB异常的麻烦。基于这点,Java在Servlet的基础上,衍生出了JSP模板基础,作为Servlet技术的补充点。所以,JSP与Servlet关系,JSP源于Servlet.

    注意:

    Servlet是服务器实现的一套规范,其具体的API是在服务器中,所以一般不需要导入任何jar包,一般使用服务器中内置jar包。

    1.如何使用Servlet

    1. 创建类实现Servlet接口,实现相关方法

      package com.sxt.controller;
      
      import java.io.IOException;
      
      import javax.servlet.Servlet;
      import javax.servlet.ServletConfig;
      import javax.servlet.ServletException;
      import javax.servlet.ServletRequest;
      import javax.servlet.ServletResponse;
      
      /**
       * @ClassName: MyServlet 
       * @Description: 创建一个具体的Servlet
       *               1. 定义类实现Servlet接口
       *               2. 重写相关方法
       * @author: Mr.T
       * @date: 2020年2月11日 下午2:41:11
       */
      public class MyServlet implements Servlet{
       
       @Override
       public ServletConfig getServletConfig() {
           System.out.println("==========config==========");
           return null;
       }
       
       @Override
       public void init(ServletConfig arg0) throws ServletException {
           System.out.println("==========init==========");
       }
      
       @Override
       public String getServletInfo() {
           return null;
       }
      
       @Override
       public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
           System.out.println("==========service==========");
       }
       
       @Override
       public void destroy() {
           System.out.println("==========destroy==========");
       }
      
      }
      
      
    2. 注册Servlet,配置对外访问的地址

      程序是在服务器中运行的,如果创建类实现Servlet接口,此时只是创建了一个遵循Servlet规范的类。但是,Servlet本质是一个在服务器中运行的小程序。得通知服务器,我们创建了一个遵循Servlet规范的类,让服务器将这个类装载到Servlet容器中,所以需要进行配置。

      在tomcat中,tomcat会默认监视:web.xml.而web.xml,是一个xml文件。xml中标签和节点,可以根据xml约束dtd等进行限定。这样就可以在web.xml中进行相关程序的配置,tomcat就可以对web.xml中的配置信息进行解析。

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
        <display-name>07servlet01</display-name>
        <welcome-file-list>
          <welcome-file>index.html</welcome-file>
          <welcome-file>index.htm</welcome-file>
          <welcome-file>index.jsp</welcome-file>
          <welcome-file>default.html</welcome-file>
          <welcome-file>default.htm</welcome-file>
          <welcome-file>default.jsp</welcome-file>
        </welcome-file-list>
        
        <!-- 注入servlet -->
        <servlet>
           <!-- servlet别名  方便使用 -->
           <servlet-name>chengfusheng</servlet-name>
           <!-- servlet本质上一个类,包名.类名    类的全路径 -->
           <servlet-class>com.sxt.controller.MyServlet</servlet-class>
           <!-- 
               以上配置是告诉服务器,有一个servlet 可以被使用,servlet的功能是接收客户端的数据 作出响应
                所以得配置一个网络地址,便于客户端进行访问
            -->
        </servlet>
        <!-- 配置网络映射地址  用于客户端访问-->
        <servlet-mapping>
           <servlet-name>chengfusheng</servlet-name>
           <url-pattern>/ergou.do</url-pattern>
        </servlet-mapping>
        
      </web-app>
      

      3.客户端访问Servlet

    servlet01.png

    2.Servelt被调用的流程

    servlet被调用的原理.png
    servlet调用顺序.png

    3.Servlet的三种实现方式

    方式一:直接实现Servlet接口,参看上面示例。

    方式二:继承GenericServlet

    /**
     * @ClassName: MyServlet02 
     * @Description: 实现Servlet的第二种方式
     * @author: Mr.T
     * @date: 2020年2月11日 下午4:02:12
     */
    public class MyServlet02  extends GenericServlet{
    
        /**
         * 序列号
         *  servlet类主要用于与客户进行数据交互.一般需要将数据序列化进行传输。
         *  如果没有序列化号,1.安全性存在问题. 2.在实际使用中,很多框架,需要存在需要列号,会出现null的 问题。
         */
        private static final long serialVersionUID = -4448635233323484080L;
        
        /**
         *  service 方法  servlet 提供具体的服务的方法
         */
        @Override
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            
        }
    
    }
    
    <!-- 配置servlet -->
      <servlet>
        <servlet-name>suxiaoxiao</servlet-name>
        <servlet-class>com.sxt.controller.MyServlet02</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>suxiaoxiao</servlet-name>
        <url-pattern>/suxiaoxiao.do</url-pattern>
      </servlet-mapping>
    

    方式三:继承HttpServlet

    package com.sxt.controller;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * @ClassName: MyServlet03 
     * @Description: servlet的第三种方式  
     * @author: Mr.T
     * @date: 2020年2月11日 下午4:09:18
     */
    public class MyServlet03 extends HttpServlet {
    
        private static final long serialVersionUID = -91495684423730465L;
        /**
         *  重写父类中的service
         *      此时 service中的参数:HttpServletRequest    HttpServletResponse  
         *  这个方法的功能是最强大的
         */
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("service");
            resp.getWriter().print("Hello HttpServlet");
        }
        
    
    }
    
    
        <!-- 配置servlet -->
      <servlet>
        <servlet-name>myServlet03</servlet-name>
        <servlet-class>com.sxt.controller.MyServlet03</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>myServlet03</servlet-name>
        <url-pattern>/myServlet03.do</url-pattern>
      </servlet-mapping>
    

    注意:

    在实际使用中,Servlet一般使用第三种方式,因为第三种方式定制化更强。并且提供了专门根据客户端请求的方法的不同,提共了专门的处理方法。会根据客户端method的值的不同,进行相应的方法调用。

    HttpServlet.png

    4.Servlet的生命周期

    servlet的生命周期,其实是指Servlet类的对象的生命周期,是指Servlet类对象的初始化,及Servlet类对象的销毁。

    package com.sxt.controller;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServlet;
    
    /**
     * @ClassName: LifeCycleServlet 
     * @Description: 此Servlet类,用于演示Servlet的生命周期
     * @author: Mr.T
     * @date: 2020年2月11日 下午4:45:57
     */
    public class LifeCycleServlet extends HttpServlet {
        
        private static final long serialVersionUID = -4411061286729536572L;
    
        /**
         *  当servlet 对象创建后  需要对属性进行初始化 可以调用 init 
         *  且  init 方法只会执行一次
         */
        @Override
        public void init() throws ServletException {
            System.out.println("==============init 出生了=============");
        }
        
        /**
         *  当有请求,访问当前servlet,那么将有service处理当前请求,每次请求都会调用service
         *  有多少次请求,那么service就会被调用多少次
         */
        @Override
        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
            System.out.println("=============service  开始打工=================");
        }
        /**
         *  destory 方法,当服务器停止,开始释放内存,此时调用destory 方法,且只会调用一次。
         */
        @Override
        public void destroy() {
            System.out.println("=================destory  悄悄的离开了=================");
        }   
    }
    
    

    注意:

    1.生命周期

    Servlet中的init方法,只会执行一次,当servlet对象被初始化后执行一次,进行对象属性值的初始化。

    Servlet中的service方法,是处理具体的请求的方法,每次请求时都会执行。

    Servlet中destory方法,是用于Servlet对象要被销毁时调用的方法。只会执行一次。可以将内存中的数据,在销毁前做一些处理。

    2.Servlet生命周期引发的线程安全问题

    在Servlet中,每个Servlet默认只会创建一个实例对象,Servlet是单例的。所以,Servlet是非线程安全的

    在使用Servlet时,不要使用成员变量。

    3.Servlet的初始化

    默认Servlet是在第一被请求时,才会进行Servlet对象的创建,调用init方法,进行属性的初始化。

    但是,可以通过在web.xml中配置Servlet的初始化时机,配置信息如下:

      <!-- 配置servlet -->
      <servlet>
        <servlet-name>LifeCycleServlet</servlet-name>
        <servlet-class>com.sxt.controller.LifeCycleServlet</servlet-class>
        <!-- 
            初始的参数 
            如果多组参数  使用 多个 init-param 标签
        -->
        <init-param>
            <param-name>key1</param-name>
            <param-value>value1</param-value>
        </init-param>
        <init-param>
            <param-name>key2</param-name>
            <param-value>value2</param-value>
        </init-param>
         <!-- 
            配置servlet的初始时机 
            只要值大于 0  那么,当服务器启动时就会进行该Servlet的初始化 就会创建该Servlet对象
            
        -->
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>LifeCycleServlet</servlet-name>
        <url-pattern>/lifeCycle.do</url-pattern>
      </servlet-mapping>
    
    @Override
        public void init() throws ServletException {
            //获取Servlet配置对象
            ServletConfig servletConfig = this.getServletConfig();
            //通过ServletConfig 对象拿到配置参数
            System.out.println(servletConfig.getInitParameter("key1"));
            System.out.println(servletConfig.getInitParameter("key2"));
            System.out.println(this);
            System.out.println("==============init 出生了=============");
        }
    

    5.Servlet使用

    Servlet主要功能就是接受客户端的请求,对客户端作出响应。而这个功能由Servlet中的service方法实现,所以Servlet使用,就是service方法的使用,service方法,有ServletRequest和ServletResponse.

    ServletRequest,是服务器,将所有的请求信息封装在该对象

    ServletResponse,是服务器,将响应信息,封装在该对象中。

    而HttpServletRequest是ServletRequest的一个子类,HttpServletResponse是ServletResponse的子类。

    5.1.HttpServletRequest使用

    package com.sxt.controller;
    
    import java.io.IOException;
    import java.util.Enumeration;
    import java.util.Map;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.catalina.tribes.util.Arrays;
    
    /**
     * @ClassName: ServletMethod 
     * @Description: 该方法主要用于演示 Servlet中  request 和  response的核心方法
     * @author: Mr.T
     * @date: 2020年2月11日 下午5:38:10
     */
    public class ServletMethod extends HttpServlet {
    
        private static final long serialVersionUID = -6390310195529724055L;
    
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //getHttpInfo(req,resp);
            getRequestParam(req,resp);
        }
    
        /**
         * @Title: getHttpInfo
         * @author: Mr.T   
         * @date: 2020年2月11日 下午5:39:36 
         * @Description: 获取Http请求信息
         * @return: void
         */
        public void getHttpInfo(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取HTTP请求的method值 : get  post  等等
            String method = req.getMethod();
            System.out.println(method);
            //获取HTTP请求的URL地址
            StringBuffer url = req.getRequestURL();
            System.out.println(url);
            //获取请求的资源路径
            String uri = req.getRequestURI();
            System.out.println(uri);
            //获取请求协议
            String protocol = req.getProtocol();
            System.out.println(protocol);
            //获取本地端口
            int localPort = req.getLocalPort();
            System.out.println(localPort);
            //获取请求头  请求头是  key - value 
            String host = req.getHeader("Host");
            System.out.println(host);
        }
        
        /**
         * @Title: getRequestParam
         * @author: Mr.T   
         * @date: 2020年2月11日 下午5:49:25 
         * @Description: 获取请求参数
         * @param req
         * @param resp
         * @throws ServletException
         * @throws IOException
         * @return: void
         */
        public void getRequestParam(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //设置请求参数编码格式
            req.setCharacterEncoding("UTF-8");
            //getParameter(name) : 根据name值 获取对应提交的参数
            String name = req.getParameter("name");
            System.out.println(name);
            //getParameterValues(name) :根据name值 获取对应提交的参数,一般用于数组类型的数据,例如复选框
            String[] likes = req.getParameterValues("like");
            System.out.println("爱好:"+Arrays.toString(likes));
            //获取所有的请求参数的name值
            Enumeration<String> parameterNames = req.getParameterNames();
            while(parameterNames.hasMoreElements()) {
                //循环遍历所有的参数的名称
                System.out.println(parameterNames.nextElement());
            }
            //将请求参数封住成一个Map
            Map<String, String[]> parameterMap = req.getParameterMap();
            System.out.println(parameterMap);
            //进行页面跳转 内部转发
            req.getRequestDispatcher("index.jsp").forward(req, resp);
        }
        /**
         * @Title: attributeMethod
         * @author: Mr.T   
         * @date: 2020年2月11日 下午6:09:26 
         * @Description: request 属性相关方法
         * @param req
         * @param resp
         * @throws ServletException
         * @throws IOException
         * @return: void
         */
        public void attributeMethod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //  向request 作用域设置属性值
            //req.setAttribute(name, o);
            //从request 作用域中取值
            //req.getAttribute(name)
            // 获取request 作用域中所有的属性name值
        }
        /**
         * @Title: scope
         * @author: Mr.T   
         * @date: 2020年2月11日 下午6:11:15 
         * @Description: 根据request 对象 获取其他作用域
         * @param req
         * @param resp
         * @throws ServletException
         * @throws IOException
         * @return: void
         */
        public void scope(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //根据request 获取与之关联的session
            req.getSession();
            // 获取application作用域
            req.getServletContext();
        }
    }
    
    

    5.2.HttpServletResponse使用

        /**
         * @Title: responseMethod
         * @author: Mr.T   
         * @date: 2020年2月11日 下午6:14:06 
         * @Description: response 响应对象中的核心方法
         * @param req
         * @param resp
         * @throws ServletException
         * @throws IOException
         * @return: void
         */
        public void responseMethod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //设置响应数据的编码
            resp.setCharacterEncoding("UTF-8");
            //设置响应头信息
            resp.addHeader("key11111111111", "value11111222222");
            // 获取打印流对象  向客户端输出数据  一般是文本数据
            //PrintWriter writer = resp.getWriter();
            //writer.print("Hello Servlet");
            // 设置Cookie addCookie
            //resp.addCookie(cookie);
            //获取字节输出流  一般用于文件下载
            //ServletOutputStream outputStream = resp.getOutputStream();
            //地址跳转    重定向
            resp.sendRedirect("index.jsp");
        }
    }
    

    相关文章

      网友评论

          本文标题:四、Servlet介绍

          本文链接:https://www.haomeiwen.com/subject/zbrushtx.html