前言:打脸了,前脚刚说过要跟Servlet正式告别。结果最近的面试被问到了同一个Servlet可不可以被映射到多个URL上,也就是如何用一个Servlet实现多个功能。


前置知识:

Servlet容器如何处理请求资源路径?

  1、这个地址  http://localhost:8080/ttms1.01/indexUI.do   什么是请求资源路径? 

    在地址栏中输入的请求地址中,端口号之后的部分都是请求资源路径。

    紧跟端口号的是部署到Web服务器上的应用名(appName)

    紧跟应用名的则是具体的应用内的组件路径。

  2、Web服务器对请求地址的处理过程:

    浏览器依据地址中的IP和端口号与Web服务器建立连接,服务器会获取到请求资源路径信息。根据端口号后面的应用名找到服务器上对应的应用。默认情况下容器会认为应用名后面的是一个Servlet,所以回到web.xml文件中所有是否有与该值匹配的<url-pattern>,找到匹配的值之后再按照<servlet-name>完成对应关系的查找,进而找到要执行的Servlet。如果没有找到匹配的资源服务器就会返回404错误。匹配Servlet的规则

      精确匹配 /

      通配符匹配 *

      后缀匹配 *.


1、Servlet能不能一对多映射?

问题:web.xml配置中一个servlet能不能映射多个url-pattern?
(1)同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。
(2)在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是“*.扩展名”,另一种格式是以正斜杠(/)开头并以“/*”结尾。

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

<servlet-mapping>
<servlet-name>AnyName</servlet-name>
<url-pattern>/action/*</url-pattern>
</servlet-mapping>

下面例子显示了针对同一Servlet实例的两个不同 pattern:

一个Servlet 可以接受任何数量url-patterns的requests 。

<servlet-mapping>
<servlet-name>getStatus</servlet-name>
<url-pattern>/status/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>getStatus</servlet-name>
<url-pattern>/briefStatus/*</url-pattern>
</servlet-mapping>

不同的pattern可以映射到同一个Servlet,但同一个pattern不能映射到不同的Servlet。

2、为什么要使用一个Servlet来处理多个请求?

  当浏览器发送了一次请求到服务器时,servlet容器会根据请求的url-pattern找到对应的Servlet类,执行对应的doPost或doGet方法,再将响应信息返回给浏览器,这种情况下,一个具体的Servlet类只能处理对应的web.xml中配置的url-pattern请求,一个Servlet类,一对配置信息。如果业务扩展,需要三个Servlet来处理请求,就需要再加上两个具体的Servlet类,两对配置信息,如果继续向上扩展,是不是会认为如此写法的效率非常低下?并且会浪费更多的资源?

  为了避免重复的操作(多次编写配置文件,多次新建具体的Servlet类)影响效率,就衍生出一套简单的操作来提高效率,一次配置,多次使用;一个Servlet具体类,处理多个请求。

3、如何使用一个Servlet来处理多个请求(将多个servlet合并)?

   a、根据请求的地址,截取其中的具体方法名,然后使用if-else判断匹配,再执行具体的方法。

  b、根据截取出来的方法名,使用反射机制,来执行具体的方法。

  第一种方案很笨拙,需要不断的使用if-else来判断;第二种方法相对来讲,灵活的处理了原先需要使用if-else的判断逻辑,由类根据方法名自主去执行。

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