java源码

编程入门 行业动态 更新时间:2024-10-27 00:27:16

java<a href=https://www.elefans.com/category/jswz/34/1770099.html style=源码"/>

java源码

文章目录

  • 1. LocaleResolver
    • 1.1 继承关系类图
    • 1.2 AcceptHeaderLocaleResolver
    • 1.3 AbstractLocaleResolver
    • 1.4 AbstractLocaleContextResolver
    • 1.5 FixedLocaleResolver
    • 1.6 SessionLocaleResolver
  • 2. ThemeResolver
    • 2.1 类继承关系图
  • 3. FlashMapManager
    • 3.1 AbstractFlashMapManager
    • 3.2 SessionFlashMapManager

1. LocaleResolver

1.1 继承关系类图


在LocaleResolver的实现类中,AcceptHeaderLocaleResolver直接使用了Header里的“acceptlanguage”值,不可以在程序中修改;FixedLocaleResolver用于解析出固定的Locale,也就是说在创建时就设置好确定的Locale,之后无法修改;SessionLocaleResolver用于将Locale保存到Session中,可以修改;CookieLocaleResolver用于将Locale保存到Cookie中,可以修改。

接口内有两个方法:

public interface LocaleResolver {/***通过给定的请求解析当前的语言环境。*可以在任何情况下返回默认的语言环境作为回退。* @param请求解析语言环境的请求* @return当前语言环境(never {@code null})*/Locale resolveLocale(HttpServletRequest request);/***将当前语言环境设置为给定的语言环境。* @param请求用于语言环境修改的请求* @param响应用于语言环境修改的响应* @param locale是新的locale,或者{@code null}清除locale* @抛出UnsupportedOperationException如果LocaleResolver*实现不支持语言环境的动态更改*/void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);}

其还有一个子接口LocaleContextResolver,其中增加了获取和设置LocaleContext的能力:

public interface LocaleContextResolver extends LocaleResolver {/ * **通过给定请求解析当前语言环境上下文。*主要用于框架级处理;考虑使用* {@link org.springframework.web.servlet.support。RequestContextUtils}或* {@link org.springframework.web.servlet.support。RequestContext},应用程序级访问当前地区和/或时区。返回的上下文可以是a* {@link org.springframework.context.i18n.TimeZoneAwareLocaleContext},*包含有相关时区信息的地区设置。简单地应用一个{@code instanceof}检查并相应地向下强制转换。自定义解析器实现也可能返回额外的设置*返回的上下文,同样可以通过向下转换访问。* @param请求解析语言环境上下文的请求* @return当前地区上下文(never {@code null})* @see # resolveLocale (HttpServletRequest)* @see org.springframework.web.servlet.support.RequestContextUtils # getLocale* @see org.springframework.web.servlet.support.RequestContextUtils # getTimeZone* /LocaleContext resolveLocaleContext(HttpServletRequest request);/ * **将当前语境上下文设置为给定语境,*可能包含带有相关时区信息的地区设置。* @param请求用于语言环境修改的请求* @param响应用于语言环境修改的响应* @param localeContext新语言环境上下文,或{@code null}清除语言环境* @抛出UnsupportedOperationException,如果LocaleResolver实现*不支持动态更改地区或时区* @see #setLocale(HttpServletRequest, HttpServletResponse, Locale)* @see org.springframework.context.i18n.SimpleLocaleContext* @see org.springframework.context.i18n.SimpleTimeZoneAwareLocaleContext* /void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response,@Nullable LocaleContext localeContext);}

1.2 AcceptHeaderLocaleResolver

@Overridepublic Locale resolveLocale(HttpServletRequest request) {Locale defaultLocale = getDefaultLocale();if (defaultLocale != null && request.getHeader("Accept-Language") == null) {return defaultLocale;}Locale requestLocale = request.getLocale();List<Locale> supportedLocales = getSupportedLocales();if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) {return requestLocale;}Locale supportedLocale = findSupportedLocale(request, supportedLocales);if (supportedLocale != null) {return supportedLocale;}return (defaultLocale != null ? defaultLocale : requestLocale);}

其实现也是非常简单,就不照着解释了。

1.3 AbstractLocaleResolver

