org.nutz.mvc.impl.NutLoading Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nutz Show documentation
Show all versions of nutz Show documentation
Nutz, which is a collections of lightweight frameworks, each of them can be used independently
package org.nutz.mvc.impl;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import org.nutz.Nutz;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.Ioc2;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.nutz.lang.Encoding;
import org.nutz.lang.Lang;
import org.nutz.lang.Mirror;
import org.nutz.lang.Stopwatch;
import org.nutz.lang.Strings;
import org.nutz.lang.util.Context;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.ActionChainMaker;
import org.nutz.mvc.ActionInfo;
import org.nutz.mvc.EntryDeterminer;
import org.nutz.mvc.Loading;
import org.nutz.mvc.LoadingException;
import org.nutz.mvc.MessageLoader;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.NutConfig;
import org.nutz.mvc.SessionProvider;
import org.nutz.mvc.Setup;
import org.nutz.mvc.UrlMapping;
import org.nutz.mvc.ViewMaker;
import org.nutz.mvc.annotation.ChainBy;
import org.nutz.mvc.annotation.Determiner;
import org.nutz.mvc.annotation.IocBy;
import org.nutz.mvc.annotation.Localization;
import org.nutz.mvc.annotation.SessionBy;
import org.nutz.mvc.annotation.SetupBy;
import org.nutz.mvc.annotation.UrlMappingBy;
import org.nutz.mvc.annotation.Views;
import org.nutz.mvc.view.DefaultViewMaker;
public class NutLoading implements Loading {
private static final Log log = Logs.get();
public UrlMapping load(NutConfig config) {
if (log.isInfoEnabled()) {
log.infof("Nutz Version : %s ", Nutz.version());
log.infof("Nutz.Mvc[%s] is initializing ...", config.getAppName());
}
if (log.isDebugEnabled()) {
Properties sys = System.getProperties();
log.debug("Web Container Information:");
log.debugf(" - Default Charset : %s", Encoding.defaultEncoding());
log.debugf(" - Current . path : %s", new File(".").getAbsolutePath());
log.debugf(" - Java Version : %s", sys.get("java.version"));
log.debugf(" - File separator : %s", sys.get("file.separator"));
log.debugf(" - Timezone : %s", sys.get("user.timezone"));
log.debugf(" - OS : %s %s", sys.get("os.name"), sys.get("os.arch"));
log.debugf(" - ServerInfo : %s", config.getServletContext().getServerInfo());
log.debugf(" - Servlet API : %d.%d",
config.getServletContext().getMajorVersion(),
config.getServletContext().getMinorVersion());
if (config.getServletContext().getMajorVersion() > 2
|| config.getServletContext().getMinorVersion() > 4)
log.debugf(" - ContextPath : %s", config.getServletContext().getContextPath());
log.debugf(" - context.tempdir : %s", config.getAttribute("javax.servlet.context.tempdir"));
log.debugf(" - MainModule : %s", config.getMainModule().getName());
}
/*
* 准备返回值
*/
UrlMapping mapping;
Ioc ioc = null;
/*
* 准备计时
*/
Stopwatch sw = Stopwatch.begin();
try {
/*
* 检查主模块,调用本函数前,已经确保过有声明 MainModule 了
*/
Class> mainModule = config.getMainModule();
/*
* 创建上下文
*/
createContext(config);
/*
* 检查 Ioc 容器并创建和保存它
*/
ioc = createIoc(config, mainModule);
/*
* 组装UrlMapping
*/
mapping = evalUrlMapping(config, mainModule, ioc);
/*
* 分析本地化字符串
*/
evalLocalization(config, mainModule);
// 初始化SessionProvider
createSessionProvider(config, mainModule);
/*
* 执行用户自定义 Setup
*/
evalSetup(config, mainModule);
}
catch (Exception e) {
if (log.isErrorEnabled())
log.error("Error happend during start serivce!", e);
if (ioc != null) {
log.error("try to depose ioc");
try {
ioc.depose();
}
catch (Throwable e2) {
log.error("error when depose ioc", e);
}
}
throw Lang.wrapThrow(e, LoadingException.class);
}
// ~ Done ^_^
sw.stop();
if (log.isInfoEnabled())
log.infof("Nutz.Mvc[%s] is up in %sms", config.getAppName(), sw.getDuration());
return mapping;
}
protected UrlMapping evalUrlMapping(NutConfig config, Class> mainModule, Ioc ioc)
throws Exception {
/*
* @ TODO 个人建议可以将这个方法所涉及的内容转换到Loadings类或相应的组装类中,
* 以便将本类加以隔离,使本的职责仅限于MVC整体的初使化,而不再负责UrlMapping的加载
*/
/*
* 准备 UrlMapping
*/
UrlMapping mapping = createUrlMapping(config);
if (log.isInfoEnabled())
log.infof("Build URL mapping by %s ...", mapping.getClass().getName());
/*
* 创建视图工厂
*/
ViewMaker[] makers = createViewMakers(mainModule, ioc);
/*
* 创建动作链工厂
*/
ActionChainMaker maker = createChainMaker(config, mainModule);
/*
* 创建主模块的配置信息
*/
ActionInfo mainInfo = Loadings.createInfo(mainModule);
// fix issue #1337
Determiner ann = mainModule.getAnnotation(Determiner.class);
EntryDeterminer determiner = null == ann ? new NutEntryDeterminer() : Loadings.evalObj(config, ann.value(), ann.args());
/*
* 准备要加载的模块列表
*/
// TODO 为什么用Set呢? 用List不是更快吗?
Set> modules = getModuleClasses(ioc, mainModule, determiner);
if (modules.isEmpty()) {
if (log.isWarnEnabled())
log.warn("None module classes found!!!");
}
int atMethods = 0;
/*
* 分析所有的子模块
*/
if (log.isDebugEnabled())
log.debugf("Use %s as EntryMethodDeterminer", determiner.getClass().getName());
for (Class> module : modules) {
ActionInfo moduleInfo = Loadings.createInfo(module).mergeWith(mainInfo, true);
for (Method method : module.getMethods()) {
if (!determiner.isEntry(module, method))
continue;
// 增加到映射中
ActionInfo info = Loadings.createInfo(method).mergeWith(moduleInfo, false);
info.setViewMakers(makers);
mapping.add(maker, info, config);
atMethods++;
}
// 记录pathMap
if (null != moduleInfo.getPathMap()) {
for (Entry en : moduleInfo.getPathMap().entrySet()) {
config.getAtMap().add(en.getKey(), en.getValue());
}
}
}
if (atMethods == 0) {
if (log.isWarnEnabled())
log.warn("None @At found in any modules class!!");
} else {
log.infof("Found %d module methods", atMethods);
}
config.setUrlMapping(mapping);
config.setActionChainMaker(maker);
config.setViewMakers(makers);
return mapping;
}
protected void createContext(NutConfig config) {
// 构建一个上下文对象,方便子类获取更多的环境信息
// 同时,所有 Filter 和 Adaptor 都可以用 ${app.root} 来填充自己
Context context = Lang.context();
String appRoot = config.getAppRoot();
context.set("app.root", appRoot);
if (log.isDebugEnabled()) {
log.debugf(">> app.root = %s", appRoot);
}
// 载入环境变量
for (Entry entry : System.getenv().entrySet())
context.set("env." + entry.getKey(), entry.getValue());
// 载入系统变量
for (Entry