Servlet、Filter

 

加载顺序是:context-param -> listener -> filter -> servlet ,而同个类型之间的实际程序调用的时候的顺序是根据对应的 mapping 的顺序进行调用的。

 

 

 

下面从几个方面阐述一下题目中四个概念的区别与联系:
1、概念
2、生命周期
3、职责
4、执行过程

一、概念:
1、servlet:servlet是一种运行服务器端的Java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层。
2、filter:filter是一个可以复用的代码片段,可以用来转换HTTP请求、响应和头信息。
Filter不像Servlet,它不能产生一个请求或者响应,它只是修改对某一资源的请求,或者修改从某一的响应。
3、listener:监听器,从字面上可以看出listener主要用来监听只用。通过listener可以监听web服务器中某一个执行动作,并根据其要求作出相应的响应。通俗的语言说就是在application,session,request三个对象创建消亡或者往其中添加修改删除属性时自动执行代码的功能组件。
4、interceptor:是在面向切面编程的,就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法,比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
5、servlet、filter、listener是配置到web.xml中,interceptor不配置到web.xml中,struts的拦截器配置到struts.xml中。spring的拦截器配置到spring.xml中。
二、生命周期:
1、servlet:servlet的生命周期始于它被装入web服务器的内存时,并在web服务器终止或重新装入servlet时结束。servlet一旦被装入web服务器,一般不会从web服务器内存中删除,直至web服务器关闭或重新结束。
(1)、装入:启动服务器时加载Servlet的实例;
(2)、初始化:web服务器启动时或web服务器接收到请求时,或者两者之间的某个时刻启动。初始化工作有init()方法负责执行完成;
(3)、调用:从第一次到以后的多次访问,都是只调用doGet()或doPost()方法;
(4)、销毁:停止服务器时调用destroy()方法,销毁实例。

2、filter:(一定要实现javax.servlet包的Filter接口的三个方法init()、doFilter()、destroy(),空实现也行)
(1)、启动服务器时加载过滤器的实例,并调用init()方法来初始化实例;
(2)、每一次请求时都只调用方法doFilter()进行处理;
(3)、停止服务器时调用destroy()方法,销毁实例。
3、listener:类似于servlet和filter
web.xml 的加载顺序是:context- param -> listener -> filter -> servlet
4、interceptor:以struts的拦截器为例,加载了struts.xml以后,初始化相应拦截器。当action请求来时调用intercept方法,服务器停止销毁interceptor。

三、职责
1、servlet:
创建并返回一个包含基于客户请求性质的动态内容的完整的html页面;
创建可嵌入到现有的html页面中的一部分html页面(html片段);
读取客户端发来的隐藏数据;
读取客户端发来的显示数据;
与其他服务器资源(包括数据库和java的应用程序)进行通信;
通过状态代码和响应头向客户端发送隐藏数据。
2、filter:
filter能够在一个请求到达servlet之前预处理用户请求,也可以在离开servlet时处理http响应:
在执行servlet之前,首先执行filter程序,并为之做一些预处理工作;
根据程序需要修改请求和响应;
在servlet被调用之后截获servlet的执行

3、listener:职责如概念。
servlet2.4规范中提供了8个listener接口,可以将其分为三类,分别如下:
第一类:与servletContext有关的listner接口。包括:ServletContextListener、ServletContextAttributeListener
第二类:与HttpSession有关的Listner接口。包括:HttpSessionListner、HttpSessionAttributeListener、HttpSessionBindingListener、 HttpSessionActivationListener;
第三类:与ServletRequest有关的Listener接口,包括:ServletRequestListner、ServletRequestAttributeListener

4、interceptor:与过滤器十分相似,通过层层拦截,处理用户的请求和响应。

备注:web.xml 的加载顺序是:context-param -> listener -> filter -> servlet 。了解了这几个概念的区别以后,不难理论这个加载顺序了。

四、几个区别:
1,servlet 流程是短的,url传来之后,就对其进行处理,之后返回或转向到某一自己指定的页面。它主要用来在 业务处理之前进行控制.
2,filter 流程是线性的, url传来之后,检查之后,可保持原来的流程继续向下执行,被下一个filter, servlet接收等,而servlet 处理之后,不会继续向下传递。
filter功能可用来保持流程继续按照原来的方式进行下去,或者主导流程,而servlet的功能主要用来主导流程。
filter可用来进行字符编码的过滤,检测用户是否登陆的过滤,禁止页面缓存等
3, servlet,filter都是针对url之类的,而listener是针对对象的操作的,如session的创建,session.setAttribute的发生,在这样的事件发生时做一些事情。

 

service返回JSON

/**
 * 在Servlet返回JSON数据
 */
