今天写了写了阵微信公众号玩,Spring+Struts搭的,有个需求是签名验证,需要在本地缓存一个用户ticket,而获取ticket的逻辑在某个spring service中实现的。

对所有的jsp页面,想要注入对应的信息,而且不配置struts的话,想了想,最好用filter。实现了filter之后,准备注入service,这个时候启动webproject发现,service为null.怎么回事?为什么spring环境中明明通过@Component注入了对应的FIlter,并且通过@Autowired注入了对应的Service,为何Web请求的时候获取不到对应的Service?

应该有这么几个问题需要我搞清楚:1.web 加载的时候有filter,listener,servlet等元素,他们是如何加载的,顺序如何,是不是filter的环境spring 管不到。2.我的配置是如何启动?3.应该如何解决这个问题,即如何在filter中使用service?

一、Filter,Listener,Servlet对比

首先这三个东东来自web.xml,那么web.xml是干嘛的?

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5">
</web-app>

第一行给出了XML头,用来定义字符编码和xml版本,一般的xml文件都有这个。紧接着是web-app元素,这个元素的xmlns,即xml namespace是定义该元素所支持的子元素的。可以看出,在web.xml中是namespace是来自于sun的javaee页面。

可以看出上面配置的,是06年发布的2.5标准。而最新的已经是13年4月发布的3.1。我看了下web-app_3.1.xsd,其中引入了

</pre><pre name="code" class="html"><xsd:include schemaLocation="web-common_3_1.xsd"/>

这个文件中定义这些元素:

 <xsd:element name="filter"type="javaee:filterType"/><xsd:element name="filter-mapping"type="javaee:filter-mappingType"/><xsd:element name="listener"type="javaee:listenerType"/><xsd:element name="servlet"type="javaee:servletType"/><xsd:element name="servlet-mapping"type="javaee:servlet-mappingType"/>

可以看到这几个元素都定义了name和type,这个type又是在哪儿定义的呢?原来web-common_3_1.xsd又引入了javaee.xsd和jsp_2_3.xsd。在javaee.xsd中,定义了这些type。

1.filterType和filterMappingTYpe的定义(在web-common_3.1.xsd中):

  <xsd:complexType name="filterType"><xsd:annotation><xsd:documentation><span style="font-size:14px;"><span style="color:#3366ff;">        <strong>The filterType is used to declare a filter in the webapplication. The filter is mapped to either a servlet or aURL pattern in the filter-mapping element, using thefilter-name value to reference.</strong></span><span style="color:#ff0000;"> </span></span>Filters can access theinitialization parameters declared in the deploymentdescriptor at runtime via the FilterConfig interface.Used in: web-app</xsd:documentation></xsd:annotation><xsd:sequence><xsd:group ref="javaee:descriptionGroup"/><xsd:element name="filter-name"type="javaee:filter-nameType"/><xsd:element name="filter-class"type="javaee:fully-qualified-classType"minOccurs="0"maxOccurs="1"><xsd:annotation><xsd:documentation>The fully qualified classname of the filter.</xsd:documentation></xsd:annotation></xsd:element><xsd:element name="async-supported"type="javaee:true-falseType"minOccurs="0"/><xsd:element name="init-param"type="javaee:param-valueType"minOccurs="0"maxOccurs="unbounded"><xsd:annotation><xsd:documentation>The init-param element contains a name/value pair asan initialization param of a servlet filter</xsd:documentation></xsd:annotation></xsd:element></xsd:sequence><xsd:attribute name="id"type="xsd:ID"/></xsd:complexType>
<xsd:complexType name="filter-mappingType"><xsd:annotation><xsd:documentation>Declaration of the filter mappings in this webapplication is done by using filter-mappingType. The container uses the filter-mapping<span style="background-color: rgb(255, 255, 255);"><span style="color:#000099;">  <strong>declarations to decide which filters to apply to a request,and in what order.</strong> </span></span>The container matches the request URI toa Servlet in the normal way. To determine which filters toapply it matches filter-mapping declarations either onservlet-name, or on url-pattern for each filter-mappingelement, depending on which style is used. The order inwhich filters are invoked is the order in whichfilter-mapping declarations that match a request URI for aservlet appear in the list of filter-mapping elements.Thefilter-name value must be the value of the filter-namesub-elements of one of the filter declarations in thedeployment descriptor.</xsd:documentation></xsd:annotation><xsd:sequence><xsd:element name="filter-name"type="javaee:filter-nameType"/><xsd:choice minOccurs="1"maxOccurs="unbounded"><xsd:element name="url-pattern"type="javaee:url-patternType"/><xsd:element name="servlet-name"type="javaee:servlet-nameType"/></xsd:choice><xsd:element name="dispatcher"type="javaee:dispatcherType"minOccurs="0"maxOccurs="5"/></xsd:sequence><xsd:attribute name="id"type="xsd:ID"/></xsd:complexType>

