Servlet注解配置与线程安全问题

1、Servlet的 XML文件配置的一点细节

     1)一个Servlet程序,可以配置多个<url-pattern>元素,表示一个Servlet有多个资源名称,必须使用 / 打头

        

     2)一个Servlet程序,可以配置多个<servlet-mapping>元素

     

     3)Servlet的映射支持通配符映射*:表示任意字符)

方式一: /* 或 /aa/*  表示请求的资源必须以 / 或者 /aa/ 打头下的任何字符才可访问该Servlet

方式二: *.扩展名  表示请求的资源必须以 *.扩展名 结尾的任何字符才可访问,比如:*.do

     4)元素的文本内容不能是 default

      因为,在Tomcat中存在一个叫做 default的Servlet(/conf/web.xml中),专门用来处理请求静态资源。

2、Web容器启动初始化Servlet

扫描二维码关注公众号,回复: 8565820 查看本文章

      <load-on-startup>元素设置Web容器启动时自动装载某些Servlet。

	<servlet>
		<servlet-name>LifeServlet</servlet-name>
		<servlet-class>cn.jq.demo.LifeServlet</servlet-class>
        <!-- 配置该servelt的初始化参数(键值对) -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>username</param-name>
            <param-value>admin</param-value>
        </init-param>
        <!--若为大于0的正整数(默认值为0)时表示web应用启动时,自动装载对应的Servlet,值越小越优先执行,只执行一次随web应用启动时。
            若为负数,则会在第一次请求时被执行对象的Servler(和默认值一样)。 -->
        <load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>LifeServlet</servlet-name>
		<url-pattern>/life</url-pattern>
	</servlet-mapping>

一、基于注解的方式配置Servlet

      注解配置:Servlet3.0新特性,对应JavaEE6的规范,所以Tomcat必须是Tomcat7+。

      我的环境是:Servlet3.1,JDK8,Tomcat8.5

在web.xml文件中进行如下配置

     设置 metadata-complete="false":表示不忽略Servlet上面的注释(默认值就为false,也可删掉不写

     设置 metadata-complete="true":表示忽略Servlet上面的注释,注释不会生效!

    

1、@WebServlet 注解配置

     作用:用于将一个类声明为 Servlet

     描述:该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为 Servlet。

     属性详解:该注解具有下表给出的一些常用属性(以下所有属性均为可选属性,但是 vlaue 或者 urlPatterns 通常是必需的,且二者不能共存,如果同时指定,通常是忽略 value 的取值)

     

       @WebInitParam注解:配置Servlet初始化时使用的参数

          

自定义Servlet类注解配置:

// value或urlPatterns指定url
// 注意:必须以  / 打头
@WebServlet(
    value= {"/life","/life2"},
    initParams = {
        @WebInitParam(name="encoding",value="UTF-8"),
        @WebInitParam(name="username",value="admin")      
    },
    loadOnStartup = 1 
)
public class LifeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    
    @Override
    public void init() throws ServletException {
       System.out.println("init");
    }
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPut(req, resp);
    }
    
    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String username = req.getParameter("username") ;
        String password = req.getParameter("password") ; 
        Enumeration<String> params = getInitParameterNames();
        while (params.hasMoreElements()) {
            String name = (String) params.nextElement();
            String value = getInitParameter(name);
            System.out.println(name + ";" + value);
        }
        
        resp.setContentType("text/html;charset=utf-8");   
        PrintWriter out = resp.getWriter();
        out.write("<html><head><title>this is tilte</title></head><body>");
        out.write("LifeServlet:" + username + "--" + password);
        out.write("</body></html>");
    } 
}

 

总结:

1、XML文件与注解的区别,如何选择?

     XML文件:优点:XML配置直观清晰,与Java代码相分离,维护性高。缺点:XML配置导致配置文件臃肿,开发效率较低

     注解配置:优点:开发效率较高,不臃肿,也方便快速定位。缺点:和Java代码耦合在一起,维护性较低

一般在开发中,注解使用非常多,而XML文件用于通用配置,两者结合使用。

 

二、Servlet线程安全问题

      当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。

Servlet线程不安全问题的根本原因:

      Servlet是单例的,是线程不安全的,而造成的根本原因主要是由于实例变量使用不当而引起的

解决方案:

1、实现了SingleThreadModel接口(已过时,不推荐)

      如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。但是本质上面并没有解决线程安全问题,因为其采用的方式是根据并发请求去产生多个Servlet实例对象,并发的每个线程分别调用一个独立的Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。而不是多个线程调用多个Servlet实例。

2、利用线程的知识加锁(慎用,尽量不使用)

      利用synchronized同步代码。将我们有并发问题的代码转化为同步代码,但是这样做的一个坏处就是,如果遇到高并发的情况下,我们的用户可能会因为同步代码的问题而造成等待的时间比较久这样的问题,所以,要慎用。

3、在Servlet中避免使用成员变量,使用局部变量(推荐)

      从根本原因入手,避免使用成员变量,使用局部变量,因为,每一个请求都会调用service方法,局部变量每次都会开辟一个新的内存空间。

       

Struts2是线程安全的,因为每一个线程(请求)访问都是一个新的Action对象。

Spring MVC是线程不安全的,都是单例的与Servlet类似。

 

参考文章:Servlet线程安全问题

    

    站在前辈的肩膀上,每天进步一点点

ends~

发布了248 篇原创文章 · 获赞 59 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_42402854/article/details/101426147