@WebServlet("/json.do")
public class JsonServlet extends HttpServlet {
  private static final long serialVersionUID = 7500835936131982864L; 

  /**
   * 返回json格式数据
   */
  protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Map<String, Object> data = new HashMap<String, Object>(); 

    data.put("date", new Date());
    data.put("email", "accountwcx@qq.com");
    data.put("age", 30);
    data.put("name", "csdn");
    data.put("array", new int[]{1,2,3,4}); 

    ResponseJsonUtils.json(response, data);
  }
} 

 

/**
 * Servlet返回JSONP格式数据
 */
@WebServlet("/jsonp.do")
public class JsonpServlet extends HttpServlet {
  private static final long serialVersionUID = -8343408864035108293L;
  
  /**
   * 请求会发送callback参数作为回调函数,如果没有发送callback参数则使用默认回调函数
   */
  protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //客户端发送的回调函数
    String callback = request.getParameter("callback");
      
    Map<String, Object> data = new HashMap<String, Object>();
      
    data.put("date", new Date());
    data.put("email", "accountwcx@qq.com");
    data.put("age", 30);
    data.put("name", "csdn");
    data.put("array", new int[]{1,2,3,4});
      
    if(callback == null || callback.length() == 0){
      //如果客户端没有发送回调函数,则使用默认的回调函数
      ResponseJsonUtils.jsonp(response, data);
    }else{
      //使用客户端的回调函数
      ResponseJsonUtils.jsonp(response, callback, data);
    }
  }
} 

 

import java.io.IOException;
import java.io.PrintWriter; 

import javax.servlet.http.HttpServletResponse; 

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature; 

/**
 *
 * Web服务端返回JSON工具类
 * 工具类依赖FastJSON
 * 工具类支持返回JSON和JSONP格式数据
 * @author accountwcx@qq.com
 *
 */
public class ResponseJsonUtils {
  /**
   * 默认字符编码
   */
  private static String encoding = "UTF-8"; 

  /**
   * JSONP默认的回调函数
   */
  private static String callback = "callback"; 

  /**
   * FastJSON的序列化设置
   */
  private static SerializerFeature[] features = new SerializerFeature[]{
    //输出Map中为Null的值
    SerializerFeature.WriteMapNullValue, 

    //如果Boolean对象为Null,则输出为false
    SerializerFeature.WriteNullBooleanAsFalse, 

    //如果List为Null,则输出为[]
    SerializerFeature.WriteNullListAsEmpty, 

    //如果Number为Null,则输出为0
    SerializerFeature.WriteNullNumberAsZero, 

    //输出Null字符串
    SerializerFeature.WriteNullStringAsEmpty, 

    //格式化输出日期
    SerializerFeature.WriteDateUseDateFormat
  }; 

  /**
   * 把Java对象JSON序列化
   * @param obj 需要JSON序列化的Java对象
   * @return JSON字符串
   */
  private static String toJSONString(Object obj){
    return JSON.toJSONString(obj, features);
  } 

  /**
   * 返回JSON格式数据
   * @param response
   * @param data 待返回的Java对象
   * @param encoding 返回JSON字符串的编码格式
   */
  public static void json(HttpServletResponse response, Object data, String encoding){
    //设置编码格式
    response.setContentType("text/plain;charset=" + encoding);
    response.setCharacterEncoding(encoding); 

    PrintWriter out = null;
    try{
      out = response.getWriter();
      out.write(toJSONString(data));
      out.flush();
    }catch(IOException e){
      e.printStackTrace();
    }
  } 

  /**
   * 返回JSON格式数据,使用默认编码
   * @param response
   * @param data 待返回的Java对象
   */
  public static void json(HttpServletResponse response, Object data){
    json(response, data, encoding);
  } 

  /**
   * 返回JSONP数据,使用默认编码和默认回调函数
   * @param response
   * @param data JSONP数据
   */
  public static void jsonp(HttpServletResponse response, Object data){
    jsonp(response, callback, data, encoding);
  } 

  /**
   * 返回JSONP数据,使用默认编码
   * @param response
   * @param callback JSONP回调函数名称
   * @param data JSONP数据
   */
  public static void jsonp(HttpServletResponse response, String callback, Object data){
    jsonp(response, callback, data, encoding);
  } 

  /**
   * 返回JSONP数据
   * @param response
   * @param callback JSONP回调函数名称
   * @param data JSONP数据
   * @param encoding JSONP数据编码
   */
  public static void jsonp(HttpServletResponse response, String callback, Object data, String encoding){
    StringBuffer sb = new StringBuffer(callback);
    sb.append("(");
    sb.append(toJSONString(data));
    sb.append(");"); 

    // 设置编码格式
    response.setContentType("text/plain;charset=" + encoding);
    response.setCharacterEncoding(encoding); 

    PrintWriter out = null;
    try {
      out = response.getWriter();
      out.write(sb.toString());
      out.flush();
    } catch (IOException e) {
      e.printStackTrace();
    }
  } 