2.listener定义在javaee_7.xsd.

  <xsd:complexType name="listenerType"><xsd:annotation><xsd:documentation><span style="background-color: rgb(255, 255, 255);"><span style="color:#000099;"><strong>The listenerType indicates the deployment properties for a webapplication listener bean.</strong></span></span></xsd:documentation></xsd:annotation><xsd:sequence><xsd:group ref="javaee:descriptionGroup"/><xsd:element name="listener-class"type="javaee:fully-qualified-classType"><xsd:annotation><xsd:documentation>The listener-class element declares a class in theapplication must be registered as a webapplication listener bean. The value is the fullyqualified classname of the listener class.</xsd:documentation></xsd:annotation></xsd:element></xsd:sequence><xsd:attribute name="id"type="xsd:ID"/></xsd:complexType>

3.Servlet定义在web-commmon_3.1.xsd中,

 <xsd:complexType name="servletType"><xsd:annotation><xsd:documentation><span style="background-color: rgb(255, 255, 255);"><span style="color:#000099;"><strong>The servletType is used to declare a servlet.</strong></span></span>It contains the declarative data of aservlet. If a jsp-file is specified and the load-on-startupelement is present, then the JSP should be precompiled andloaded.Used in: web-app</xsd:documentation></xsd:annotation><xsd:sequence><xsd:group ref="javaee:descriptionGroup"/><xsd:element name="servlet-name"type="javaee:servlet-nameType"/><xsd:choice minOccurs="0"maxOccurs="1"><xsd:element name="servlet-class"type="javaee:fully-qualified-classType"><xsd:annotation><xsd:documentation>The servlet-class element contains the fullyqualified class name of the servlet.</xsd:documentation></xsd:annotation></xsd:element><xsd:element name="jsp-file"type="javaee:jsp-fileType"/></xsd:choice><xsd:element name="init-param"type="javaee:param-valueType"minOccurs="0"maxOccurs="unbounded"/><xsd:element name="load-on-startup"type="javaee:load-on-startupType"minOccurs="0"><xsd:annotation><xsd:documentation>The load-on-startup element indicates that thisservlet should be loaded (instantiated and haveits init() called) on the startup of the webapplication. The optional contents of theseelement must be an integer indicating the order inwhich the servlet should be loaded. If the valueis a negative integer, or the element is notpresent, the container is free to load the servletwhenever it chooses. If the value is a positiveinteger or 0, the container must load andinitialize the servlet as the application isdeployed. The container must guarantee thatservlets marked with lower integers are loadedbefore servlets marked with higher integers. Thecontainer may choose the order of loading ofservlets with the same load-on-start-up value.</xsd:documentation></xsd:annotation></xsd:element><xsd:element name="enabled"type="javaee:true-falseType"minOccurs="0"/><xsd:element name="async-supported"type="javaee:true-falseType"minOccurs="0"/><xsd:element name="run-as"type="javaee:run-asType"minOccurs="0"/><xsd:element name="security-role-ref"type="javaee:security-role-refType"minOccurs="0"maxOccurs="unbounded"/><xsd:element name="multipart-config"type="javaee:multipart-configType"minOccurs="0"maxOccurs="1"/></xsd:sequence><xsd:attribute name="id"type="xsd:ID"/></xsd:complexType><!-- **************************************************** --><xsd:complexType name="servlet-mappingType"><xsd:annotation><xsd:documentation>The servlet-mappingType defines a mapping between aservlet and a url pattern. Used in: web-app</xsd:documentation></xsd:annotation><xsd:sequence><xsd:element name="servlet-name"type="javaee:servlet-nameType"/><xsd:element name="url-pattern"type="javaee:url-patternType"minOccurs="1"maxOccurs="unbounded"/></xsd:sequence><xsd:attribute name="id"type="xsd:ID"/></xsd:complexType><!-- **************************************************** --><xsd:complexType name="servlet-nameType"><xsd:annotation><xsd:documentation>The servlet-name element contains the canonical name of theservlet. Each servlet name is unique within the webapplication.</xsd:documentation></xsd:annotation><xsd:simpleContent><xsd:extension base="javaee:nonEmptyStringType"/></xsd:simpleContent></xsd:complexType>

