ServletContext对象
之前代码存在的问题
虽然项目中可以使用Session对象在服务器端存储数据,它解决了一个用户不同请求的数据共享问题。但是在实际功能中,不同的用户也可能会用到相同的数据,如果使用Session来进行存储,会造成同一份数据在服务器中被存储多份,浪费空间。
解决方法
ServletContext对象, 在一个web项目中只创建一次,所有用户都可以获取及使用,可以实现不同用户请求的数据共享。
特点
-
ServletContext对象由Tomcat服务器在启动加载项目的时候完成创建。
-
ServletContext对象一个项目中只有一个,以任意方式获取到的都是同一个。
-
ServletContext对象中保存的数据是所有用户共享的
ServletContext的使用
1.获取ServletContext对象
//方式一:
ServletContext servletContext = this.getServletContext();
//方式二:
ServletContext servletContext1 = req.getSession().getServletContext();
//方式三:
ServletContext servletContext2 = req.getServletContext();
2.ServletContext对象存储数据(键值对的结构存储)
//往ServletContext对象中存数据,键值对的方式
servletContext.setAttribute("name", "root");
//从ServletContext对象中获取数据
String name = (String)servletContext.getAttribute("name");
3.ServletContext对象获取web.xml中配置的上下文参数
可以在web.xml中配置一些参数,可以通过ServletContext对象获取。经常出现在框架的底层
<!--配置上下文参数-->
<context-param>
<param-name>name</param-name>
<param-value>admin</param-value>
</context-param><context-param>
<param-name>age</param-name>
<param-value>18</param-value>
</context-param>
String name1 = servletContext.getInitParameter("name");
String age = servletContext.getInitParameter("age");
ServletContext对象的生命周期
当服务器启动时会创建ServletContext对象。服务器关闭后该对象销毁。
ServletContext对象的生命周期很长,仅存放所有用户共享的数据。
域对象
什么是域对象
域对象类似于之前学习的map集合,可以存放键值对的数据。不同的是域对象中数据的使用有一定的区域范围限制。
常用方法
1.request域
有效范围(作用范围)
一次请求有效
作用
流转业务数据
生命周期
创建:浏览器每次请求,服务器都会重新创建
使用:在请求的Servlet中或者请求转发后的Servlet中使用
销毁:请求响应结束后,该请求对象就会被销毁
2.Session域
有效范围(作用范围)
一次会话
作用
一般用来存储用户状态数据,如 用户的登录信息等
生命周期
创建:从第一次发出请求,会话开始
使用:一次会话内,浏览器和服务器之间发生多次请求都有效
销毁:会话结束,比如:达到最大不活动时间、手动销毁
3.Application域
有效范围
当前Web项目中都有效,可以跨请求、跨会话访问
作用
一般放一些全局的、项目本身相关所有或所有用户共享的数据,如 在线人数等,不建议存放业务数据
生命周期
创建:服务器启动
使用:服务器运行期间都有效
销毁:服务器关闭
文件上传
在Servlet3.0之前的版本中如果实现文件上传需要依赖apache的Fileupload组件,在Servlet3.0以及之后的版本中提供了Part对象处理文件上传,所以不在需要额外的添加Fileupload组件。
配置
在Servlet3.0以及之后的版本中实现文件上传时必须要在Servlet中开启多参数配置
配置方式1:
web.xml配置
<multipart-config>
<file-size-threshold></file-size-threshold>
<location></location>
<max-file-size></max-file-size>
<max-request-size></max-request-size>
</multipart-config>
配置方式2:
注解配置(@MultipartConfig配置)
常用方法
文件下载
获取文件的输入流,通过输出流响应到浏览器
监听器
为什么要使用监听器
目前我们在web项目中,可以使用三大域对象request、session、application作为数据流转的载体。而这三个域对象都不是我们创建的,也不是我们销毁的。如果想要在Servlet被创建及销毁的时候完成一系列其他的操作,怎么办?
可以给三大域对象添加监听,监听三大域对象的创建及销毁,监听到他们有动态的时候,执行对应的方法。这就是监听器。
作用
监听三大域对象的创建、销毁及数据的变更
特点
1.监听方法由tomcat根据监听结果来调用对应的方法执行
2.监听方法中的逻辑代码我们可以根据需要进行编写
监听器接口的分类
ServletRequestListenter 监听request对象的创建销毁
ServletRequestAttributeListener 监听request域中数据的变更
HttpSessionListener 监听Session对象的创建销毁
HttpSessionAttributeListener 监听Session对象中数据的变更
ServletContextListener 监听ServletContext对象的创建销毁
ServletContextAttributeListener 监听ServletContext对象中数据的变更
使用
1.自定义一个类,实现监听器接口(Listener),根据需求实现里面的方法
public class MyListener implements ServletRequestListener, ServletRequestAttributeListener,
HttpSessionListener, HttpSessionAttributeListener, ServletContextListener, ServletContextAttributeListener {
//监听ServletContext对象中数据的添加
@Override
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
}
//监听ServletContext对象中数据的删除
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
}
//监听ServletContext对象中数据的修改
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
}
//监听ServletContext对象的初始化
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
//监听ServletContext对象的销毁
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
//监听ServletRequest对象中数据的添加
@Override
public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("request对象中添加的数据!");
}
//监听ServletRequest对象中数据的删除
@Override
public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("request对象中删除了数据!");
}
//监听ServletRequest对象中数据的修改
@Override
public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("request对象中修改了数据!");
}
//监听ServletRequest对象中数据的销毁
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("request对象被销毁!");
}
//监听ServletRequest对象的初始化
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("request对象被初始化!");
}
//监听HttpSession对象中数据的添加
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
}
//监听HttpSession对象中数据的删除
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
}
//监听HttpSession对象中数据的修改
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
}
//监听HttpSession对象的创建
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
}
//监听HttpSession对象的销毁
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
}
}
2.在web.xml中配置或通过注解配置监听器
<!--
配置监听器,在服务器启动的时候就会创建监听器对象,监听器生效,一旦符合监听要求,
tomcat底层会通过反射调用监听器中的方法完成处理
-->
<listener>
<listener-class>com.bjsxt.listener.MyListener</listener-class>
</listener>
过滤器(Filter)
目前存在的安全问题
由于Tomcat服务器一直是在被动的接收请求,而且Tomcat服务器收到请求后需要调用Servlet的service方法进行处理。目前只要在浏览器中输入正确的url地址,不管此次请求是否合理,Tomcat服务器在接收到请求后就会直接调用对应的资源完成请求的处理。有些场景, 需要对请求进行相关处理, 处理完成后, 在访问请求的资源。
解决方案
在浏览器发起请求,Tomcat服务器收到后,调用资源处理请求之前添加拦截。
拦截后发现请求不合理,可以拒绝访问;如果合理,可以进行相关的设置, 然后放行,继续访问请求的资源。这个其实就是过滤器(Filter)。
作用
Tomcat收到客户端请求后, 调用资源前会对请求进行拦截, 完成相关的处理。
过滤器的使用
1.自定义一个类,实现过滤器接口(javax包下的Filter)
2.实现接口中的方法,根据业务需求来编写逻辑代码
public class CharacterFilter implements Filter {
public CharacterFilter() {
System.out.println("过滤器被创建!");
}
/**
* 处理化方法,执行一些初始化的操作,一般不用
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器被初始化!");
}
/**
* 过滤器的核心方法,过滤器拦截到请求后,就是在该方法中对请求进行判断,看是否让其继续访问我们的资源
* @param servletRequest 封装的请求信息
* @param servletResponse 封装的响应对象
* @param filterChain 过滤器链,用来放行的
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("开始对请求进行判断处理!");
filterChain.doFilter(servletRequest, servletResponse);//放行
}
/**
* 销毁方法,用来做一些释放资源的操作,一般不用
*/
@Override
public void destroy() {
System.out.println("过滤器被销毁!");
}
}
3.在web.xml中配置过滤器或通过注解配置
<!--配置过滤器-->
<filter>
<filter-name>CharacterFilter</filter-name>
<!--
配置过滤器所在的全路径,由Tomcat在启动的时候,通过放射创建该过滤器对象
-->
<filter-class>com.bjsxt.filter.CharacterFilter</filter-class>
</filter><!--配置过滤器的拦截路径,也就是对哪些请求进行拦截-->
<filter-mapping>
<filter-name>CharacterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器链的流程