Jforum启动

启动:
net.jforum.JForum.java是核心Servlet,启动方法:
public class JForum extends JForumBaseServlet {
public void init(ServletConfig config) throws ServletException{
//调用父类JForumBaseServlet的init方法初始化
super.init(config);
super.startApplication();
//根据配置文件实例化DBConnection的具体类,并初始化数据源
// Start database
isDatabaseUp = ForumStartup.startDatabase();

try {
Connection conn = DBConnection.getImplementation().getConnection();
conn.setAutoCommit(!SystemGlobals.getBoolValue(ConfigKeys.DATABASE_USE_TRANSACTIONS));
//解决MYSQL的问题,确定MYSQL版本,根据版本调整具体使用的JFORUM的MYSQL数据库驱动
// Try to fix some MySQL problems
MySQLVersionWorkarounder dw = new MySQLVersionWorkarounder();
dw.handleWorkarounds(conn);

//每个线程一个JForumExecutionContext
// Continues loading the forum
JForumExecutionContext ex = JForumExecutionContext.get();
ex.setConnection(conn);
JForumExecutionContext.set(ex);

//初始化缓存
//将论坛目录,论坛,最多在线用户数,用户数量,最近注册用户等信息放到缓存中
// Init general forum stuff
ForumStartup.startForumRepository();
RankingRepository.loadRanks();
SmiliesRepository.loadSmilies();
BanlistRepository.loadBanlist();
}
catch (Throwable e) {
e.printStackTrace();
throw new ForumStartupException("Error while starting jforum", e);
}
finally {
//启动完毕释放资源
JForumExecutionContext.finish();
}
}
}

public class JForumBaseServlet extends HttpServlet
{
private static Logger logger = Logger.getLogger(JForumBaseServlet.class);

protected boolean debug;

protected void startApplication()
{
try {
//加载通用的SQL语句
SystemGlobals.loadQueries(SystemGlobals.getValue(ConfigKeys.SQL_QUERIES_GENERIC));
//加载对于某一种数据库的驱动(专属某一库的SQL)相同的key将覆盖通用SQL中的值(properties.put)
SystemGlobals.loadQueries(SystemGlobals.getValue(ConfigKeys.SQL_QUERIES_DRIVER));
//获取quartz配置文件名
String filename = SystemGlobals.getValue(ConfigKeys.QUARTZ_CONFIG);
//根据quartz配置文件路径加载quartz配置
SystemGlobals.loadAdditionalDefaults(filename);
//生成用户认证类(net.jforum.sso.LoginAuthenticator)放到全局map(SystemGlobals.objectProperties)中默认的实现类是:net.jforum.sso.DefaultLoginAuthenticator,不是SSO
ConfigLoader.createLoginAuthenticator();
// 加载net.jforum.dao.DataAccessDriver并初始化,具体的实现类在系统安装时生成的jforum-custom.conf文件中
ConfigLoader.loadDaoImplementation();
//监听文件修改(见下面对FileMonitor.java的分析)
ConfigLoader.listenForChanges();
//初始化SearchFacade,被代理给SearchManager具体实现类在SystemGlobals.properties中配置,默认实现是net.jforum.search.LuceneManager
ConfigLoader.startSearchIndexer();
//调度发送邮件
ConfigLoader.startSummaryJob();
}
catch (Exception e) {
throw new ForumStartupException("Error while starting JForum", e);
}
}

public void init(ServletConfig config) throws ServletException
{
super.init(config);

try {
String appPath = config.getServletContext().getRealPath("");
debug = "true".equals(config.getInitParameter("development"));
//初始化LOG4J
DOMConfigurator.configure(appPath + "/WEB-INF/log4j.xml");

logger.info("Starting JForum. Debug mode is " + debug);
//加载配置文件,在从配置文件中取值时遇到${}格式的会被当作变量进行扩展,与许多脚本语言类似
ConfigLoader.startSystemglobals(appPath);
//启动缓存引擎
ConfigLoader.startCacheEngine();
//配置freemarker引擎
// Configure the template engine
Configuration templateCfg = new Configuration();
templateCfg.setTemplateUpdateDelay(2);
templateCfg.setSetting("number_format", "#");
templateCfg.setSharedVariable("startupTime", new Long(new Date().getTime()));

//配置freemarker模板的加载目录
// Create the default template loader
String defaultPath = SystemGlobals.getApplicationPath() + "/templates";
FileTemplateLoader defaultLoader = new FileTemplateLoader(new File(defaultPath));

String extraTemplatePath = SystemGlobals.getValue(ConfigKeys.FREEMARKER_EXTRA_TEMPLATE_PATH);

if (StringUtils.isNotBlank(extraTemplatePath)) {
// An extra template path is configured, we need a MultiTemplateLoader
FileTemplateLoader extraLoader = new FileTemplateLoader(new File(extraTemplatePath));
TemplateLoader[] loaders = new TemplateLoader[] { extraLoader, defaultLoader };
MultiTemplateLoader multiLoader = new MultiTemplateLoader(loaders);
templateCfg.setTemplateLoader(multiLoader);
}
else {
// An extra template path is not configured, we only need the default loader
templateCfg.setTemplateLoader(defaultLoader);
}

ModulesRepository.init(SystemGlobals.getValue(ConfigKeys.CONFIG_DIR));

this.loadConfigStuff();

if (!this.debug) {
templateCfg.setTemplateUpdateDelay(3600);
}
//将模板的配置放到net.jforum.JForumExecutionContext
JForumExecutionContext.setTemplateConfig(templateCfg);
}
catch (Exception e) {
throw new ForumStartupException("Error while starting JForum", e);
}
}

protected void loadConfigStuff()
{
//加载urlPattern.properties文件
ConfigLoader.loadUrlPatterns();
//加载i18n文件
I18n.load();
//加载templatesMapping.properties文件,供freemarker使用
Tpl.load(SystemGlobals.getValue(ConfigKeys.TEMPLATES_MAPPING));

// BB Code
BBCodeRepository.setBBCollection(new BBCodeHandler().parse());
}
}