看完这3个元素的定义,总结一句话,他们是干啥的,servlet呢是定义servlet的,listener呢是定义listener的,filter是定义filter的。扯了半天蛋,其实要了解web.xml中的这几个元素,还是得看看其它资料,先看看百度百科吧,Servlet(http://baike.baidu.com/link?url=PK8201TxZwwQZKAwLiu9Mob6rPo2AnApub5uT8PCPoigifBFGdGyFMQeyuBL3e6KWdTpQkxpxZwPJGvwgHLF8K),Filter(http://baike.baidu.com/link?url=Zb9NDPAOIgkyy2OvquA7pLapG58QlM0O1fTBlIIVdFk8NoJXhuC2fKJnOnksnNaf62T7936X8isYIvDHWp59iq).然后就知道了, servlet可以看成一个简单的服务提供者,filter则是一个在请求到达服务提供者之前对request进行预处理的过滤器,而listener则是在web应用启动的时候进行初始化,然后拦截相关的请求,只有当应用重新部署或者停止的时候才干掉。

这几个元素都是通过实现几个接口才能拓展,这几个接口分别是:

1.FIlter.java

/** DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.** Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.** The contents of this file are subject to the terms of either the GNU* General Public License Version 2 only ("GPL") or the Common Development* and Distribution License("CDDL") (collectively, the "License").  You* may not use this file except in compliance with the License.  You can* obtain a copy of the License at* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html* or packager/legal/LICENSE.txt.  See the License for the specific* language governing permissions and limitations under the License.** When distributing the software, include this License Header Notice in each* file and include the License file at packager/legal/LICENSE.txt.** GPL Classpath Exception:* Oracle designates this particular file as subject to the "Classpath"* exception as provided by Oracle in the GPL Version 2 section of the License* file that accompanied this code.** Modifications:* If applicable, add the following below the License Header, with the fields* enclosed by brackets [] replaced by your own identifying information:* "Portions Copyright [year] [name of copyright owner]"** Contributor(s):* If you wish your version of this file to be governed by only the CDDL or* only the GPL Version 2, indicate your decision by adding "[Contributor]* elects to include this software in this distribution under the [CDDL or GPL* Version 2] license."  If you don't indicate a single choice of license, a* recipient has the option to distribute your version of this file under* either the CDDL, the GPL Version 2 or to extend the choice of license to* its licensees as provided above.  However, if you add GPL Version 2 code* and therefore, elected the GPL Version 2 license, then the option applies* only if the new code is made subject to such option by the copyright* holder.*** This file incorporates work covered by the following copyright and* permission notice:** Copyright 2004 The Apache Software Foundation** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package javax.servlet;import java.io.IOException;/*** A filter is an object that performs filtering tasks on either the* request to a resource (a servlet or static content), or on the response* from a resource, or both.* * <p>Filters perform filtering in the <code>doFilter</code> method.* Every Filter has access to a FilterConfig object from which it can obtain* its initialization parameters, and a reference to the ServletContext which* it can use, for example, to load resources needed for filtering tasks.** <p>Filters are configured in the deployment descriptor of a web* application.** <p>Examples that have been identified for this design are:* <ol>* <li>Authentication Filters* <li>Logging and Auditing Filters* <li>Image conversion Filters* <li>Data compression Filters* <li>Encryption Filters* <li>Tokenizing Filters* <li>Filters that trigger resource access events* <li>XSL/T filters* <li>Mime-type chain Filter* </ol>** @since Servlet 2.3*/public interface Filter {/** * Called by the web container to indicate to a filter that it is* being placed into service.** <p>The servlet container calls the init* method exactly once after instantiating the filter. The init* method must complete successfully before the filter is asked to do any* filtering work.* * <p>The web container cannot place the filter into service if the init* method either* <ol>* <li>Throws a ServletException* <li>Does not return within a time period defined by the web container* </ol>*/public void init(FilterConfig filterConfig) throws ServletException;/*** The <code>doFilter</code> method of the Filter is called by the* container each time a request/response pair is passed through the* chain due to a client request for a resource at the end of the chain.* The FilterChain passed in to this method allows the Filter to pass* on the request and response to the next entity in the chain.** <p>A typical implementation of this method would follow the following* pattern:* <ol>* <li>Examine the request* <li>Optionally wrap the request object with a custom implementation to* filter content or headers for input filtering* <li>Optionally wrap the response object with a custom implementation to* filter content or headers for output filtering* <li>* <ul>* <li><strong>Either</strong> invoke the next entity in the chain* using the FilterChain object* (<code>chain.doFilter()</code>),* <li><strong>or</strong> not pass on the request/response pair to* the next entity in the filter chain to* block the request processing* </ul>* <li>Directly set headers on the response after invocation of the* next entity in the filter chain.* </ol>*/public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)throws IOException, ServletException;/*** Called by the web container to indicate to a filter that it is being* taken out of service.** <p>This method is only called once all threads within the filter's* doFilter method have exited or after a timeout period has passed.* After the web container calls this method, it will not call the* doFilter method again on this instance of the filter.** <p>This method gives the filter an opportunity to clean up any* resources that are being held (for example, memory, file handles,* threads) and make sure that any persistent state is synchronized* with the filter's current state in memory.*/public void destroy();
}