  public static String getEncoding() {
    return encoding;
  } 

  public static void setEncoding(String encoding) {
    ResponseJsonUtils.encoding = encoding;
  } 

  public static String getCallback() {
    return callback;
  } 

  public static void setCallback(String callback) {
    ResponseJsonUtils.callback = callback;
  }
}

 

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        try {
      ...//业务逻辑 

            filterChain.doFilter(httpServletRequest, httpServletResponse);
        } catch (BadCredentialsException e) {
            httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
            httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            ResultData<Object> result = new ResultData<>(GlobalCode.INVALID_IDENTITY);
            try (PrintWriter out = httpServletResponse.getWriter()) {
                out.write(JSON.toJSONString(result));
                out.flush();
            }
        }

 

 

 

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; 

/**
 * Spring MVC返回JSON和JSONP数据
 */
@Controller
@RequestMapping("/json")
public class JsonController { 

  /**
   * 返回JSON数据
   * @param request
   * @param response
   */
  @RequestMapping("/json.do")
  public void json(HttpServletRequest request, HttpServletResponse response){
    Map<String, Object> data = new HashMap<String, Object>(); 

    data.put("date", new Date());
    data.put("email", "accountwcx@qq.com");
    data.put("age", 30);
    data.put("name", "csdn");
    data.put("array", new int[]{1,2,3,4}); 

    ResponseJsonUtils.json(response, data);
  } 

  /**
   * 返回JSONP数据
   * @param callback JSONP的回调函数
   * @param request
   * @param response
   */
  @RequestMapping("/jsonp.do")
  public void json(String callback, HttpServletRequest request, HttpServletResponse response){
    Map<String, Object> data = new HashMap<String, Object>(); 

    data.put("date", new Date());
    data.put("email", "accountwcx@qq.com");
    data.put("age", 30);
    data.put("name", "csdn");
    data.put("array", new int[]{1,2,3,4}); 

    if(callback == null || callback.length() == 0){
      //如果客户端没有发送回调函数,则使用默认的回调函数
      ResponseJsonUtils.jsonp(response, data);
    }else{
      //使用客户端的回调函数
      ResponseJsonUtils.jsonp(response, callback, data);
    }
  }
} 

 

 

import java.io.IOException;  

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;  

import com.ajun.exception.BsException;  

/**
 * 业务异常过滤器
 * @author ajun
 * @http://blog.csdn.net/ajun_studio
 */
public class ExceptionFiler implements Filter {  

    private String errorPage;//跳转的错误信息页面  

    public void destroy() {  

    }  

    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {  

         HttpServletResponse response = (HttpServletResponse) res;
         HttpServletRequest request = (HttpServletRequest) req;
         //捕获你抛出的业务异常
         try {
            chain.doFilter(req, res);
        } catch (RuntimeException e) {
            if(e instanceof BsException){//如果是你定义的业务异常
                request.setAttribute("BsException", e);//存储业务异常信息类
                request.getRequestDispatcher(errorPage).forward(request, response);//跳转到信息提示页面!!
            }
            e.printStackTrace();
        }
    }
       //初始化读取你配置的提示页面路径
    public void init(FilterConfig config) throws ServletException {
        //读取错误信息提示页面路径
        errorPage = config.getInitParameter("errorPage");
        if(null==errorPage || "".equals(errorPage)){
            throw new RuntimeException("没有配置错误信息跳转页面,请再web.xml中进行配置\n<init-param>\n<param-name>errorPage</param-name>\n<param-value>/error.jsp</param-value>\n </init-param>\n路径可以是你自己设定的任何有效路径页面!!");
            //System.out.println("没有配置错误信息跳转页面");
        }
    }  

}  

Filter在web.xml中的配置如下:

<filter>
    <filter-name>ExceptionFilter</filter-name>
    <filter-class>com.ajun.filter.ExceptionFiler</filter-class>
    <init-param>
        <param-name>errorPage</param-name>
        <param-value>/error.jsp</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>ExceptionFilter</filter-name>
    <url-pattern>*.do</url-pattern>
</filter-mapping>  

 

时间: 2024-11-01 16:05:51

Servlet、Filter的相关文章

深入Jetty源码之Servlet框架及实现(Servlet、Filter、Registration)

