【Web入门系列】初探Servlet

1、Servlet开发过程及执行过程

2、Servlet路径映射

3、缺省Servlet 

4、Servlet生命周期

5、Servlet自动加载 

6、Servlet线程安全 


Servlet开发过程及执行过程

1、编写java类,继承HttpServlet 2、重写doGetdoPost方法 3、Servlet程序交给tomcat服务器运行 4、web.xml文件中进行配置

<!-- 配置一个servlet -->
<!-- servlet的配置 -->
<servlet>
    <!-- servlet的内部名称,自定义,尽量有意义 -->
    <servlet-name>FirstServlet</servlet-name>
    <!-- servlet的类全名: 包名 + 简单类名 -->
    <servlet-class>ysdrzp.servlet.FirstServlet</servlet-class>
</servlet>

<!-- servlet的映射配置 -->
<servlet-mapping>
    <!-- servlet的内部名称,一定要和上面的内部名称保持一致 -->
    <servlet-name>FirstServlet</servlet-name>
    <!-- servlet的映射路径(访问servlet的名称) -->
    <url-pattern>/first</url-pattern>
</servlet-mapping>
public class FirstServlet extends HttpServlet {

    /**
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("this is first servlet");
    }

    /**
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        doGet(request,response);
    }
    
}

访问http://localhost:8080/myweb/first是如何找到FirstServlet的?

首先tomcat服务器启动时会加载webapps中的每个web应用的web.xml配置文件。

http://指定http协议,localhost会到本地的hosts文件中查找是否存在该域名对应的IP地址127.0.0.1,根据8080端口找到tomcat服务器,

/myweb会在tomcat的webapps目录下找myweb的目录,/first 匹配资源名称。

1)在myweb的web.xml中查找是否有匹配的url-pattern的内容(/first)

2)如果找到匹配的url-pattern,则使用当前servlet-name的名称到web.xml文件中查询是否相同名称的servlet配置

3)如果找到,则取出对应的servlet配置信息中的servlet-class内容:ysdrzp.servlet.FirstServlet

4)通过反射:构造FirstServlet的对象,然后调用FirstServlet里面的方法

Servlet路径映射

精确映射

/first                  http://localhost:8080/myweb/first

/xxx/firstServlet        http://localhost:8080/myweb/xxx/firstServlet

模糊匹配

/*                       http://localhost:8080/myweb/任意路径

/test/*                  http://localhost:8080/myweb/test/任意路径

*.后缀名                 http://localhost:8080/myweb/任意路径.do   如:*.do      *.action        *.html(伪静态)

假如将上面的配置文件,映射信息调整一下由<url-pattern>/first</url-pattern>改为<url-pattern>/*</url-pattern>

在浏览器地址栏中输入http://localhost:8080/myweb/xxxx(任意的请求映射路径/xxxx)一样可以请求到FirstServlet。

注意:

1)url-pattern(请求servlet的映射路径)要么以 / 开头,要么以*开头

2)不能同时使用两种模糊匹配,例如 /test/*.do是非法路径

3)当有输入的URL有多个servlet同时被匹配的情况下:3.1 精确匹配优优先,长的最像优先被匹配 3.2 以后缀名结尾的模糊url-pattern优先级最低

缺省Servlet路径

Servlet的缺省路径(<url-pattern>/</url-pattern>)是在tomcat服务器内置的一个路径。该路径对应的是一个DefaultServlet(缺省Servlet)。这个缺省的Servlet的作用是用于解析web应用的静态资源文件。

URL输入http://localhost:8080/myweb/index.html 是如何读取文件?

1)到当前myweb应用下的web.xml文件查找是否有匹配的url-pattern。

2)如果没有匹配的url-pattern,则交给tomcat的内置的DefaultServlet处理

3)DefaultServlet程序到myweb应用的根目录下查找是存在一个名称为index.html的静态文件。

4)如果找到该文件,则读取该文件内容,返回给浏览器。

5)如果找不到该文件,则返回404错误页面。

结论: 先找动态资源,再找静态资源。

Servlet生命周期

Servlet的生命周期是由tomcat服务器控制的。

构造方法:创建servlet对象的时候调用。默认情况下,第一次访问Servlet的时候创建Servlet对象只调用1次,这也可以说明Servlet对象在tomcat是单实例的。

init方法:创建完servlet对象的时候调用,只调用1次。

service方法:每次发出请求时调用,会被调用n次。

destroy方法:销毁Servlet对象的时候调用,停止服务器或者重新部署web应用时销毁servlet对象,只调用1次。

public class FirstServlet extends HttpServlet {

public FirstServlet(){
System.out.println("FirstServlet对象构造完成");
}

@Override
public void init(ServletConfig servletConfig){
System.out.println("init()方法被调用");
}


@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("service()方法被调用");
doGet(request,response);
}

@Override
public void destroy(){
System.out.println("destroy()方法被调用");
}

/**
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("this is first servlet");
}

/**
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

doGet(request,response);
}


 

Servlet自动加载

默认情况下,第一次访问Servlet的时候创建Servlet对象。如果Servlet的构造方法或init方法中执行了比较多的逻辑代码,这样会导致用户第一次访问sevrlet的时候比较慢。

在Servlet的配置信息中,加上一个<load-on-startup>配置信息,这样就可改变servlet创建对象的时机,提前到加载web应用的时候。

<servlet>
    <servlet-name>FirstServlet</servlet-name>
    <servlet-class>ysdrzp.servlet.FirstServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>FirstServlet</servlet-name>
    <url-pattern>/first</url-pattern>
</servlet-mapping>

有参init方法和无参init方法

/**
 *  有参数的init和无参的init方法
 */
public class InitServlet extends HttpServlet {

    /**
     * 有参数的init方法
     * 该方法是Servlet的生命周期方法,一定会被tomcat服务器调用
     * 注意:如果要编写初始代码,不需要覆盖有参数的init方法
     */
    /*@Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("有参数的init方法被调用");
    }*/

    /**
     * 无参数的init方法
     * 该方法是Servlet的编写初始化代码的方法,是设计出来专门给开发者进行覆盖,然后在里面编写Servlet的初始逻辑代码的方法。
     */
    @Override
    public void init() throws ServletException {
        System.out.println("无参数的init方法被调用");
    }

}

Servlet线程安全

Servlet对象在tomcat服务器是单实例多线程的。正因为Servlet是多线程的,所以当多个Servlet的线程同时访问了Servlet的共享数据,如成员变量,可能会引发线程安全问题。

解决办法:

1)把使用到共享数据的代码块进行同步(使用synchronized关键字)

2)建议在Servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步,而且尽量缩小同步代码块的范围,避免因为同步而导致并发效率降低。

public class ThreadServlet extends HttpServlet {

    int count = 1;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        synchronized (ThreadServlet.class) {
            response.getWriter().write("你是第"+count+"位仿客。");
            /*try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            count++;
        }
    }
}

 

posted @ 2018-10-28 09:20  过向往的生活  阅读(152)  评论(0编辑  收藏  举报