• JavaWeb(一)-Servlet知识


    一、Servlet简介

    Servlet是sun公司提供一门用于开发动态web资源的技术。

    sun公司在其API中提供了一个servlet接口,用户若想开发一个动态web资源(即开发一个java程序向浏览器输出数据),需要完成以下步骤即可:

    1、编写一个java类,实现servlet接口

    2、把研发好的java类部署到web服务器(配置路径)

    所以servlet本身是一个java类,这种java类可以提供web形式的访问,通过Java的API动态的向客户输出内容。

    Servlet是JavaWeb的三大组件(filter,Servlet,listener)之一,客户端发出请求,这些请求都交由servlet来处理,接受请求数据(传过来的参数值)、

    处理请求、发回响应。每个servlet都必须实现javax.servle.Servlet接口。

    二、Servlet运行过程

    servlet程序是由web服务器调用,web服务器受到客户端的请求后:

    1. web服务器首先检查是否已经装载了servlet的实例对象,如果是直接执行第四步,否则执行第二步
    2. 装载并创建一个servlet的实例对象
    3. 调用servlet实例对象的哦init()方法进行初始化
    4. 创建一个用于封装HTTP请求消息的httpservletRequest对象和一个代表HTTP响应信息的httpservletResponse对象,然后调用service()方法,请求和响应对象作为参数
    5. web应用程序被停止或者重新启动之前,servlet引擎将卸载servlet,并在卸载之前调用servlet的destory()方法进行销毁

     

    三、实现一个Servlet

    3.1实现javax.Servlet.Servlet接口

    package com.briup.web.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.nio.charset.Charset;
    
    import javax.servlet.Servlet;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    //向浏览器写会一个页面
    public class Test3_Servlet implements Servlet{
    
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		// TODO Auto-generated method stub
    		
    	}
    	@Override
    	public ServletConfig getServletConfig() {
    		// TODO Auto-generated method stub
    		return null;
    	}
    	@Override
    	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    		//向页面写东西第一步设置编码格式与内容格式
    		res.setContentType("text/html;charset=utf-8");
    		//向页面写回东西
    		PrintWriter out = res.getWriter();
    		out.println("<html>");
    		out.println("<head>");
    		out.println("<title>test</title>");
    		out.println("</head>");
    		out.println("<body>");
    		out.println("<h1>helloworld</h1>");
    		out.println("</body>");
    		out.println("</html>");
    		//将缓冲带输出干净
    		out.flush();
    	}
    	@Override
    	public String getServletInfo() {
    		// TODO Auto-generated method stub
    		return null;
    	}
    	@Override
    	public void destroy() {
    		// TODO Auto-generated method stub
    		
    	}
    }
    

      在servlet接口中共有五个方法,void init()方法是用来初始化servlet对象时调用的;ServletConfig getServletConfig()方法返回一个servletConfig对象,

    以后会介绍这个对象的用途;void service()方法是在访问servlet对象的时候被调用;String getServletInfo()返回servlet的相关信息,比如作者、版权、版本等;

    void destory()在销毁servlet的时候被调用。

    3.2继承javax.servlet.GenericServlet类

    package com.briup.web.servlet;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    import javax.servlet.GenericServlet;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebServlet;
    //实现servlet的第二种方式继承GenericServlet类,然后实现在网页上展示图片的功能
    //该类中只有一种抽象方法只需要实现这个抽象方法就可以了
    //用字节流用页面输出一张图片
    @WebServlet("/young")
    public class Test_Servlet extends GenericServlet{
    
    	@Override
    	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		InputStream in=Test_Servlet.class.getClassLoader().getResourceAsStream("1.jpg");
    		//类加载器把类变成流
    		int len = in.available();//流无间断的输出的长度
    		byte [] bug=new byte[len];
    		in.read(bug);//读取这个流
    		res.setContentType("image/jpeg");//设置响应的格式
    		ServletOutputStream out=res.getOutputStream();//用res向页面输出
    		out.write(bug);
    		out.flush();
    		if(in!=null) in.close();
    	}
    
    }
    

      抽象类genericServlet里面只有一个抽象方法service,它实现了servlet接口的其余四个抽象方法,所以我们需要重写这个方法就行了。

    3.3继承javax.servlet.HttpServlet类

    package com.briup.web.servlet;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class Test2_Servlet
     */
    @WebServlet("/Test2_Servlet")//实现servlet的第三种方式,继承httpservlet
    //这个httpservlet类中没有任何的抽象方法,但是可以重写两个写好的方法
    //向页面输出一句话
    public class Test2_Servlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
      
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		response.getWriter().println("test2");
    		String path = request.getServletPath();
    		System.out.println(path);
    	}
    
    	
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    

      httpservlet是一个抽象类,但是没有任何的抽象方法。httpservlet中定义了许多的doXXXX()方法,每一种方法都对应了浏览器发送请求的方法,

    一般常用浏览器发送请求的方法为get和post方式的,所以我们基本上都是重写这两个方法,下面是httpservlet类中的一些源代码,还有一些doxxxx()方法没有列出。

     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
        {
            String protocol = req.getProtocol();
            String msg = lStrings.getString("http.method_get_not_supported");
            if (protocol.endsWith("1.1")) {
                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
            } else {
                resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
            }
        }
     protected void doHead(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
    
            if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
                doGet(req, resp);
            } else {
                NoBodyResponse response = new NoBodyResponse(resp);
                doGet(req, response);
                response.setContentLength();
            }
        }
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
    
            String protocol = req.getProtocol();
            String msg = lStrings.getString("http.method_post_not_supported");
            if (protocol.endsWith("1.1")) {
                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
            } else {
                resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
            }
        }
    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
    
            String protocol = req.getProtocol();
            String msg = lStrings.getString("http.method_put_not_supported");
            if (protocol.endsWith("1.1")) {
                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
            } else {
                resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
            }
        }
    

      

    四、servlet的生命周期

    4.1生命周期相关方法和特点

    void init():servlet对象创建之后马上执行的初始化方法,只执行一次;

    void service():每次请求都是调用这个方法,它会被调用很多次;

    void destory():在servlet被销毁之前调用,负责释放servlet对象占用资源的方法。

    特点:线程不安全的,所以效率较高;servlet类由自己编写,但对象由服务器来创建,并有服务器来调用相关的方法。

    4.2生命周期

    1.servlet是单例,所以servlet在运行期间只会运行创建一个servlet

    2.默认情况下,servlet对象在用户第一次访问的时候,由Tomcat服务器来创建

    3.servlet对象创建成功后,Tomcat服务器会通过层层调用,无参的init方法对创建好的servlet对象进行初始化

    4.如果用户要访问这个servlet对象,那么Tomcat服务器会调用servlet对象中的service方法,最后通过层层调用,调用到的是

     我们重写到的doget()和dopost()方法

    5.当servlet对象被销毁的时候,Tomcat会调用servlet的destory方法,程序员就可以调用这个方法进行销毁

    6.可以通过修改web.xml文件的配置,去改变servlet对象的创建时间,<servlet-on-startup>标签里面设置一个整数值

    数值的大小可以决定servlet对象被创建的先后顺序,数值越小越先被创建,默认情况下是0。

    图解:

     详细说明:

    五、Servlet工作原理

            首先简单解释一下Servlet接收和响应客户请求的过程,首先客户发送一个请求,Servlet是调用service()方法对请求进行响应的,通过源代码可见,

    service()方法中对请求的方式进行了匹配,选择调用doGet,doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。

    在Servlet接口和GenericServlet中是没有doGet,doPost等等这些方法的,HttpServlet中定义了这些方法,但是都是返回error信息。

    所以,我们每次定义一个Servlet的时候,都必须实现doGet或doPost等这些方法。

      每一个自定义的Servlet都必须实现Servlet的接口,Servlet接口中定义了五个方法,其中比较重要的三个方法涉及到Servlet的生命周期,

    分别是上文提到的init(),service(),destroy()方法。GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。

    而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可。

    只有一个需要实现的抽象方法service

    定义了很多变量和很多方法,我们可以重写一些需要的方法。

    Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,

    并将请求ServletRequest,ServletResponse强转为HttpRequest和HttpResponse。

    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
    
            HttpServletRequest  request;
            HttpServletResponse response;
    
            try {
                request = (HttpServletRequest) req;
                response = (HttpServletResponse) res;
            } catch (ClassCastException e) {
                throw new ServletException("non-HTTP request or response");
            }
            service(request, response);
        }
    }
    

      代码的最后调用了HTTPServlet自己的service(request,response)方法,然后根据请求去调用对应的doXXX方法,因为HttpServlet中的doXXX方法都是返回错误信息,

     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
        {
            String protocol = req.getProtocol();
            String msg = lStrings.getString("http.method_get_not_supported");
            if (protocol.endsWith("1.1")) {
                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
            } else {
                resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
            }
        }
    

      所以我们需要在servlet类中重写这些方法。

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Servlet响应请求阶段:

      对于用户到达Servlet的请求,Servlet容器会创建特定于这个请求的ServletRequest对象和ServletResponse对象,然后调用Servlet的service方法。

    service方法从ServletRequest对象获得客户请求信息,处理该请求,并通过ServletResponse对象向客户返回响应信息。

      对于Tomcat来说,它会将传递过来的参数放在一个Hashtable中,该Hashtable的定义是:

       这是一个String-->String[]的键值映射。

      HashMap线程不安全的,Hashtable线程安全。

     -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Servlet终止阶段:

      当WEB应用被终止,或Servlet容器终止运行,或Servlet容器重新装载Servlet新实例时,Servlet容器会先调用Servlet的destroy()方法

    ,在destroy()方法中可以释放掉Servlet所占用的资源。

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Servlet与JSP的比较:

      有许多相似之处,都可以生成动态网页。

      JSP的优点是擅长于网页制作,生成动态页面比较直观,缺点是不容易跟踪与排错。

      Servlet是纯Java语言,擅长于处理流程和业务逻辑,缺点是生成动态网页不直观。

  • 相关阅读:
    自定义 alert 弹窗
    js控制div内的滚动条的位置
    vue 的 起手式
    d3.js封装文本实现自动换行和旋转平移等功能
    redux
    mui 本地打包
    vue-router 运行机制 及 底层原理
    替代 Navigator 组件
    react-native 创建 ios 项目
    三元运算符
  • 原文地址:https://www.cnblogs.com/yfstudy/p/9292106.html
Copyright © 2020-2023  润新知