概述 Servlet是Server Applet的缩写,即在服务器端运行的小程序,而Servlet框架则是对HTTP服务器(Servlet Container)和用户小程序中间层的标准化和抽象.这一层抽象隔离了HTTP服务器的实现细节,而Servlet规范定义了各个类的行为,从而保证了这些"服务器端运行的小程序"对服务器实现的无关性(即提升了其可移植性).在Servlet规范有以下几个核心类(接口):ServletContext:定义了一些可以和Servlet Container交互的

Java servlet、filter、listener、interceptor之间的区别和联系_java

servlet.filter.listener.interceptor之间的区别和联系 一.概念 1.servlet:servlet是一种运行服务器端的java应用程序,具有独立于平台和协议的特性,并且可以动态的生成web页面,它工作在客户端请求与服务器响应的中间层. 2.filter:filter是一个可以复用的代码片段,可以用来转换HTTP请求.响应和头信息.Filter不像Servlet,它不能产生一个请求或者响应,它只是修改对某一资源的请求,或者修改从某一的响应. 3.listener:

JSP中的Servlet及Filter

asp.net中,如果开发人员想自己处理http请求响应,可以利用HttpHandler来满足这一要求:类似的,如果要拦截所有http请求,可以使用HttpMoudle.java的web开发中,也有类似的处理机制,与HttpHandler应对的是HttpServlet,与HttpModule对应的则是Filter. 一.HttpServlet 先看一个简单的示例: 1 package com.cnblogs.yjmyzz.servlet; 2 3 import java.io.IOExcepti

web.xml 中的listener、 filter、servlet 加载顺序及其详解

在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰.         首先可以肯定的是,加载顺序与它们在 web.xml 文件中的先后顺序无关.即不会因为 filter 写在 listener 的前面而会先加载 filter.最终得出的结论是:listener -> filter -> servlet         同时还存在着这样一种配置节:context-pa

Servlet和Filter的url匹配url-pattern

Servlet和filter是J2EE开发中常用的技术,使用方便,配置简单,老少皆宜. 估计大多数朋友都是直接配置用,也没有关心过具体的细节,今天遇到一个问题,上网查了servlet的规范才发现,servlet和filter中的url-pattern还是有一些文章在里面的,总结了一些东西,放出来供大家参考,以免遇到问题又要浪费时间. 一.servlet容器对url的匹配过程: 当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,

Servlet和Filter之间的区别与联系_java

filter是一个可以复用的代码片段,可以用来转换HTTP请求.响应和头信息.Filter不像Servlet,它不能产生一个请求或者响应,它只是修改对某一资源的请求,或者修改从某一的响应. 最近使用插装的时候,改用cookie对计算机进行识别,加入了过滤,仔细研究了一下servlet和filter,区别主要是: 过滤器的生命周期一般都要经过下面三个阶段: servlet的特点是: 初始化 当容器第一次加载该过滤器时,init() 方法将被调用.该类在这个方法中包含了一个指向 Filter Con

Servlet、Jsp性能优化

js|servlet|性能|优化 你的J2EE应用是不是运行的很慢?它们能不能承受住不断上升的访问量?本文讲述了开发高性能.高弹性的JSP页面和Servlet的性能优化技术.其意思是建立尽可能快的并能适应数量增长的用户及其请求.在本文中,我将带领你学习已经实践和得到证实的性能调整技术,它将大大地提高你的servlet和jsp页面的性能,进而提升J2EE的性能.这些技术的部分用于开发阶段,例如,设计和编码阶段.另一部分技术则与配置相关. 技术1:在HttpServlet init()方法中缓存数据

关于Servlet、Jsp中的多国语言显示

js|servlet|显示 因为一直不信Java竟会有不能混排显示多国语言的BUG,这个周末研究了一下Servlet.Jsp的多国语言显示的问题,也就是Servlet的多字符集问题,由于我对字符集的概念还不是很清晰所以写出的东西未必是准确的,我是这样理解Java中的字符集的:在运行时,每个字符串对象中存储的都是编码为UNICODE内码的(我觉得所有的语言中都是有相应编码的,因为在计算机内部字符串总是用内码来表示的,只不过一般计算机语言中的字符串编码时平台相关的,而Java则采用了平台无关的UNI

关于Servlet、Jsp中的多国语言显示 -- 转自高人

js|servlet|显示 /***有朋友有如此苦心之作,实在感谢,相信它不会怪我转贴吧,他的email是vividq@china.com*/ 关于Servlet.Jsp中的多国语言显示 因为一直不信Java竟会有不能混排显示多国语言的BUG,这个周末研究了一下Servlet.Jsp的多国语言显示的问题,也就是Servlet的多字符集问题,由于我对字符集的概念还不是很清晰所以写出的东西未必是准确的,我是这样理解Java中的字符集的:在运行时,每个字符串对象中存储的都是编码为UNICODE内码的(