zoukankan      html  css  js  c++  java
  • JavaWeb学习之Servlet(三)----Servlet的映射匹配问题、线程安全问题(转)

    JavaWeb学习之Servlet(三)----Servlet的映射匹配问题、线程安全问题

    【声明】

    欢迎转载,但请保留文章原始出处→_→

    文章来源:http://www.cnblogs.com/smyhvae/p/4140529.html

    一、Servlet映射匹配问题:

    在第一篇文章中的第四段(MyEclipse及Tomcat的配置)已经讲到这个知识,现在再细化一下:

    由于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。

    <servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name>和<servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。

    一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name>和<url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。例如:

    复制代码
        <servlet>
            <servlet-name>MyServlet</servlet-name>
            <servlet-class>com.vae.servlet.MyServlet</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>MyServlet</servlet-name>
            <url-pattern>/servlet/MyServlet</url-pattern>
        </servlet-mapping>
    复制代码

    需要注意的是:

    1、一个<servlet>可以对应多个<serlvet-mapping>,从而一个Servlet可以有多个路径来访问

    2、url-partten中的路径也可以使用*通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。

    由于*的引入,有可能一个路径被多个urlpartten匹配,这是优先级判断条件如下:

    • 哪个越精确找哪个
    • *.后缀的格式永远匹配级最低

    【举例】

    对于如下的一些映射关系:

    • 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。

    3、可以在<serlvet>标签里配置<load-on-startup>可以用来指定启动顺序。Servlet默认是在第一次被访问的时候创建,如果配置了这个标签,就会随着Web应用的启动而创建。举例:

        <servlet>
            <servlet-name>Servlet2</servlet-name>
            <servlet-class>Servlet2</servlet-class>
            <load-on-startup>2</load-on-startup>
        </servlet>

    第4行的int值表示多个serlvet的启动顺序。 

    4、缺省Servlet:

    如果有一个Servlet的url-partten被配置为了一根正斜杠"/",这个Servlet就变成了缺省Serlvet.其他Servlet都不处理的请求,由缺省Servlet来处理.

    其实对于静态资源的访问就是由缺省Servlet来执;设置404页面、500页面等提示页面也是由缺省Servlet来执行。通常我们不会自己去配置缺省Servlet

    二、线程安全问题

    Servlet引擎采用多线程模式运行,它为并发的每个访问请求都使用一个独立的线程来进行响应。

    由于默认情况下Servlet在内存中只有一个对象,当多个浏览器并发访问Servlet时就有可能产生线程安全问题。

    面试题目注意:Servlet线程不安全,自始至终只维护一个实例。

    注:线程安全本质即:同一个资源被多个线程同时操作,可能会互相干扰。  

    解决方案:

    1、SingleThreadModel接口(标记接口,单线程模型接口):不能真的防止线程安全问题(已过时)

    Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用Servlet的service方法。对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用独立的一个Servlet实例对象

    注:此接口在API 2.4中就已经过时,虽然解决了线程安全问题,但是消耗了大量性能(不同的客户端同时访问会创建不同的Servlet实例),所以此方法建议不用,实际开发中也不用。

    2、使用同步代码块:效率降低

    下列需要考虑线程安全问题:(多个线程同时访问数据时)

    • 访问成员变量时(所以,在Servlet中定义成员变量时,需要考虑线程安全问题) 
    • 访问共享资源时

    注:Servlet中尽量不要使用成员变量。

    代码举例:访问成员变量时,要考虑线程安全问题

    复制代码
     1 public class MyServlet1 extends HttpServlet {
     2     private static final long serialVersionUID = 1L;
     3     
     4     public int count = 10;// 在Servlet中定义成员变量,需要考虑线程安全问题     
     5        
     6     public MyServlet1() {
     7         super();
     8     }
     9  
    10     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    11         doPost(request, response);
    12     }
    13  
    14     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    15     
    16         synchronized (this) {
    17             count ++;
    18         }
    19     }
    20  
    21 }
    复制代码

    最终解决方案:在Servlet中尽量少用类变量(成员变量),如果一定要用类变量则用锁来防止线程安全问题,但是要注意锁住内容应该是造成线程安全问题的核心代码,尽量的少锁主内容,减少等待时间提高servlet的响应速度。

  • 相关阅读:
    Cocoa中对日期和时间的处理 NSCalendar (一)
    iOS优秀博客收录
    八大排序(内容是转载链接)
    IOS8定位无效问题
    ios 里如何判断当前应用的定位服务是否可用
    MKMapView和MKMapViewDelegate
    根据经纬度翻译成详细位置的各种方法
    iOS 根据经纬度反查 地名
    MapKit学习笔记
    解决Collection <__NSArrayM: 0xb550c30> was mutated while being enumerated
  • 原文地址:https://www.cnblogs.com/yasepix/p/7454064.html
Copyright © 2011-2022 走看看