Servlet.java

/** DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.** Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.** The contents of this file are subject to the terms of either the GNU* General Public License Version 2 only ("GPL") or the Common Development* and Distribution License("CDDL") (collectively, the "License").  You* may not use this file except in compliance with the License.  You can* obtain a copy of the License at* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html* or packager/legal/LICENSE.txt.  See the License for the specific* language governing permissions and limitations under the License.** When distributing the software, include this License Header Notice in each* file and include the License file at packager/legal/LICENSE.txt.** GPL Classpath Exception:* Oracle designates this particular file as subject to the "Classpath"* exception as provided by Oracle in the GPL Version 2 section of the License* file that accompanied this code.** Modifications:* If applicable, add the following below the License Header, with the fields* enclosed by brackets [] replaced by your own identifying information:* "Portions Copyright [year] [name of copyright owner]"** Contributor(s):* If you wish your version of this file to be governed by only the CDDL or* only the GPL Version 2, indicate your decision by adding "[Contributor]* elects to include this software in this distribution under the [CDDL or GPL* Version 2] license."  If you don't indicate a single choice of license, a* recipient has the option to distribute your version of this file under* either the CDDL, the GPL Version 2 or to extend the choice of license to* its licensees as provided above.  However, if you add GPL Version 2 code* and therefore, elected the GPL Version 2 license, then the option applies* only if the new code is made subject to such option by the copyright* holder.*** This file incorporates work covered by the following copyright and* permission notice:** Copyright 2004 The Apache Software Foundation** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package javax.servlet;import java.io.IOException;/*** Defines methods that all servlets must implement.** <p>A servlet is a small Java program that runs within a Web server.* Servlets receive and respond to requests from Web clients,* usually across HTTP, the HyperText Transfer Protocol. ** <p>To implement this interface, you can write a generic servlet* that extends* <code>javax.servlet.GenericServlet</code> or an HTTP servlet that* extends <code>javax.servlet.http.HttpServlet</code>.** <p>This interface defines methods to initialize a servlet,* to service requests, and to remove a servlet from the server.* These are known as life-cycle methods and are called in the* following sequence:* <ol>* <li>The servlet is constructed, then initialized with the <code>init</code> method.* <li>Any calls from clients to the <code>service</code> method are handled.* <li>The servlet is taken out of service, then destroyed with the * <code>destroy</code> method, then garbage collected and finalized.* </ol>** <p>In addition to the life-cycle methods, this interface* provides the <code>getServletConfig</code> method, which the servlet * can use to get any startup information, and the <code>getServletInfo</code>* method, which allows the servlet to return basic information about itself,* such as author, version, and copyright.** @author     Various** @see     GenericServlet* @see   javax.servlet.http.HttpServlet**/public interface Servlet {/*** Called by the servlet container to indicate to a servlet that the * servlet is being placed into service.** <p>The servlet container calls the <code>init</code>* method exactly once after instantiating the servlet.* The <code>init</code> method must complete successfully* before the servlet can receive any requests.** <p>The servlet container cannot place the servlet into service* if the <code>init</code> method* <ol>* <li>Throws a <code>ServletException</code>* <li>Does not return within a time period defined by the Web server* </ol>*** @param config          a <code>ServletConfig</code> object *                   containing the servlet's*                  configuration and initialization parameters** @exception ServletException  if an exception has occurred that*                  interferes with the servlet's normal*                  operation** @see               UnavailableException* @see                 #getServletConfig**/public void init(ServletConfig config) throws ServletException;/**** Returns a {@link ServletConfig} object, which contains* initialization and startup parameters for this servlet.* The <code>ServletConfig</code> object returned is the one * passed to the <code>init</code> method. ** <p>Implementations of this interface are responsible for storing the * <code>ServletConfig</code> object so that this * method can return it. The {@link GenericServlet}* class, which implements this interface, already does this.** @return        the <code>ServletConfig</code> object*          that initializes this servlet** @see       #init**/public ServletConfig getServletConfig();/*** Called by the servlet container to allow the servlet to respond to * a request.** <p>This method is only called after the servlet's <code>init()</code>* method has completed successfully.* * <p>  The status code of the response always should be set for a servlet * that throws or sends an error.** * <p>Servlets typically run inside multithreaded servlet containers* that can handle multiple requests concurrently. Developers must * be aware to synchronize access to any shared resources such as files,* network connections, and as well as the servlet's class and instance * variables. * More information on multithreaded programming in Java is available in * <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">* the Java tutorial on multi-threaded programming</a>.*** @param req     the <code>ServletRequest</code> object that contains*           the client's request** @param res     the <code>ServletResponse</code> object that contains*          the servlet's response** @exception ServletException  if an exception occurs that interferes*                 with the servlet's normal operation ** @exception IOException         if an input or output exception occurs**/public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;/*** Returns information about the servlet, such* as author, version, and copyright.* * <p>The string that this method returns should* be plain text and not markup of any kind (such as HTML, XML,* etc.).** @return      a <code>String</code> containing servlet information**/public String getServletInfo();/**** Called by the servlet container to indicate to a servlet that the* servlet is being taken out of service.  This method is* only called once all threads within the servlet's* <code>service</code> method have exited or after a timeout* period has passed. After the servlet container calls this * method, it will not call the <code>service</code> method again* on this servlet.** <p>This method gives the servlet an opportunity * to clean up any resources that are being held (for example, memory,* file handles, threads) and make sure that any persistent state is* synchronized with the servlet's current state in memory.**/public void destroy();
}

