Servlet的细节问题

本文详细介绍了Servlet的配置与映射方式,包括如何通过web.xml文件进行Servlet的注册及映射路径设置,并探讨了不同映射规则的优先级与执行顺序。此外,还讲解了Servlet的单例特性及线程安全问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

① 一个已经注册的Servlet可以被多次映射即:

 <servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
   	<!-- servlet的注册名 -->
    <servlet-name>MyServlet1</servlet-name>
    <!-- servlet类的全路径(包名+类名) -->
    <servlet-class>com.hsp.servlet.MyServlet1</servlet-class>
  </servlet>
<!-- 对一个已经注册的servlet的映射 -->
  <servlet-mapping>
  <!-- servelt的注册名 -->
    <servlet-name>MyServlet1</servlet-name>
  <!-- servlet的访问路径 -->
    <url-pattern>/MyServlet1</url-pattern>
  </servlet-mapping>
  
  <servlet-mapping>
  <servlet-name>MyServlet1</servlet-name>
  <url-pattern>/hsp</url-pattern>
  </servlet-mapping>

① 当映射一个servlet时候,可以多层 比如

<url-pattern>/servlet/index.html</url-pattern> ok

从这里还可以看出,后缀名是 html不一定就是html,可能是假象.


① 使用通配符在servlet映射到URL

有两种格式:

第一种格式  *.扩展名  比如*.do  *.ss

第二种格式   /开头 同时以/*结尾  比如  /*   /news/*

通配符练习题:

l Servlet1 映射到 /abc/*

l Servlet2 映射到 /*

l Servlet3 映射到 /abc

l 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

 

在匹配的时候,要参考的标准:

(1) 看谁的匹配度高,谁就被选择

(2) *.do 的优先级最低


① Servlet单例问题

Servlet被第一次访问后,就被加载到内存,以后该实例对各个请求服务.即在使用中是单例.

因为 Servlet是单例,因此会出现线程安全问题:比如:

售票系统. 如果不加同步机制,则会出现问题:

这里我给大家一个原则:

(1) 如果一个变量需要多个用户共享,则应当在访问该变量的时候,加同步机制

synchronized (对象){

//同步代码

}

2)如果一个变量不需要共享,则直接在doGet()或者doPost()定义.这样不会存在线程安全问题

① servlet 中的 <load-on-startup>配置

需求: 当我们的网站启动的时候,可能会要求初始化一些数据,(比如创建临时表),在比如:

我们的网站有一些要求定时完成的任务[ 定时写日志,定时备份数据.. 定时发送邮件..]

解决方法: 可以通过 <load-on-startup>配合 线程知识搞定.

 

先说明<load-on-startup>: 通过配置<load-on-startup> 我们可以指定某个Servlet自动创建.

 

我们来模拟一个定时发送电子邮件的功能:

实现思路:

sendEmailTable

id content sendtime

1 “hello” 2011-11-11 20:11

2 “hello2” 2012-11-11 10:00

看看如何线程去完成任务:
这里的代码请参考项目:
SendMailThread.java
package com.hsp.model;
public class SendEmailThread extends Thread{
	@Override
	public void run() {
		int i=0;
		try {
			while(true){
				//每休眠一分钟,就去扫表sendmail, 看看那份信件应当被发出
				Thread.sleep(10*1000);
				System.out.println("发出 第"+(++i)+"邮件");//javamail
			}
		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}
	}
}
MyInitServlet1.java
public void init() throws ServletException {
		// Put your code here
		System.out.println("MyInitServlet1 的init被调用..");
		//完成一些初始化任务
		System.out.println("创建数据库,表,读取参数");
		//创建一个线程
		SendEmailThread sendEmailThread=new SendEmailThread();
		sendEmailThread.start();
	}
说明:
<!-- 1表示该servlet被 init的顺序 -->
<load-on-startup>1</load-on-startup>

  •  ServletConfig对象

该对象主要用于 读取 servlet的配置信息.

案例:
<servlet>
    <servlet-name>ServletConfigTest</servlet-name>
    <servlet-class>com.hsp.servlet.ServletConfigTest</servlet-class>
    <!-- 这里可以给servlet配置信息,这里配置的信息,只能被该servlet 读取 -->
    <init-param>
    <param-name>encoding</param-name>
    <param-value>utf-8</param-value>
    </init-param>
  </servlet>

如何使用

String encoding=this.getServletConfig().getInitParameter("encoding");

补充说明:这种配置参数的方式,只能被某个Servlet独立使用.如希望让所有的Servlet都去读取某个参数,这样配置:

<!-- 如果这里配置参数,可被所有servlet读取 -->

 <context-param>

 <param-name></param-name>

 <param-value></param-value>

 </context-param>

如果要把所有的参数都读取,则使用 如下方法

Enumeration<String> names=this.getServletConfig().getInitParameterNames();
		
		while(names.hasMoreElements()){
			String name=names.nextElement();
			System.out.println(name);
			System.out.println(this.getServletConfig().getInitParameter(name));
		}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值