一.Servlet原理
Servlet是由web服务器
调用的,web服务器在接收到浏览器请求之后,会进行以下操作:
浏览器向web容器发送Http请求
。web容器在收到请求之后,如果这个请求时第一次访问的话,web容器会生成一个servlet(只有首次访问才会产生)。web容器会产生一个请求(request)
和一个响应(response)
(请求有请求头
和请求体
,响应也有响应头
和响应体
)。Servlet接口中的service方法便是用来处理请求(Request)
,并且将请求处理的结果封装到响应(Response)
中。之后将响应放到web容器中。
大致流程如下图所示:
我们可以在此做一个总结:
1.请求(request)
中封装的是浏览器向web容器发送来的请求数据。响应(response)
是用来封装Servlet.service()
方法处理请求之后的所产生的结果数据。
2.Servlet.service()
方法的作用其实就是获取request中的数据,根据request中的数据做出处理,并且将处理之后的结果封装到response中,之后将response返回给web容器,web容器读取到响应的信息,之后web容器将数据响应给浏览器。
3.Servlet.service()方法是由我们(web开发人员)
来进行重写的。
二.Mapping问题(< servlet-mapping >)
在web.xml中我们添加了一个<servlet-mapping>
标签:
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
其中的<url-pattern>/hello</url-pattern>
是对对应servlet的映射路径进行设置。
servlet指定映射规则:
1.一个servlet可以指定一个映射路径
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
2.一个servlet可以指定多个映射路径
<!-- 我们可以将hello这个servlet指定hello1 hello2...等多个映射路径-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
3.一个servlet可以指定通用映射路径
<!-- 比如我们可以使用通配符'*',来让hello这个servlet指定在hello路径下的任意请求-->
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello/*</url-pattern>
<!-- '*'为通配符,可以匹配所有路径-->
</servlet-mapping>
值得注意的是,当我们在将一个servlet的映射设置为'/*'
,即:
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
此时当我们访问项目路径时,我们访问到的是配置的servlet,并不会访问到web项目中的index.jsp
。可以理解为,我们设置映射路径为/*
的servlet将index.jsp
的映射路径给顶替了。也可以理解为我们配置的servlet优先级高于默认的index。
4.一个servlet可以指定有前缀或者后缀的映射路径
映射路径后缀设置:
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>*.hhh</url-pattern>
</servlet-mapping>
注意:后缀前面不可添加路径。可以理解为**添加了后缀映射之后,只要是以此后缀结尾的请求路径都会映射到配置这个Servlet。**比如我们在配置了*.hhh
之后,我们访问的路径为locahost:8080/servlet01/jskaldjaskld/123.hhh
,那么此路径依然映射的是我们配置的servlet。
<servlet-mapping>
优先级问题
指定了固定的映射路径的优先级最高,如果找不到对应的固定优先级配置路径才会走带有通配符的映射路径。
应用案例:改变404页面的显示
我们可以根据<servlet-mapping>
优先级规则,来设置servlet的映射,使得我们在访问路径错误找不到页面时使路径映射到我们自己编写的servlet。
操作步骤:
- 编写一个ErrorServlet类,此类便是URL路径错误时映射的Servlet
package com.kuang;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ErrorServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置resp响应的输出格式以及字符编码
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
// 设置resp的输出内容
resp.getWriter().print("<h1>自己编写的404页面</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
- 给ErrorServlet类编写Servlet映射路径
<servlet>
<servlet-name>ErrorPage</servlet-name>
<servlet-class>com.kuang.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ErrorPage</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
我们可以看到,此案例中我们就是运用的<servlet-mapping>
的优先级,在我们输入一个无法匹配到的路径时,我们就使用’/*'映射到所有路径来对无法映射的路径进行一个“拦截”。
效果:
当我们输入错误的路径时:
当我们访问HelloServlet时:
我们可以看到,有映射的路径并没有收到影响。
本篇结束。