ServletContextListener.java

/** DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.** Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.** The contents of this file are subject to the terms of either the GNU* General Public License Version 2 only ("GPL") or the Common Development* and Distribution License("CDDL") (collectively, the "License").  You* may not use this file except in compliance with the License.  You can* obtain a copy of the License at* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html* or packager/legal/LICENSE.txt.  See the License for the specific* language governing permissions and limitations under the License.** When distributing the software, include this License Header Notice in each* file and include the License file at packager/legal/LICENSE.txt.** GPL Classpath Exception:* Oracle designates this particular file as subject to the "Classpath"* exception as provided by Oracle in the GPL Version 2 section of the License* file that accompanied this code.** Modifications:* If applicable, add the following below the License Header, with the fields* enclosed by brackets [] replaced by your own identifying information:* "Portions Copyright [year] [name of copyright owner]"** Contributor(s):* If you wish your version of this file to be governed by only the CDDL or* only the GPL Version 2, indicate your decision by adding "[Contributor]* elects to include this software in this distribution under the [CDDL or GPL* Version 2] license."  If you don't indicate a single choice of license, a* recipient has the option to distribute your version of this file under* either the CDDL, the GPL Version 2 or to extend the choice of license to* its licensees as provided above.  However, if you add GPL Version 2 code* and therefore, elected the GPL Version 2 license, then the option applies* only if the new code is made subject to such option by the copyright* holder.*** This file incorporates work covered by the following copyright and* permission notice:** Copyright 2004 The Apache Software Foundation** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package javax.servlet;import java.util.EventListener;/** * Interface for receiving notification events about ServletContext* lifecycle changes.** <p>In order to receive these notification events, the implementation* class must be either declared in the deployment descriptor of the web* application, annotated with {@link javax.servlet.annotation.WebListener},* or registered via one of the addListener methods defined on* {@link ServletContext}.** <p>Implementations of this interface are invoked at their* {@link #contextInitialized} method in the order in which they have been* declared, and at their {@link #contextDestroyed} method in reverse* order.** @see ServletContextEvent** @since Servlet 2.3*/
public interface ServletContextListener extends EventListener {/*** Receives notification that the web application initialization* process is starting.** <p>All ServletContextListeners are notified of context* initialization before any filters or servlets in the web* application are initialized.** @param sce the ServletContextEvent containing the ServletContext* that is being initialized*/public void contextInitialized(ServletContextEvent sce);/*** Receives notification that the ServletContext is about to be* shut down.** <p>All servlets and filters will have been destroyed before any* ServletContextListeners are notified of context* destruction.** @param sce the ServletContextEvent containing the ServletContext* that is being destroyed*/public void contextDestroyed(ServletContextEvent sce);
}