@Nullableprivate Locale defaultLocale;/ * **设置默认语言环境,如果找不到其他语言环境,该解析器将返回该语言环境。* /public void setDefaultLocale(@Nullable Locale defaultLocale) {this.defaultLocale = defaultLocale;}/ * **返回该解析器应该返回的默认语言环境(如果有的话)。* /@Nullableprotected Locale getDefaultLocale() {return this.defaultLocale;}

这个类只是添加了一个defaultLocale。

1.4 AbstractLocaleContextResolver

这个类就很完善了,它里面做了两件事:①添加默认时区的属性defaultTimeZone,以及其getter/setter方法;②提供LocaleResolver接口的默认实现,实现方法是使用LocaleContext。

public abstract class AbstractLocaleContextResolver extends AbstractLocaleResolver implements LocaleContextResolver {@Nullableprivate TimeZone defaultTimeZone;/ * **设置默认时区,如果没有找到其他时区,该解析器将返回该时区。* /public void setDefaultTimeZone(@Nullable TimeZone defaultTimeZone) {this.defaultTimeZone = defaultTimeZone;}/ * **返回该解析器应该返回的默认时区(如果有的话)。* /@Nullablepublic TimeZone getDefaultTimeZone() {return this.defaultTimeZone;}@Overridepublic Locale resolveLocale(HttpServletRequest request) {Locale locale = resolveLocaleContext(request).getLocale();return (locale != null ? locale : request.getLocale());}@Overridepublic void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) {setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));}}

1.5 FixedLocaleResolver

public class FixedLocaleResolver extends AbstractLocaleContextResolver {/***创建默认FixedLocaleResolver,公开配置的默认值语言环境(或JVM默认的语言环境作为回退)。* @see # setDefaultLocale* @see # setDefaultTimeZone*/public FixedLocaleResolver() {setDefaultLocale(Locale.getDefault());}/ * **创建一个公开给定语言环境的FixedLocaleResolver。* @param locale要公开的locale* /public FixedLocaleResolver(Locale locale) {setDefaultLocale(locale);}/ * **创建一个FixedLocaleResolver,它公开给定的语言环境和时区。* @param locale要公开的locale* @param时区要暴露的时区* /public FixedLocaleResolver(Locale locale, TimeZone timeZone) {setDefaultLocale(locale);setDefaultTimeZone(timeZone);}@Overridepublic Locale resolveLocale(HttpServletRequest request) {Locale locale = getDefaultLocale();if (locale == null) {locale = Locale.getDefault();}return locale;}@Overridepublic LocaleContext resolveLocaleContext(HttpServletRequest request) {return new TimeZoneAwareLocaleContext() {@Override@Nullablepublic Locale getLocale() {return getDefaultLocale();}@Overridepublic TimeZone getTimeZone() {return getDefaultTimeZone();}};}@Overridepublic void setLocaleContext( HttpServletRequest request, @Nullable HttpServletResponse response,@Nullable LocaleContext localeContext) {throw new UnsupportedOperationException("Cannot change fixed locale - use a different locale resolution strategy");}
}

FixedLocaleResolver继承自AbstractLocaleContextResolver,也就具有了defaultLocale和defaultTimeZone属性。
FixedLocaleResolver在构造方法里对这两个属性进行了设置,它一共有三个构造方法,其中,如果有Locale、TimeZone参数则将其设置为默认值,无参数的构造方法会使用Locale.getDefault()作为默认Locale,这时一般为Java虚拟机所在环境的Locale,也可以人为修改。
resolveLocaleContext方法返回新建的TimeZoneAwareLocaleContext匿名类,其中getLocale和getTimeZone使用了defaultLocale和defaultTimeZone。

1.6 SessionLocaleResolver

SessionLocaleResolver和FixedLocaleResolver的实现差不多,只不过把从默认值获取变成从Session中获取,不过如果获取不到还会使用默认值。

	@Overridepublic Locale resolveLocale(HttpServletRequest request) {Locale locale = (Locale) WebUtils.getSessionAttribute(request, this.localeAttributeName);if (locale == null) {locale = determineDefaultLocale(request);}return locale;}
