Struts2の全体的な実装プロセス
コアフィルタ初期
web.xmlの構成フィルタコアStrutsPrepareAndExecuteFilter、負荷のweb.xmlフィルタ構成サーブレットコンテナが起動し、初期化フィルタを実行するための方法、およびオブジェクト(フィルタチュートリアル自身の知識をインスタンス化してください)。
コアは、initメソッドであるディスパッチャ= init.initDispatcher(設定)
に進みます。
public Dispatcher initDispatcher( HostConfig filterConfig ) { Dispatcher dispatcher = createDispatcher(filterConfig); dispatcher.init(); return dispatcher; }
入射dispatcher.initを();
次のコードブロックを参照してください。
init_DefaultProperties(); // [1]
init_TraditionalXmlConfigurations(); // [2]
init_LegacyStrutsProperties(); // [3]
init_CustomConfigurationProviders(); // [5]
init_FilterInitParameters() ; // [6]
init_AliasStandardObjects() ; // [7]
ここでマークも、Struts2のフレームワークを初期化するために、設定ファイルをロードするStruts2のためにロードされたコンフィギュレーションファイルになります。
1、init_DefaultProperties(); // [
1] ロードORG /アパッチ/ Struts2の/ default.propertiesファイル
のソースコードを見るためにクリック。
private void init_DefaultProperties() { configurationManager.addContainerProvider(new DefaultPropertiesProvider()); }
入力する]をクリックして続行します。
public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { try { PropertiesSettings defaultSettings = new PropertiesSettings("org/apache/struts2/default"); loadSettings(props, defaultSettings); } catch (Exception e) { throw new ConfigurationException("Could not find or error in org/apache/struts2/default.properties", e); } }
( "ORG / apacheの/ Struts2の/デフォルト")を入力する新しいPropertiesSettingsをクリックして続行します。
public PropertiesSettings(String name) { URL settingsUrl = ClassLoaderUtil.getResource(name + ".properties", getClass()); 略...... }
ここでは、へのパスを見つけることは非常に明白されている組織/ apacheの/ Struts2の/ default.propertiesファイルを。
設定ファイルは、実際にビットの定数です。ビューへの無料。
2.init_TraditionalXmlConfigurations()。// [2]
加载
支柱-default.xmlの
支柱-plugin.xmlの
struts.xml
ソースコードを表示します。
private void init_TraditionalXmlConfigurations() {
String configPaths = initParams.get("config");
if (configPaths == null) {
configPaths = DEFAULT_CONFIGURATION_PATHS;
}
String[] files = configPaths.split("\\s*[,]\\s*");
for (String file : files) {
if (file.endsWith(".xml")) {
if ("xwork.xml".equals(file)) {
configurationManager.addContainerProvider(createXmlConfigurationProvider(file, false));
} else {
configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));
}
} else {
throw new IllegalArgumentException("Invalid configuration file name");
}
}
}
どこ:DEFAULT_CONFIGURATION_PATHSは、次のように定義されます
private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";
ここでは、この文がロードされた設定ファイルであることは明らかである:
Strutsの-default.xmlの
Strutsの-plugin.xmlの
struts.xml
- ストラット-default.xmlの
コアパッケージのStruts2のファイル。
- ストラット-plugin.xmlの
Struts2のパッケージプラグイン、あなたはStruts2の複数のプラグインをカスタマイズすることができ、各プラグインのjarパッケージがストラット-plugin.xmlの設定ファイルを持っています。
- struts.xml
リソースディレクトリに格納されているユーザー定義の構成ファイルに。
3.init_LegacyStrutsProperties(); // [3]
のカスタムファイルはJAR内部struts2.properties定義された一定のカバレッジStruts2のコアの値をカスタマイズするために使用することができるロードstruts2.propertoes。
ソースコードを見るためにクリック
private void init_LegacyStrutsProperties() {
configurationManager.addContainerProvider(new PropertiesConfigurationProvider());
}
入力を続行:
public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
final DefaultSettings settings = new DefaultSettings();
loadSettings(props, settings);
}
続行:
public DefaultSettings() {
ArrayList<Settings> list = new ArrayList<Settings>();
// stuts.properties, default.properties
try {
list.add(new PropertiesSettings("struts"));
} catch (Exception e) {
LOG.warn("DefaultSettings: Could not find or error in struts.properties", e);
}
略.....
}
新しいPropertiesSettings(「ストラット」)を入力し、あなたが見ることができます:
URL settingsUrl = ClassLoaderUtil.getResource(name + ".properties", getClass());
リソースディレクトリにstruts2.properties設定ファイルを探しています。
4、init_CustomConfigurationProviders(); // [
5] ユーザ定義の構成は、実質的に詳細に展開していない、アクセス権を持っていません。
5、init_FilterInitParameters(); // [
6] ロードweb.xmlファイル。
これは、ここで注意しなければならない:
web.xmlファイルは、ブート時のサーブレットコンテナにロードされ、そして、そのような荷重は、フレームワークStruts2のStruts2の独自のタグを参照するフィルタの初期化などの他の操作は、web.xmlのファイルの解析を定義しました。
具体的な原理は不明です。
6、init_AliasStandardObjects(); // [
7] のロードBean構成。
以下のコード(自己検査の一部のみの除去):
private void init_AliasStandardObjects() {
configurationManager.addContainerProvider(new DefaultBeanSelectionProvider());
}
点击进入:
public void register(ContainerBuilder builder, LocatableProperties props) {
alias(ObjectFactory.class, StrutsConstants.STRUTS_OBJECTFACTORY, builder, props);
略...
/** Checker is used mostly in interceptors, so there be one instance of checker per interceptor with Scope.DEFAULT **/
alias(ExcludedPatternsChecker.class, StrutsConstants.STRUTS_EXCLUDED_PATTERNS_CHECKER, builder, props, Scope.DEFAULT);
alias(AcceptedPatternsChecker.class, StrutsConstants.STRUTS_ACCEPTED_PATTERNS_CHECKER, builder, props, Scope.DEFAULT);
switchDevMode(props);
// Convert Struts properties into XWork properties
convertIfExist(props, StrutsConstants.STRUTS_LOG_MISSING_PROPERTIES, XWorkConstants.LOG_MISSING_PROPERTIES);
略...
LocalizedTextUtil.addDefaultResourceBundle("org/apache/struts2/struts-messages");
loadCustomResourceBundles(props);
}
ロード順に、Struts2のフレームワークの構成ファイルを要約すると:
- コアパッケージのdefault.properties
- コアパッケージ内のstruts-default.xmlの
- プラグインパッケージ内のstruts-plugin.xmlの
- struts.xmlカスタムリソースディレクトリの下に
- struts.propertiesカスタムリソースディレクトリの下に
- web.xmlの
第二に、インターセプタ
Struts2のインターセプタは、アクションまたはアクション、またはフィールドの後にアクセスする方法の前の実施形態を傍受し、プラグイン可能なStruts2のインターセプタです、インターセプターは、AOPの実装です。
出典分析:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
prepare.setEncodingAndLocale(request, response);
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request, response, true);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
execute.executeAction(request, response, mapping);
}
}
} finally {
prepare.cleanupRequest(request);
}
}
execute.executeAction方法を入力します。
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping)
throws ServletException {
Map<String, Object> extraContext = createContextMap(request, response, mapping);
// If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
boolean nullStack = stack == null;
if (nullStack) {
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
stack = ctx.getValueStack();
}
}
if (stack != null) {
extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
}
String timerKey = "Handling request from Dispatcher";
try {
UtilTimerStack.push(timerKey);
String namespace = mapping.getNamespace();
String name = mapping.getName();
String method = mapping.getMethod();
ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
// if the ActionMapping says to go straight to a result, do it!
if (mapping.getResult() != null) {
Result result = mapping.getResult();
result.execute(proxy.getInvocation());
} else {
proxy.execute();
}
// If there was a previous value stack then set it back onto the request
if (!nullStack) {
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
}
} catch (ConfigurationException e) {
logConfigurationException(request, e);
sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e);
} catch (Exception e) {
if (handleException || devMode) {
sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
} else {
throw new ServletException(e);
}
} finally {
UtilTimerStack.pop(timerKey);
}
}
ここでは、アクションは、プロキシオブジェクトを作成した見ることができます。内部ビューにプロキシオブジェクトを作成します。
public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
DefaultActionProxy proxy = new DefaultActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
container.inject(proxy);
proxy.prepare();
return proxy;
}
方法を準備するために進み、その後のinitメソッドを入力します。
public void init(ActionProxy proxy) {
this.proxy = proxy;
Map<String, Object> contextMap = createContextMap();
// Setting this so that other classes, like object factories, can use the ActionProxy and other
// contextual information to operate
ActionContext actionContext = ActionContext.getContext();
if (actionContext != null) {
actionContext.setActionInvocation(this);
}
createAction(contextMap);
if (pushAction) {
stack.push(action);
contextMap.put("action", action);
}
invocationContext = new ActionContext(contextMap);
invocationContext.setName(proxy.getActionName());
// get a new List so we don't get problems with the iterator if someone changes the list
List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());
interceptors = interceptorList.iterator();
}
ここではインターセプタのセットを取得し、イテレータとして返すために、反復子は、ここで迎撃文書、18の合計で定義されたストラット-default.xmlのデフォルトのセットです。
プロキシオブジェクトを生成した後、次のように、メソッドを実行し続けます。
public String execute() throws Exception {
ActionContext nestedContext = ActionContext.getContext();
ActionContext.setContext(invocation.getInvocationContext());
String retCode = null;
String profileKey = "execute: ";
try {
UtilTimerStack.push(profileKey);
retCode = invocation.invoke();
} finally {
if (cleanupContext) {
ActionContext.setContext(nestedContext);
}
UtilTimerStack.pop(profileKey);
}
return retCode;
}
次のようにここでインターセプタの実装のコアは、呼び出しメソッドを入力すること、です。
public String invoke() throws Exception {
String profileKey = "invoke: ";
try {
UtilTimerStack.push(profileKey);
if (executed) {
throw new IllegalStateException("Action has already executed");
}
if (interceptors.hasNext()) {
final InterceptorMapping interceptor = interceptors.next();
String interceptorMsg = "interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
finally {
UtilTimerStack.pop(interceptorMsg);
}
} else {
resultCode = invokeActionOnly();
}
略.....
}
インターセプト法は、次のように簡単に、ExceptionMappingInterceptor(18のインターセプタのデフォルトの1)として、ビューにブロッカーを見つけることができ、実際に傍受を実行することです。
public String intercept(ActionInvocation invocation) throws Exception {
String result;
try {
result = invocation.invoke();
} catch (Exception e) {
if (isLogEnabled()) {
handleLogging(e);
}
List<ExceptionMappingConfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
ExceptionMappingConfig mappingConfig = this.findMappingFromExceptions(exceptionMappings, e);
if (mappingConfig != null && mappingConfig.getResult()!=null) {
Map parameterMap = mappingConfig.getParams();
// create a mutable HashMap since some interceptors will remove parameters, and parameterMap is immutable
invocation.getInvocationContext().setParameters(new HashMap<String, Object>(parameterMap));
result = mappingConfig.getResult();
publishException(invocation, new ExceptionHolder(e));
} else {
throw e;
}
}
return result;
}
この方法は、別のメソッドを呼び出しインターセプトするインターセプターの中に発見、前面に戻ります(interceptors.hasNext())判決、18のインターセプタが全て実行されないことを示すデフォルトが、次の要素が存在する場合、反復子、そう再帰的に繰り返します。
ルーチンとスプリングAOPインターセプタは非常に類似している技術は、動的プロキシの使用、特定の処理のための要求です。Struts2のインターセプタはまた、特定のメソッドの実装のためにインターセプトするための手段をカスタマイズし、ターゲットの実行の反射を利用する方法、および動的に変更に実行前と後に、特定の物事を行うか、その機能を強化することができます。