学习servlet,都需要学习关于web.xml的配置,但是往往又都不关注这些内容,需要使用的时候,很多人都是直接百度,然后复制粘贴,可是真的遇到一些问题,百度又解决不了的时候,就麻烦了,所以做java web开发需要对web.xml有一定的了解才行。
为什么要配置filter
总不能说java web支持这些东西,所以我就要配置这些类吧,所以这些配置解决了什么问题。
以Filter为例,很多初学者都会遇到的一个问题:乱码,于是为了解决这个问题,我需要设置响应的编码方式,比如:
response.setCharacterEncoding("UTF-8");
单纯的使用的servlet的时候,通常这样写:
public class HelloServlet extends HttpServlet {
@Override
protected void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
.........
}
@Override
protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
@Override
public void destroy () {
System.out.println("servlet 销毁");
super.destroy();
}
@Override
public void init () throws ServletException {
System.out.println("servlet 初始化");
super.init();
}
public void init(String name, String mobile) throws ServletException{
System.out.println("name===" + name);
System.out.println("mobile===" + mobile);
System.out.println("servlet 初始化");
super.init();
}
}
一个项目李里面可能有很多的servlet,这样就需要在很多的servlet中写这个代码,为了不重复写这个代码,就需要有一个地方一次性设置,就类似过水厂的过滤器一样,如下图:
所以Filter可以说就是切面的一种,所以也就是说,Filter通常被用来解决一些通用性的设置或者校验。所以也就有了下面这种常用的web.xml配置:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.learn.filter.CharsetFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
配置很简单,但是一定要理解为什么要配置这个Filter。
另外一种常用的场景是验证请求的信息是否和要求的一致。
为什么要配置监听器Listener
我的同事很难理解监听器是个什么东西,为什么就可以监听某些内容。
监听器就像某些场所的监控室,一旦监控设置发出警告,监控室就做出某些反应,如果没有警告,监控室就一直保持监控状态,知道接到警告位置。
所以要理解监听器,就要理解三个内容。第一、监听什么;第二、谁来发出警告信息,告诉监听器;第三、监听器接受到警告信息之后要做什么。
以上三个问题可以参考这里,这篇文章中详细说明了监听器的内容,我就不重复写了。
我遇到的大多数使用监听器的场景分为两类,第一类用来监听session或者servletContext的变化,第二类是用来接收一些消息(特别是spring中的监听器);
Filter与Listener的使用与销毁
最开是学习servlet的时候,总会好奇谁Filter与Listener谁先执行谁后执行的问题,从上面的理解来看,Filter和Listener是两种不同的功能,所以两者的配置在web.xml中的顺序应该是不重要的。
这是我配置的一个web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>simpleweb</display-name>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.learn.filter.CharsetFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>sessionFilter</filter-name>
<filter-class>com.learn.filter.SessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionFilter</filter-name>
<url-pattern>*.do</url-pattern>
<url-pattern>/role/addRole</url-pattern>
</filter-mapping>
<listener>
<listener-class>com.learn.listener.SessionListener</listener-class>
</listener>
<listener>
<listener-class>com.learn.listener.RequestListener</listener-class>
</listener>
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.learn.servlet.HelloServlet</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>nyl</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
测试的结果:
SessionFilter=========初始化
CharsetFilter-------编码过滤器初始化
[2018-04-16 07:27:54,145] Artifact Gradle : com.learn : simpleweb-1.0-SNAPSHOT.war (exploded): Artifact is deployed successfully
[2018-04-16 07:27:54,146] Artifact Gradle : com.learn : simpleweb-1.0-SNAPSHOT.war (exploded): Deploy took 1,769 milliseconds
RequestListener==========创建了request
sessionlistener==========创建了session
RequestListener==========销毁了request
RequestListener==========创建了request
sessionlistener==========创建了session
RequestListener==========销毁了request
servlet 销毁
SessionFilter=========销毁
CharsetFilter-------编码过滤器销毁
可以看到执行结果:
- Filter是按照配置顺序执行的, 类似下图
- listner是根据监听的内容执行的
总结
有些配置只有理解了才知道怎么回事;写代码能自己能实现的,还是要多写一写,深入理解一点,不然就真的是码农了。