@Overridepublic LocaleContext resolveLocaleContext(final HttpServletRequest request) {return new TimeZoneAwareLocaleContext() {@Overridepublic Locale getLocale() {Locale locale = (Locale) WebUtils.getSessionAttribute(request, localeAttributeName);if (locale == null) {locale = determineDefaultLocale(request);}return locale;}@Override@Nullablepublic TimeZone getTimeZone() {TimeZone timeZone = (TimeZone) WebUtils.getSessionAttribute(request, timeZoneAttributeName);if (timeZone == null) {timeZone = determineDefaultTimeZone(request);}return timeZone;}};}

其中解析TimeZone的过程和解析Locale的过程一样,先从Session中获取,如果获取不到则使用默认值。

2. ThemeResolver

ThemeResolver用于根据request解析Theme

2.1 类继承关系图


其实和Locale差不多。

public interface ThemeResolver {/***通过给定的请求解析当前的主题名称。*应该在任何情况下返回默认的主题作为回退。* @param请求用于解析的请求* @返回当前主题名称*/String resolveThemeName(HttpServletRequest request);/***设置当前主题的名称为给定的。用于修改主题名称的请求* @param响应用于修改主题名称* @param themeName新主题名称({@code null}或空重置)* @抛出UnsupportedOperationException如果ThemeResolver实现*不支持动态更改主题*/void setThemeName(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName);}

就不多赘述了。

3. FlashMapManager

FlashMapManager用来管理FlashMap,FlashMap用于在redirect时传递参数


看明白没?这是最不复杂的类了。接口,抽象类,类。
抽象类采用模板模式定义了整体流程,具体实现类SessionFlashMapManager通过模板方法提供了具体操作FlashMap的功能。

public interface FlashMapManager {/***查找先前保存的与当前请求匹配的FlashMap*请求,删除它从底层存储,也删除其他*过期的FlashMap实例。相比之下,该方法在每个请求开始时被调用*到{@link #saveOutputFlashMap},只有在存在时才调用*要保存的flash属性-例如,在重定向之前。* @param请求当前请求* @param响应当前响应* @return匹配当前请求的FlashMap或{@code null}*/@NullableFlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response);/***保存给定的FlashMap,在一些底层存储并设置开始*其有效期。*注意:在重定向前按顺序调用此方法*允许在HTTP会话或响应中保存FlashMap* cookie在响应提交之前。* @param flashMap要保存的flashMap* @param请求当前请求* @param响应当前响应*/void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response);
}

有两点需要注意:
第一,实际在Session中保存的FlashMap是List<FlashMap>类型,也就是说,一个Session可以保存多个FlashMap,一个FlashMap保存着一套Redirect转发所传递的参数;
第二,FlashMap继承自HashMap,它除了具有HashMap的功能和设置有效期,还可以保存Redirect后的目标路径和通过url传递的参数,这两项内容主要用来从Session保存的多个FlashMap中查找当前请求的FlashMap。