这三个接口都在package javax.servlet下。

好吧,差不多该看看起初提出的问题了,web 加载的时候有filter,listener,servlet等元素,他们是如何加载的,顺序如何,是不是filter的环境spring 管不到?

Listener的加载是在应用一开始启动的时候,多个listener之间是没有顺序的,如果有多个listener需要顺序加载,可以考虑把多个listener合并成一个。(eg:http://www.iteye.com/problems/33443)Filter的加载是按照在web.xml中的先后顺序的,其中的init方法,按照的是filter的顺序,doFilter方法是按照filter-mapping的顺序,如果多个filter被一次请求匹配到,则是按照一个filter栈的逻辑进行调用。Servlet的加载顺序则没有前后之别,是请求匹配到哪个就进行哪个的加载。 它们3个之间的顺序关系是,可以看这个(http://www.oschina.net/code/snippet_52678_44994),启动-->listener-->filter-->servlet--->访问-->filter-->servlet-->关闭-->servlet--->filter-->listener。

那么spring bean是否可以在filter中加载到?

从上面的启动顺序可以看出,filter调用的时候,Spring是通过listener进行加载的,肯定是已经启动了。那么为什么我直接把Filter添加Spring的@Component注解,通过@Autowired却加载不到呢?这是由于,在spring对对应的bean进行扫描的时候,filter还没有执行初始化,filter的加载是在listener之后的,那么想要在filter中加载到spring的环境,那么可以通过init方法进行注入,或者在doFilter的时候进行注入(这样成本较高,每次都得注入)。具体实现在第三部分。

二、我的配置是如何启动的。

代码:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"version="2.5"><!-- 加载SPRING配置文件 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/spring.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- STRUTS2配置 --><filter><filter-name>struts2</filter-name><filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class><init-param><param-name>config</param-name>  <param-value>struts-default.xml,struts-plugin.xml,struts2/struts.xml,struts2/struts-redis.xml</param-value>  </init-param></filter><filter-mapping><filter-name>struts2</filter-name><url-pattern>*</url-pattern></filter-mapping><!-- 过滤器可以作用于jsp而拦截器只能拦截action. --><filter><filter-name> wechat_web_filter</filter-name><filter-class>com.marsyoung.filter.WeChatJspFilter</filter-class></filter><filter-mapping><filter-name>wechat_web_filter</filter-name><url-pattern>*.jsp</url-pattern></filter-mapping>
<pre name="code" class="plain"><span style="font-family: Arial, Helvetica, sans-serif;">   <!-- 超时时间,半小时 --></span>

<session-config> <session-timeout>30</session-timeout> </session-config><welcome-file-list><welcome-file>/jsp/index.jsp</welcome-file></welcome-file-list></web-app>

日志:

九月 01, 2015 2:57:44 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-nio-8080"]
九月 01, 2015 2:57:44 下午 org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
信息: Using a shared selector for servlet write/read
九月 01, 2015 2:57:44 下午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["ajp-nio-8009"]
九月 01, 2015 2:57:44 下午 org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
信息: Using a shared selector for servlet write/read
九月 01, 2015 2:57:44 下午 org.apache.catalina.startup.Catalina load
信息: Initialization processed in 998 ms
九月 01, 2015 2:57:44 下午 org.apache.catalina.core.StandardService startInternal
信息: Starting service Catalina
九月 01, 2015 2:57:44 下午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet Engine: Apache Tomcat/8.0.24
九月 01, 2015 2:57:45 下午 org.apache.catalina.util.SessionIdGeneratorBase createSecureRandom
信息: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [105] milliseconds.
九月 01, 2015 2:57:52 下午 org.apache.jasper.servlet.TldScanner scanJars
信息: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
九月 01, 2015 2:57:52 下午 org.apache.catalina.core.ApplicationContext log
信息: No Spring WebApplicationInitializer types detected on classpath
九月 01, 2015 2:57:52 下午 org.apache.catalina.core.ApplicationContext log
信息:<strong> <span style="color:#ff0000;">Initializing Spring root WebApplicationContext</span></strong>
2015-09-01 14:57:56.812  INFO Program init successful.
九月 01, 2015 2:57:58 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["http-nio-8080"]
九月 01, 2015 2:57:58 下午 org.apache.coyote.AbstractProtocol start
信息: Starting ProtocolHandler ["ajp-nio-8009"]
九月 01, 2015 2:57:58 下午 org.apache.catalina.startup.Catalina start
信息: Server startup in 13985 ms

额,日志中只打出了spring listener进行加载的这一句,前面是tomcat进行启动。其实启动过程就是,加载那个context-param,然后加载listener,然后listener中加载spring.xm的配置,引入了其中配置的数据源bean,Service Bean,以及Struts Action Bean。之后在加载Filter。

三、如何写在Filter中加载Spring环境。

package com.marsyoung.filter;import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.Map.Entry;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;import com.marsyoung.constants.WeiXinConstants;
import com.marsyoung.service.WeChatService;/*** 微信验证过滤器* * @author Mars* */
public class WeChatJspFilter implements Filter {Logger logger = LoggerFactory.getLogger(WeChatJspFilter.class);private static final String EQUAL_SIGN = "=";private static final String PLUS_SIGN = "+";private static final String AND = "&";WeChatService weChatService;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {ServletContext servletContext = filterConfig.getServletContext();WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);weChatService = wac.getBean(WeChatService.class);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;// HttpSession session = request.getSession();String timestamp = (System.currentTimeMillis() + "").substring(0, 10);// 时间戳String nonce = create_nonce_str();String createSignature = null;try {createSignature = weChatService.getJsapiTicket();} catch (Exception e) {logger.info("获取签名失败,{}", e);}request.setAttribute("signature", createSignature);// 这个值得设置应该放到Action中去。request.setAttribute("timestamp", timestamp);request.setAttribute("appId", WeiXinConstants.WeiXin_AppID);request.setAttribute("nonce", nonce);log(request, response);chain.doFilter(request, response);}private void log(HttpServletRequest request, HttpServletResponse response) {String remoteHost = request.getHeader("x-real-ip"); // 获取客户端的主机名if (remoteHost == null) {remoteHost = "“没有获取到客户端IP”";}String requestURL = request.getRequestURL().toString(); // 获取客户端请求的URLMap<String, String[]> paramsMap = request.getParameterMap(); // 获取所有的请求参数/** 获取所有参数的名值对信息的字符串表示,存储在变量paramsStr中*/StringBuilder paramsStrSb = new StringBuilder();if (paramsMap != null && paramsMap.size() > 0) {Set<Entry<String, String[]>> paramsSet = paramsMap.entrySet();for (Entry<String, String[]> param : paramsSet) {StringBuilder paramStrSb = new StringBuilder();String paramName = param.getKey(); // 参数的名字String[] paramValues = param.getValue(); // 参数的值if (paramValues.length == 1) { // 参数只有一个值,绝大多数情况paramStrSb.append(paramName).append(EQUAL_SIGN).append(paramValues[0]);} else {paramStrSb.append(paramName).append(EQUAL_SIGN);for (String paramValue : paramValues) {paramStrSb.append(paramValue);paramStrSb.append(PLUS_SIGN);}paramStrSb.deleteCharAt(paramStrSb.length() - 1);}paramsStrSb.append(paramStrSb).append(AND);}paramsStrSb.deleteCharAt(paramsStrSb.length() - 1);}String paramsStr = paramsStrSb.toString();logger.info("收到来自" + remoteHost + "的请求,URL:" + requestURL + ",参数:" + paramsStr);}private static String create_nonce_str() {return UUID.randomUUID().toString();}@Overridepublic void destroy() {}}

Web filter中如何引用Spring的bean相关推荐

  1. maven mybatis mysql_Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问...

    标签: 本篇内容还是建立在上一篇Java Web学习系列--Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Ja ...

  2. webservice引用spring的bean

    1 <jaxws:endpoint address="/test/webservice" implementor="#testBean" /> 这行 ...

  3. 在servlet中或者在filter中获取spring容器中的bean

    1 配置spring文件 <bean id="hibernateTemplate" class="org.springframework.orm.hibernate ...

  4. 从源码看spring applicationContext在web容器中加载过程

    2019独角兽企业重金招聘Python工程师标准>>> 原文:http://blog.csdn.net/fuliangliang/archive/2006/12/22/1454382 ...

  5. Spring在web开发中的应用

    (1)在 web 项目中要使用 spring 需要导入一个 jar 包: spring-web-4.2.4.jar包 (2)在 web.xml 文件中配置 Listener <listener& ...

  6. spring配置bean

    第一章 spring框架构成 第二章 spring容器 第三章 spring配置bean 文章目录 spring配置bean 使用xml配置 使用构造器创建 依赖注入方式 setter方法注入 构造方 ...

  7. spring的Bean

    Bean标签的常用属性     1.Id:属性值名称随便起,但是不能有特殊符号     2.Class:创建类对象的所在类的全路径     3.Name:与Id相似,但是名称可以用特殊符号(遗留的一个 ...

  8. spring web.xml中 过滤器(Filter)的工作原理和代码演示

    一.Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术之一,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, ...

  9. springboot项目中的注解 启动项目的方式 解决spring的bean.xml配置不生效 spring的基础JDBC配置

    依赖 创建一个 Spring Boot 工程时,可以继承自一个 spring-boot-starter-parent ,也可以不继承 先来看 parent 的基本功能有哪些? 定义了 Java 编译版 ...

最新文章

  1. bash编程-循环控制的结构
  2. 云炬Android开发笔记 5-5,6Loading框架集成与完善AVLoadingIndicatorView
  3. 总结java父类构造函数对子类构造函数的影响
  4. 使用内置函数操作数据库
  5. java 二叉树迭代器_C,为二叉树实现自定义迭代器(长)
  6. 推荐两款工具给爱做实验的人
  7. SQLServer 2005新功能
  8. 9-12 原生安装4
  9. 2012写给自己的年度总结
  10. PSD网页切图制作HTML全过程教程
  11. EasyUi之书籍功能(CRUD)
  12. exoplay切换全屏_基于exoPlayer 拓展自定义播放器
  13. 【办公自动化Excel】制作图表
  14. 亲爱的朋友,祝您天天好心情!
  15. 海康威视存储服务器915CVR设备手动配置RAID5操作手册
  16. 王者荣耀怎么删除在服务器上建立的账号,王者荣耀账号怎么注销 王者荣耀账号注销方法...
  17. ERP系统软件在国家电网公司中的应用
  18. python中cos函数_Python代码中cos()函数有什么功能呢?
  19. connetos 装php,RouterOS 5.16软路由安装图解教程 | 系统运维
  20. luogu P3041 [USACO12JAN]视频游戏的连击Video Game Combos

热门文章

  1. 【金猿产品展】Quick Audience——一站式消费者运营和管理平台
  2. Java 多线程 之 火车站售票实例
  3. hive源码之get_json_object
  4. linux web全栈编辑器,sx html5全栈可视编辑器下载
  5. 文字识别如何行切割matlab,车牌识别程序里怎么调入切割函数
  6. 华为note8鸿蒙,华为荣耀NOTE8综合评测:性价比如何看完就知道了
  7. 股票证券软件测试简历,股票交易系统测试计划.doc
  8. C语言layout文件有用吗,C语言内存模型 (C memory layout)
  9. spring-cloud-kubernetes学习(一) 编写第一个spring-cloud-kubernetes例子并在kubernetes中测试
  10. 通知 | 中秋节放假安排