grails基本框架

使用grails开发已经有一段时间,中间遇到不少问题,由于grails本身提供的文档有点简单,某些功能实现还须参考其源码。在分析过程中逐渐了解其运行构架,稍做介绍。
grails框架是根据约定优于配置这条原则搭建,MVC部分是基于Spring MVC,持久层是基于hibernate。查看打包后的文件目录,找到WEB-INF/web.xml,可以发现核心的几个配置


<filter>
<filter-name>urlMapping</filter-name>
<filter-class>org.codehaus.groovy.grails.web.mapping.filter.UrlMappingsFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>urlMapping</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


<servlet>
<servlet-name>grails</servlet-name>
<servlet-class>org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>grails</servlet-name>
<url-pattern>*.dispatch</url-pattern>
</servlet-mapping>

urlMapping filter的作用是根据request uri查找到相应的grails controller的处理路径,然后forward到/grails/controller/action.dispatch,这样就
把请求转到了GrailsDispatcherServlet来处理,调用controller的各种拦截器,处理逻辑,并返回view。
在看看WEB-INF目录下还有两个重要的配置文件,applicationContext.xml和grails.xml
applicationContext.xml,加载grails各种工件(Artefact)和插件(plugin)

<bean id="grailsApplication" class="org.codehaus.groovy.grails.commons.GrailsApplicationFactoryBean">
<description>Grails application factory bean</description>
<property name="grailsDescriptor" value="/WEB-INF/grails.xml" />
<property name="grailsResourceLoader" ref="grailsResourceLoader" />
</bean>

grails.xml:又grails命令生成,包含grails工件和插件

<grails>
<resources>
<resource>ApplicationFilters</resource>
<resource>BootStrap</resource>
<resource>Config</resource>
<resource>DataSource</resource>
<resource>resources</resource>
<resource>UrlMappings</resource>
<resource>MagazineBusinessController</resource>
<resource>BusinessSmsLog</resource>
<resource>MonthBusinessChargeJob</resource>
<resource>SmsChargeService</resource>
<resource>MagazineBusinessService</resource>
<resource>XMLCodec</resource>
<resource>DefaultQuartzConfig</resource>
<resource>QuartzBootStrap</resource>
<resource>JobManagerController</resource>
<resource>JobManagerService</resource>
</resources>
<plugins>
<plugin>QuartzGrailsPlugin</plugin>
<plugin>RemotingGrailsPlugin</plugin>
</plugins>

grails中包含以下几种工件
DomainClass Artefact(Domain模型工件),Controller Artefact(Controller工件),Service Artefact(Service工件),TagLib Artefact(工件),Bootstrap ArtefactHandler(初始化启动工件),
Codec Artefact(Codec工件),UrlMappings Artefact(UrlMapping工件),Filters Artefact(过滤拦截工件)

GrailsApplicationFactoryBean的代码

public void afterPropertiesSet() throws Exception {
if(descriptor != null && descriptor.exists()) {
// Enforce UTF-8 on source code for reloads
CompilerConfiguration config = CompilerConfiguration.DEFAULT;
config.setSourceEncoding("UTF-8");

GroovyClassLoader classLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config);
List classes = new ArrayList();
SAXReader reader = new SAXReader();
InputStream inputStream = null;
try {
inputStream = descriptor.getInputStream();
Document doc = reader.read(inputStream);
List grailsClasses = doc.selectNodes("/grails/resources/resource");
for (Iterator i = grailsClasses.iterator(); i.hasNext();) {
Node node = (Node) i.next();
try {
classes.add(classLoader.loadClass(node.getText()));
} catch (ClassNotFoundException e) {
LOG.warn("Class with name ["+node.getText()+"] was not found, and hence not loaded. Possible empty class or script definition?");
}
}
} finally {
if(inputStream!=null)
inputStream.close();
}
Class[] loadedClasses = (Class[])classes.toArray(new Class[classes.size()]);
this.grailsApplication = new DefaultGrailsApplication(loadedClasses, classLoader);
}
else {
Assert.notNull(resourceLoader, "Property [resourceLoader] must be set!");

this.grailsApplication = new DefaultGrailsApplication(this.resourceLoader);
}

ApplicationHolder.setApplication(this.grailsApplication);
}

GrailsApplicationFactoryBean已经把grails.xml中所有的grails工件类加载了进来,保存在DefaultGrailsApplication中
DefaultGrailsApplication的代码

public DefaultGrailsApplication(final Class[] classes, GroovyClassLoader classLoader) {
...
this.allClasses = classes;
this.cl = classLoader;
this.applicationMeta = loadMetadata();//读取WEB-INF/classes下application.properties配置
}

private void initArtefactHandlers() {
registerArtefactHandler(new DomainClassArtefactHandler());
registerArtefactHandler(new ControllerArtefactHandler());
registerArtefactHandler(new ServiceArtefactHandler());
registerArtefactHandler(new TagLibArtefactHandler());
registerArtefactHandler(new BootstrapArtefactHandler());
registerArtefactHandler(new CodecArtefactHandler());
registerArtefactHandler(new UrlMappingsArtefactHandler());

// Cache the list as an array
this.artefactHandlers = ((ArtefactHandler[]) this.artefactHandlersByName.values().toArray(
new ArtefactHandler[artefactHandlersByName.size()]));
}

public boolean isArtefact(Class theClazz) {
String className = theClazz.getName();
for (Iterator i = allArtefactClasses.iterator(); i.hasNext();) {
Class artefactClass = (Class) i.next();
if (className.equals(artefactClass.getName())) {
return true;
}
}
return false;
}

就此分析GrailsApplication接口代表是应用中所有的工件,而ArtefactHandler是工件接口

public interface GrailsApplication extends ApplicationContextAware {

public Class[] getAllClasses();
public Class[] getAllArtefacts();
public boolean isArtefact(Class theClazz);
}

public interface ArtefactHandler {
boolean isArtefact(Class aClass);
GrailsClass newArtefactClass(Class artefactClass);
}


待续,后面准备就UrlMapping机制看看grails是如何处理工件再做分析
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值