3.1 AbstractFlashMapManager

	@Overridepublic final void saveOutputFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {if (CollectionUtils.isEmpty(flashMap)) {return;}//首先对flashMap中转发地址和参数进行编码,这里的request主要用来获取当前编码方式String path = decodeAndNormalizePath(flashMap.getTargetRequestPath(), request);flashMap.setTargetRequestPath(path);//设置有效期flashMap.startExpirationPeriod(getFlashMapTimeout());//加锁Object mutex = getFlashMapsMutex(request);if (mutex != null) {synchronized (mutex) {//没有获取到就新建一个List<FlashMap> allFlashMaps = retrieveFlashMaps(request);allFlashMaps = (allFlashMaps != null ? allFlashMaps : new CopyOnWriteArrayList<>());allFlashMaps.add(flashMap);updateFlashMaps(allFlashMaps, request, response);}}else {List<FlashMap> allFlashMaps = retrieveFlashMaps(request);allFlashMaps = (allFlashMaps != null ? allFlashMaps : new LinkedList<>());allFlashMaps.add(flashMap);updateFlashMaps(allFlashMaps, request, response);}}

编码格式使用当前request获取;其次设置有效期,有效期可以通过flashMapTimeout参数配置,默认值是180秒;然后将flashMap添加到整体的List<FlashMap>中并更新。

其中,retrieveFlashMaps、getFlashMapsMutex和updateFlashMaps方法都在子类SessionFlashMapManager中实现。

接下来看retrieveAndUpdate方法:

@Override@Nullablepublic final FlashMap retrieveAndUpdate(HttpServletRequest request, HttpServletResponse response) {List<FlashMap> allFlashMaps = retrieveFlashMaps(request);if (CollectionUtils.isEmpty(allFlashMaps)) {return null;}List<FlashMap> mapsToRemove = getExpiredFlashMaps(allFlashMaps);FlashMap match = getMatchingFlashMap(allFlashMaps, request);if (match != null) {mapsToRemove.add(match);}if (!mapsToRemove.isEmpty()) {Object mutex = getFlashMapsMutex(request);if (mutex != null) {synchronized (mutex) {allFlashMaps = retrieveFlashMaps(request);if (allFlashMaps != null) {allFlashMaps.removeAll(mapsToRemove);updateFlashMaps(allFlashMaps, request, response);}}}else {allFlashMaps.removeAll(mapsToRemove);updateFlashMaps(allFlashMaps, request, response);}}return match;}

首先使用retrieveFlashMaps模板方法获取List<FlashMap>;然后检查其中已经过期的FlashMap并保存,检查方法通过保存时设置的过期时间进行判断;接着调用getMatchingFlashMap方法从获取的List<FlashMap>中找出和当前request相匹配的FlashMap;最后将过期的和与当前请求相匹配的FlashMap从List<FlashMap>中删除并更新到Session中,将与当前request匹配的返回。

isFlashMapForRequest()方法如下:

	/***给定的FlashMap是否与当前请求匹配。*使用FlashMap中保存的预期请求路径和查询参数。*/protected boolean isFlashMapForRequest(FlashMap flashMap, HttpServletRequest request) {String expectedPath = flashMap.getTargetRequestPath();if (expectedPath != null) {String requestUri = getUrlPathHelper().getOriginatingRequestUri(request);if (!requestUri.equals(expectedPath) && !requestUri.equals(expectedPath + "/")) {return false;}}MultiValueMap<String, String> actualParams = getOriginatingRequestParams(request);MultiValueMap<String, String> expectedParams = flashMap.getTargetRequestParams();for (Map.Entry<String, List<String>> entry : expectedParams.entrySet()) {List<String> actualValues = actualParams.get(entry.getKey());if (actualValues == null) {return false;}for (String expectedValue : entry.getValue()) {if (!actualValues.contains(expectedValue)) {return false;}}}return true;}

这里的检查方法就是通过FlashMap中保存的目标地址和url参数与Request进行比较的,如果保存的目标地址和Request的url以及url+“/”都不一样则返回false,如果FlashMap中保存的url参数在Request中没有也返回false,如果这两项都合格则返回true。

3.2 SessionFlashMapManager

public class SessionFlashMapManager extends AbstractFlashMapManager {private static final String FLASH_MAPS_SESSION_ATTRIBUTE = SessionFlashMapManager.class.getName() + ".FLASH_MAPS";/***从HTTP会话中检索保存的FlashMap实例(如果有的话)。*/@Override@SuppressWarnings("unchecked")@Nullableprotected List<FlashMap> retrieveFlashMaps(HttpServletRequest request) {HttpSession session = request.getSession(false);return (session != null ? (List<FlashMap>) session.getAttribute(FLASH_MAPS_SESSION_ATTRIBUTE) : null);}/***在HTTP会话中保存给定的FlashMap实例。*/@Overrideprotected void updateFlashMaps(List<FlashMap> flashMaps, HttpServletRequest request, HttpServletResponse response) {WebUtils.setSessionAttribute(request, FLASH_MAPS_SESSION_ATTRIBUTE, (!flashMaps.isEmpty() ? flashMaps : null));}/***公开最好的可用会话互斥量。* @see org.springframework.web.util.WebUtils # getSessionMutex* @see org.springframework.web.util.HttpSessionMutexListener*/@Overrideprotected Object getFlashMapsMutex(HttpServletRequest request) {return WebUtils.getSessionMutex(request.getSession());}
}

更多推荐

java源码

本文发布于:2023-06-17 04:19:28,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/753651.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:源码   java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!