对文件的加载大体都在这个类里:net.jforum.ConfigLoader,分析一下文件修改的监听:
public class ConfigLoader 
{
public static void listenForChanges()
{
int fileChangesDelay = SystemGlobals.getIntValue(ConfigKeys.FILECHANGES_DELAY);

if (fileChangesDelay > 0) {
//这里用了单例和观察者模式,临听通用SQL语句配置文件的修改
// Queries
FileMonitor.getInstance().addFileChangeListener(new QueriesFileListener(),
SystemGlobals.getValue(ConfigKeys.SQL_QUERIES_GENERIC), fileChangesDelay);
//监听对某种数据库的SQL配置文件修改
FileMonitor.getInstance().addFileChangeListener(new QueriesFileListener(),
SystemGlobals.getValue(ConfigKeys.SQL_QUERIES_DRIVER), fileChangesDelay);
//监听SystemGlobals.properties的修改
// System Properties
FileMonitor.getInstance().addFileChangeListener(new SystemGlobalsListener(),
SystemGlobals.getValue(ConfigKeys.DEFAULT_CONFIG), fileChangesDelay);

ConfigLoader.listenInstallationConfig();
}
}
}

文件修改监听器net.jforum.util.FileMonitor:
public class FileMonitor
{
private static Logger logger = Logger.getLogger(FileMonitor.class);
private static final FileMonitor instance = new FileMonitor();
private Timer timer;
private Map timerEntries;

private FileMonitor() {
this.timerEntries = new HashMap();
this.timer = new Timer(true);
}

public static FileMonitor getInstance() {
return instance;
}


public void addFileChangeListener(FileChangeListener listener,
String filename, long period) {
this.removeFileChangeListener(filename);

logger.info("Watching " + filename);
//通过JDK的TimerTask实现
FileMonitorTask task = new FileMonitorTask(listener, filename);

this.timerEntries.put(filename, task);
//定时调度
this.timer.schedule(task, period, period);
}


public void removeFileChangeListener(String filename) {
FileMonitorTask task = (FileMonitorTask)this.timerEntries.remove(filename);

if (task != null) {
task.cancel();
}
}
//继承TimerTask
private static class FileMonitorTask extends TimerTask {
private FileChangeListener listener;
private String filename;
private File monitoredFile;
private long lastModified;

public FileMonitorTask(FileChangeListener listener, String filename) {
this.listener = listener;
this.filename = filename;

this.monitoredFile = new File(filename);
if (!this.monitoredFile.exists()) {
return;
}

this.lastModified = this.monitoredFile.lastModified();
}

public void run() {
long latestChange = this.monitoredFile.lastModified();
//判断是否修改
if (this.lastModified != latestChange) {
this.lastModified = latestChange;
//修改触发事件
this.listener.fileChanged(this.filename);
}
}
}
}
搜索:net.jforum.search.LuceneManager
public class LuceneManager implements SearchManager
{
private LuceneSearch search;
private LuceneSettings settings;
private LuceneIndexer indexer;

/**
* @see net.jforum.search.SearchManager#init()
*/
public void init()
{
try {
//分词器根据配置文件中的配置实例化具体的分词器,配置文件中默认分词器:org.apache.lucene.analysis.standard.StandardAnalyzer
Analyzer analyzer = (Analyzer)Class.forName(SystemGlobals.getValue(
ConfigKeys.LUCENE_ANALYZER)).newInstance();

this.settings = new LuceneSettings(analyzer);
//根据配置文件确定索引目录
this.settings.useFSDirectory(SystemGlobals.getValue(ConfigKeys.LUCENE_INDEX_WRITE_PATH));

this.removeLockFile();

this.indexer = new LuceneIndexer(this.settings);

this.search = new LuceneSearch(this.settings,
new LuceneContentCollector(this.settings));

this.indexer.watchNewDocuDocumentAdded(this.search);
//将搜索配置放到全局对象中
SystemGlobals.setObjectValue(ConfigKeys.LUCENE_SETTINGS, this.settings);
}

catch (Exception e) {
throw new ForumException(e);
}
}

public LuceneSearch luceneSearch()
{
return this.search;
}

public LuceneIndexer luceneIndexer()
{
return this.indexer;
}

public void removeLockFile()
{
try {
if (IndexReader.isLocked(this.settings.directory())) {
IndexReader.unlock(this.settings.directory());
}
}
catch (IOException e) {
throw new ForumException(e);
}
}

/**
* @see net.jforum.search.SearchManager#create(net.jforum.entities.Post)
*/
public void create(Post post)
{
this.indexer.create(post);
}

/**
* @see net.jforum.search.SearchManager#update(net.jforum.entities.Post)
*/
public void update(Post post)
{
this.indexer.update(post);
}

/**
* @see net.jforum.search.SearchManager#search(net.jforum.search.SearchArgs)
*/
public SearchResult search(SearchArgs args)
{
return this.search.search(args);
}

/**
* @see net.jforum.search.SearchManager#delete(net.jforum.entities.Post)
*/
public void delete(Post p)
{
this.indexer.delete(p);
}
}

