Servlet配置

1.Servlet的运行原理和流程:

 

1.http协议有多种请求方式,最常见的就是GET请求 和POST

2.GET请求是没有请求正文的,主要用户获取服务器的信息,是浏览器的默认请求方式

3.POST请求是有请求正文的,主要是用于浏览器向服务器提交数据

1.1 执行过程

1客户端发出请求http://localhost:8080/Demo1/abc

2根据web.xml文件的配置,找到<url-pattern>子元素的值“/hello”的<servlet-mapping>元素

3读取<servlet-mapping>元素的<servlet-name>子元素的值,由此确定Servlet的名字为”HelloServlet”

4找到<servlet-name>值为HelloServlet的<servlet>元素

5读取<servlet>元素的<servlet-class>子元素的值,由此确定Servlet的类名为cn.itcast.HelloServlet。

6到Tomcat安装目录/webapps/Demo1/WEB-INF/classes/cn/itcast目录下查找到HelloServlet.class文件

 

1.2 映射位置

1,同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。

2,在Servlet映射到的URL中也可以使用通配符,但是只能有两种固定的格式:一种格式是“.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。

 

3.关联关系优先级

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

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。

 

4.缺省配置

4.1 如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。

4.2 凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。

4.3在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。

4.4 当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。

 

2.Servlet的生命周期

2.1 基本概念

Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。

 

针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其它请求服务,直至web容器退出,servlet实例对象才会销毁。

 

在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。

 

2.2 Servlet启动配置

如果在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。

举例:

    <servlet>
        <servlet-name>invoker</servlet-name>
        <servlet-class>
            org.apache.catalina.servlets.InvokerServlet
        </servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>

用途:

为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。

3. ServletConfig对象

3.1 简介

在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。

当srvlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

常用的Api:

String getServletName() -- 获取当前Servlet在web.xml中配置的名字

String getInitParameter(String name) -- 获取当前Servlet指定名称的初始化参数的值

Enumeration getInitParameterNames() -- 获取当前Servlet所有初始化参数的名字组成的枚举

ServletContext getServletContext() -- 获取代表当前web应用的ServletContext对象

在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。

当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

这样做的好处是:如果将数据库信息、编码方式等配置信息放在web.xml中,如果以后数据库的用户名、密码改变了,则直接很方便地修改web.xml就行了,避免了直接修改源代码的麻烦。

 

3.2 基本使用

1.在web.xml中创建servlet的初始化配置

  <servlet>
        <servlet-name>ServletConfigTest</servlet-name>
        <servlet-class>com.vae.servlet.ServletConfigTest</servlet-class>
        <init-param>
            <param-name>name1</param-name>
            <param-value>value1</param-value>
        </init-param>
        <init-param>
            <param-name>encode</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </servlet>

2.在servlet代码中获取配置

    public void init(ServletConfig config) throws ServletException {
        String username = config.getInitParameter("name1");
        System.out.println(username);
    }
​

4.ServletContext

4.1 简介

WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。

ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。

由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。

查看ServletContext API文档,了解ServletContext对象的功能。

4.2 ServletConfig和ServletContext的区别

ServletConfig记录着单个服务员的信息,比如说年龄,性别等

ServletConfig只能获得自己的servlet信息配置信息

比如:以前获取编码参数的问题等

<servlet>
<servlet-name>hello7</servlet-name>
    <servlet-class>com.accp.servlet.Hello7</servlet-class>
   <init-param>
     <param-name>encoding</param-name>
     <param-value>text/html;charset=GB18030</param-value>
    </init-param>
   <init-param>
     <param-name>sex</param-name>
     <param-value>男</param-value>
    </init-param>
   <init-param>
     <param-name>age</param-name>
     <param-value>女</param-value>
    </init-param>
 </servlet>
 <servlet-mapping>
    <servlet-name>hello7</servlet-name>
    <url-pattern>/hello7</url-pattern>
 </servlet-mapping>

Service()方法中

//ServletConfig使用,拿到Hello7这个servlet单独的信息

//拿到所有servlet所有参数名

Enumeration configs = this.getServletConfig().getInitParameterNames();

while(configs.hasMoreElements()){

String key=(String)configs.nextElement();

//根据参数名拿参数值

String value = this.getServletConfig().getInitParameter(key);

System.out.println(key+"--"+value);

}

*但是我们发现以前每个servlet都要有编码问题的设置,那我们能不能配置一个公有的,让每一个*

*Servlet都享有*

其实可以配置一个公有信息

    <context-param>
      <param-name>encoding</param-name>
      <param-value>text/html;charset=GBK</param-value>
   </context-param>

问题是在servlet中怎么获取这些公共的信息?

ServletContext记录着整个这个门店的信息,也就是服务员工作坏境的信息。比如墙壁是刷成什么颜

色等.

ServletContext保存着整个公共的配置信息

Enumeration contexts =this.getServletContext().getInitParameterNames();

while(contexts.hasMoreElements()){

String key=(String)contexts.nextElement();

String value = this.*getServletContext()*.getInitParameter(key);

System.out.println(key+"--"+value);

}

5 .Servlet的线程安全

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

如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。

SingleThreadModel接口中没有定义任何方法,只要在Servlet类的定义中增加实现SingleThreadModel接口的声明即可。

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

实现SingleThreadModel接口并不能真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为Deprecated(过时的)。

解决方案:不要定义成员变量;

6.JSP和Servlet对比

out转译后对应JspWriter对象,其内部关联一个PringWriter对象
request转译后对应HttpServletRequest/ServletRequest对象
response转译后对应HttpServletRespons/ServletResponse对象
config转译后对应ServletConfig对象
application转译后对应ServletContext对象
session转译后对应HttpSession对象
pageContext转译后对应PageContext对象,它提供了JSP页面资源的封装,并可设置页面范围属性
exception转译后对应Throwable对象,代表由其他JSP页面抛出的异常对象,只会出现于JSP错误页面(isErrorPage设置为true的JSP页面)
page转译后对应this

 

7.使用Beanutils来封装参数(需要导入jar包):

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Map<String, String[]> parameterMap = req.getParameterMap();
        UserServiceImpl userService = new UserServiceImpl();
        User user = new User();
        try {
            System.out.println("封装之前:"+user);
            //如果需要封装时间则,需要像下面一样,注册一个转换器
            ConvertUtils.register(new Converter() {
                @Override
                public Object convert(Class clazz, Object value) {
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                    Date parse = null;
                    try {
                        if (value.equals("") || value == null) {//如果为空给个默认值
                            value = "1949-10-1";
                        }
                        parse = format.parse(value.toString());
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    return parse;
                }
            }, Date.class);
            BeanUtils.populate(user,parameterMap);
            System.out.println("封装之后:"+user);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值