当前位置: 代码迷 >> Java相关 >> java学习笔记—Servlet配置跟线程安全性(12)
  详细解决方案

java学习笔记—Servlet配置跟线程安全性(12)

热度:10   发布时间:2016-04-22 20:34:30.0
java学习笔记—Servlet配置和线程安全性(12)

问题1:

用户是否可以即使用get又使用post发送请求?

对于开发人员而言不知道用户到底要使用什么请求方式,因此需要将doGet或doPost都要重写。但是响应的数据时一样,因此可以在实现一个方法的基础上在另一个方法中直接调用即可。

public class Template extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {        // 处理用户的请求    }    public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {        doGet(request, response);    }}

问题2:如何修改IDE中创建servlet和jsp等资源的模板?

查找IDE安装的目录的Genuitec\Common\plugins中的以下jar包com.genuitec.eclipse.wizards_7.0.0.zmyeclipse70020081206.jarServlet.java修改文件即可。

Servlet配置

编写好的Servlet如果需要进行使用浏览器访问,那么需要对其进行基本的配置。web.xml

1  一对一配置(基本配置)

<servlet>        ? 配置一个servlet     <servlet-name>helloservlet</servlet-name> ? 指定servlet的名字(任意)     ? 指定servlet具体的类的全限定名(包名.类名)     <servlet-class>cn.itcast.servlets.HelloServlet</servlet-class></servlet><servlet-mapping>        ? 映射一个servlet     <servlet-name>helloservlet</servlet-name> ? 需要映射的servlet名     <url-pattern>/helloservlet</url-pattern>     ? 浏览器需要访问的路径</servlet-mapping>

2  一对多配置(基本配置)

  <servlet-mapping>     <servlet-name>Mapping1</servlet-name>    <url-pattern>/map1</url-pattern>    <url-pattern>/map2</url-pattern>  </servlet-mapping>

3  使用*进行映射

DTD * 0到多个  Xpath //* 表示所有元素

在servlet中*匹配的任意个字符

 <servlet-mapping>    <servlet-name>Mapping2</servlet-name>    <url-pattern>/*</url-pattern>  </servlet-mapping>

原则”如果多个servlet都匹配用户的请求资源,那么tomcat服务器会找最像的那个进行响应!”

4  *.do映射

<servlet-mapping>    <servlet-name>Mapping2</servlet-name>    <url-pattern>*.do</url-pattern></servlet-mapping>

如果要映射为*.do那么就不要以/开头,而且*.do的优先级最低。

思考:如果以后上网的时候看到用户的请求资源是.html结尾,那么是否就是静态页面?

因为servlet可以映射为任何的路径,那么因此你看到的访问路径有可能是假的。

5 默认映射

对于用户而言很有可能访问一些网站中不存在的资源,那么如果直接使用服务器中默认的servlet进行处理,那么错误对于用户是不友好的,所有任何一个开发好的网站,应该都具备处理用户错误请求的默认的servlet。

<servlet-mapping>    <servlet-name>MyDefault</servlet-name>    <url-pattern>/</url-pattern></servlet-mapping>

6 自启动servlet

一个网站在别人访问之前应该提前将网站的数据建立好。

<servlet>    <servlet-name>AutoStart</servlet-name>    <servlet-class>cn.itcast.servlets.AutoStart</servlet-class>    <load-on-startup>1</load-on-startup>  </servlet>

load-on-startup的值必须是一个正整数,值越小那么越先启动。通常在实际的开发中我们将数据库的创建、 表的创建以及数据的添加写在一个自启动的servlet中,进而提高用户的体验。

Servlet线程安全性

问题:使用以下的代码演示servlet的线程安全问题?

public class MultiThreadQuestion extends HttpServlet {    public int count = 0;    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        // 1. 验证服务器是以线程的方式处理用户请求的        try {            this.count++;            Thread.sleep(5 * 1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        response.getOutputStream().write(("线程名:"+Thread.currentThread().getName()+"count="+this.count).getBytes());    }}

同时访问以上的代码发现三次同时出现3,这就是线程的并发访问的问题。

解决方案就是:同步

给访问共享资源的代码加锁。

public class MultiThreadQuestion extends HttpServlet {    public int count = 0;    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        // 1. 验证服务器是以线程的方式处理用户请求的        synchronized (this) {            try {                this.count++;                Thread.sleep(5 * 1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            response.getOutputStream().write(("线程名:"+Thread.currentThread().getName()+"count="+this.count).getBytes());        }    }}

总结:

  1. 如果直接使用同步关键字,那么会导致servlet的运行效率严重的降低。
  2. 尽量避免使用servlet的成员变量。
  3. 如果避免不了那么我们就需要使用线程安全的成员变量。

ArrayList    Vector    HashSet  

如果需要不是线程安全的集合可以使用Collections进行线程安全的转换

  1. ServletContext、HttpSession需要使用的时候一定要使用同步。
  2. 在servlet中最好使用局部变量。
  相关解决方案