本文主要研究下spring mvc的No thread-bound request found異常html
該錯誤信息在RequestContextHolder這個類中,詳細以下:
spring-web-4.3.7.RELEASE-sources.jar!/org/springframework/web/context/request/RequestContextHolder.javajava
public abstract class RequestContextHolder { private static final boolean jsfPresent = ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader()); private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal<RequestAttributes>("Request attributes"); private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal<RequestAttributes>("Request context"); /** * Return the RequestAttributes currently bound to the thread. * <p>Exposes the previously bound RequestAttributes instance, if any. * Falls back to the current JSF FacesContext, if any. * @return the RequestAttributes currently bound to the thread * @throws IllegalStateException if no RequestAttributes object * is bound to the current thread * @see #setRequestAttributes * @see ServletRequestAttributes * @see FacesRequestAttributes * @see javax.faces.context.FacesContext#getCurrentInstance() */ public static RequestAttributes currentRequestAttributes() throws IllegalStateException { RequestAttributes attributes = getRequestAttributes(); if (attributes == null) { if (jsfPresent) { attributes = FacesRequestAttributesFactory.getFacesRequestAttributes(); } if (attributes == null) { throw new IllegalStateException("No thread-bound request found: " + "Are you referring to request attributes outside of an actual web request, " + "or processing a request outside of the originally receiving thread? " + "If you are actually operating within a web request and still receive this message, " + "your code is probably running outside of DispatcherServlet/DispatcherPortlet: " + "In this case, use RequestContextListener or RequestContextFilter to expose the current request."); } } return attributes; } /** * Return the RequestAttributes currently bound to the thread. * @return the RequestAttributes currently bound to the thread, * or {@code null} if none bound */ public static RequestAttributes getRequestAttributes() { RequestAttributes attributes = requestAttributesHolder.get(); if (attributes == null) { attributes = inheritableRequestAttributesHolder.get(); } return attributes; } //... }
在非web下訪問了RequestContextHolder.currentRequestAttributes()致使,所以在service層方法裏頭調用該方法要慎重,爲了不出錯,能夠再封裝一下web
public RequestAttributes getRequestAttributesSafely(){ RequestAttributes requestAttributes = null; try{ requestAttributes = RequestContextHolder.currentRequestAttributes(); }catch (IllegalStateException e){ requestAttributes = new NonWebRequestAttributes(); } return requestAttributes; }
NonWebRequestAttributes實現RequestAttributes接口,重寫的方法都爲空便可
對於在service層使用RequestContextHolder的方法要當心,除了controller層外,調度任務等也可能調用service層的方法。spring