论坛启动:net.jforum.ForumStartup
public class ForumStartup 
{

private static final Logger log = Logger.getLogger(ForumStartup.class);

/**
* Starts the database implementation
* @return <code>true</code> if everthing were ok
* @throws DatabaseException if something were wrong
*/
public static boolean startDatabase()
{
try {
if (DBConnection.createInstance()) {
DBConnection.getImplementation().init();

// Check if we're in fact up and running
Connection conn = DBConnection.getImplementation().getConnection();
DBConnection.getImplementation().releaseConnection(conn);
}
}
catch (Exception e) {
throw new DatabaseException("Error while trying to start the database: " + e, e);
}

return true;
}

/**
* Starts the cache control for forums and categories.
* @throws RepositoryStartupException is something were wrong.
*/
public static void startForumRepository()
{
try {
//使用单例
ForumDAO fm = DataAccessDriver.getInstance().newForumDAO();
CategoryDAO cm = DataAccessDriver.getInstance().newCategoryDAO();
ConfigDAO configModel = DataAccessDriver.getInstance().newConfigDAO();
//将论坛目录,论坛,最多在线用户数,用户数量,最近注册用户等信息放到缓存中
ForumRepository.start(fm, cm, configModel);
}
catch (Exception e) {
log.error("Unable to bootstrap JForum repository.", e);
throw new RepositoryStartupException("Error while trying to start ForumRepository: " + e, e);
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值