zoukankan      html  css  js  c++  java
  • javaweb开发之servlet

    一,什么是Servlet?
    Servlet是一个Java编写的程序,此程序是基于Http协议的,在服务器端运行的(如tomcat),是按照Servlet规范编写的一个Java类。Servlet 可以使用 javax.servlet 和 javax.servlet.http 包创建,它是 Java 企业版的标准组成部分,Java 企业版是支持大型开发项目的 Java 类库的扩展版本。


    二,Servlet有什么作用?
    主要是处理客户端的请求并将其结果发送到客户端。
    Servlet 执行以下主要任务:
    1、读取客户端(浏览器)发送的显式的数据。如网页上的 HTML 表单。
    2、读取客户端(浏览器)发送的隐式的 HTTP 请求数据。包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
    3、处理数据并生成结果。这个过程可能需要访问数据库,调用 Web 服务,或者直接计算得出对应的响应。
    4、发送显式的数据(即文档)到客户端(浏览器)。
    5、发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数等


    三,Servlet的生命周期?

    Servlet的生命周期是由Servlet的容器来控制的,它可以分为3个阶段;初始化,运行,销毁。


    初始化阶段:
    1,Servlet容器加载servlet类,把servlet类的.class文件中的数据读到内存中。
    2,然后Servlet容器创建一个ServletConfig对象。ServletConfig对象包含了Servlet的初始化配置信息。
    3,Servlet容器创建一个servlet对象。
    4,Servlet容器调用servlet对象的init()方法进行初始化。


    运行阶段:
    当servlet容器接收到一个请求时,servlet容器会针对这个请求创建servletRequest和servletResponse对象。然后调用service方法。并把这两个参数传递给service方法。Service方法通过servletRequest对象获得请求的信息。并处理该请求。再通过servletResponse对象生成这个请求的响应结果。然后销毁servletRequest和servletResponse对象。我们不管这个请求是post提交的还是get提交的,最终这个请求都会由service方法来处理。
     
    销毁阶段:当Web应用被终止时,servlet容器会先调用servlet对象的destrory方法,然后再销毁servlet对象,同时也会销毁与servlet对象相关联的servletConfig对象。我们可以在destroy方法的实现中,释放servlet所占用的资源,如关闭数据库连接,关闭文件输入输出流等。


    在这里该注意的地方:
    在servlet生命周期中,servlet的初始化和和销毁阶段只会发生一次,而service方法执行的次数则取决于servlet被客户端访问的次数




    四,Servlet怎么处理一个请求?
    doGet() 方法
    GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。
    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws ServletException, IOException {
        // Servlet 代码
    }
    doPost() 方法
    POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response)
        throws ServletException, IOException {
        // Servlet 代码
    }
    service() 方法
    service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。
    下面是该方法的特征:
    public void service(ServletRequest request, 
                        ServletResponse response) 
          throws ServletException, IOException{
    }
    service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,只需要根据来自客户端的请求类型来重载 doGet() 或 doPost() 即可。




    五,Servlet与JSP有什么区别?
    1,jsp经编译后就是servlet,也可以说jsp等于servlet。
    2,jsp更擅长页面(表现)。servlet更擅长逻辑编辑。 (最核心的区别)。
    3,在实际应用中采用Servlet来控制业务流程,而采用JSP来生成动态网页.在struts框架中,JSP位于MVC设计模式的视图层,而Servlet位于控制层。
     


    六,创建Servlet
    Servlet 是服务 HTTP 请求并实现 javax.servlet.Servlet 接口的 Java 类。Web 应用程序开发人员通常编写 Servlet 来扩展 javax.servlet.http.HttpServlet,并实现 Servlet 接口的抽象类专门用来处理 HTTP 请求。下面为一个helloworld实例。
    / 导入必需的 java 库
    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;


    // 扩展 HttpServlet 类
    public class HelloWorld extends HttpServlet {
     
      private String message;


      public void init() throws ServletException
      {
          // 执行必需的初始化
          message = "Hello World";
      }


      public void doGet(HttpServletRequest request,
                        HttpServletResponse response)
                throws ServletException, IOException
      {
          // 设置响应内容类型
          response.setContentType("text/html");


          // 实际的逻辑是在这里
          PrintWriter out = response.getWriter();
          out.println("<h1>" + message + "</h1>");
      }
      
      public void destroy()
      {
          // 什么也不做
      }
    }
    创建完毕后需要进行在web.xml进行相应的部署使servlet生效。
    <web-app>      
        <servlet>
            <servlet-name>HelloWorld</servlet-name>
            <servlet-class>HelloWorld类的全类名</servlet-class>
        </servlet>


        <servlet-mapping>
            <servlet-name>HelloWorld</servlet-name>
            <url-pattern>/HelloWorld</url-pattern>
        </servlet-mapping>
    </web-app>  
    需要注意的是<servlet-class>需要的是servlet类的全类名,既含包名例如java.lang.String。两个<servlet-name>中的值可以任意,但必须保持一致。<url-pattern>是映射的URL地址。上述映射的地址是http://localhost:8080/HelloWorld。同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。
    在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是"*.扩展名",另一种格式是以正斜杠(/)开头并以"/*"结尾。


    对于一些通配符引起的歧义:
    对于如下的一些映射关系:
      Servlet1 映射到 /abc/* 
      Servlet2 映射到 /* 
      Servlet3 映射到 /abc 
      Servlet4 映射到 *.do 
    问题:
      当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,哪个servlet响应
          Servlet引擎将调用Servlet1。
      当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,哪个servlet响应
          Servlet引擎将调用Servlet3。
      当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,哪个servlet响应
          Servlet引擎将调用Servlet1。
      当请求URL为“/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应
          Servlet引擎将调用Servlet2。
      当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,哪个servlet响应
          Servlet引擎将调用Servlet2。
      匹配的原则就是"谁长得更像就找谁"


    七,Servlet里的过滤器?
    (1)过滤器的主要作用
    1,任何系统或网站都要判断用户是否登录。
    2,网络聊天系统或论坛,功能是过滤非法文字
    3,统一解决编码
    (2)怎么创建一个过滤器:
    1,生成一个普通的class类,实现Filter接口(javax.servlet.Filter;)。
    2,重写接口里面的三个方法:init,doFilter,destroy。
    3,然后在web.xml配置过滤器。


    八,Servlet里的监听器?
    监听器的作用:自动执行一些操作。
    三种servlet监听器:
    对request的监听。对session的监听。对application的监听。


    怎么创建一个session监听器:
    1,生成一个普通的class类,如果是对session的监听,则实现HttpSessionListener。
    2,然后重写里面的五个方法:
    public void sessionCreated(HttpSessionEvent arg0) {} // 创建  
    public void sessionDestroyed(HttpSessionEvent arg0) {} // 销毁  
    public void attributeAdded(HttpSessionEvent arg0) {} // 增加  
    public void attributeRemoved(HttpSessionEvent arg0) {} // 删除  
    public void attributeReplaced(HttpSessionEvent arg0) {} // 替换  


    九、关于Servlet的一些问题
    1、
        针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。
      在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。
    2、
       如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。 凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。 
    3、
       当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。
       针对Servlet的线程安全问题,Sun公司是提供有解决方案的:让Servlet去实现一个SingleThreadModel接口,如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。让Servlet实现了SingleThreadModel接口,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。  
      对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象。 
        如果一个Servlet实现了SingleThreadModel接口,Servlet引擎将为每个新的请求创建一个单独的Servlet实例,这将引起大量的系统开销。SingleThreadModel在Servlet2.4中已不再提倡使用;同样如果在程序中使用同步synchronized来保护要使用的共享的数据,也会使系统的性能大大下降。这是因为被同步的代码块在同一时刻只能有一个线程执行它,使得其同时处理客户请求的吞吐量降低,而且很多客户处于阻塞状态。另外为保证主存内容和线程的工作内存中的数据的一致性,要频繁地刷新缓存,这也会大大地影响系统的性能。所以在实际的开发中也应避免或最小化 Servlet 中的同步代码;
        在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。从Java 内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。
      


  • 相关阅读:
    分析脚本搭建docker环境:python, R
    python 正则
    xargs的用法
    sed 用法
    linux系统时区问题
    docker, docker-compose安装和使用
    订单相关
    python开发接口文档
    mysql中的乐观锁,库存相关的简单实现
    mysql中的锁
  • 原文地址:https://www.cnblogs.com/kangsir/p/6653273.html
Copyright © 2011-2022 走看看