`
qinwei6060
  • 浏览: 6933 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

Jforum启动

    博客分类:
  • Java
阅读更多
启动:
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);
		}
	}
}
分享到:
评论

相关推荐

    Jforum相关文档和PPT

    初始化流程是Jforum启动时执行的一系列操作,如加载配置、初始化核心组件、注册监听器等。这个过程保证了论坛在启动后能正确地提供服务。开发者可以通过跟踪源代码或日志来理解这一过程,以便在出现问题时快速定位...

    jforum3.0所需要的jar包

    《深入解析jforum3.0所需jar包》 在Java Web开发领域,...开发者通常会将这些jar包放在WEB-INF/lib目录下,以便Web服务器在启动时自动加载。理解这些jar包的作用和功能,有助于我们更好地理解和维护jForum3.0应用。

    JForum_SSO_-_JForum单点登陆原理与配置

    具体的配置步骤可能涉及修改`forum.properties`或其他相关配置文件,确保JForum在启动时加载并使用自定义的SSO实现。 通过以上步骤,JForum就可以识别已登录主应用的用户,从而实现单点登录。这种方式简化了用户在...

    jforum3.0项目需要的jar包

    然后,启动服务器,如果一切配置正确,JForum应该可以正常运行。 10. **安全性与权限**:在实际部署中,确保对JForum进行了适当的权限和安全配置,以防止未授权访问和潜在的安全漏洞。 11. **测试与调试**:部署后...

    Jforum2.19

    运行服务器,如果配置正确,Jforum应该可以在指定端口上启动。 5. **调试与优化**:使用MyEclipse的调试工具进行代码调试,检查和修复可能出现的问题。根据性能监控结果进行必要的优化,如调整缓存策略、数据库查询...

    JForum3 完整项目

    下载JForum3源码后,使用构建工具导入项目,配置好数据库连接,即可启动服务器进行测试和开发。 总结来说,JForum3是一个成熟的Java论坛解决方案,它的完整源代码对于Java Web开发者来说是一个宝贵的资源,无论是...

    利用JForum创建论坛

    4. 启动Tomcat,访问JForum的安装页面,根据提示完成论坛的初始化设置。 5. 版面设计:根据需求设计论坛的版块,可以创建多个版块并分配不同的权限。 6. 用户管理:设置用户分组,如管理员、版主和普通用户,定义...

    jforum安装

    然后,启动Tomcat服务器,JForum会自动解压并部署。访问`http://localhost:8080/jforum`(假设Tomcat默认端口为8080),如果出现JForum的安装向导页面,说明部署成功。 在安装向导中,你需要配置数据库连接信息,...

    jforum2.1.8

    5. **部署应用**:将WAR文件部署到Web服务器的应用目录下,启动服务器完成部署。 6. **初始化数据**:访问安装URL,按照向导完成论坛的初始化设置,如管理员账户、默认板块等。 7. **运行论坛**:安装完成后,通过...

    jforum开源的论坛文档

    6. **启动应用服务**:通过命令行或IDE启动jForum应用程序。 7. **访问首页**:在浏览器中输入http://localhost:8080/jforum即可看到论坛首页。 #### 五、常见问题解答 1. **如何解决安装过程中的错误提示?** - ...

    chx 学习jForum笔记十八 jForum与ms sqlserver

    启动Tomcat服务器,浏览器访问`http://localhost:8080/jforum`(假设Tomcat默认端口为8080),你应该能看到jForum的欢迎页面。通过注册新用户或使用管理员账号登录,你可以开始体验并管理你的论坛。 通过以上步骤...

    jforum 2.1.9源码

    4. **运行与安装**:将WAR文件部署到Tomcat或其他Servlet容器,启动后访问`install`目录进行初始设置,包括创建数据库表、设置管理员账户等。 5. **升级与维护**:若已有旧版本JForum,需按照官方文档进行数据迁移...

    Jforum安装部署

    2. **启动Tomcat**:启动Tomcat服务。 3. **访问安装页面**:通过浏览器访问`http://127.0.0.1:8080/jforum/install.jsp`,按照提示填写相关信息。 - **数据库编码**:选择`UTF-8`。 - **数据库名称**:与步骤3.1...

    jforum-2.1.8.zip

    5. 运行:点击运行,Eclipse将启动服务器并加载JForum应用,通过浏览器访问`http://localhost:8080/jforum`即可查看和使用论坛。 四、JForum核心组件与技术 1. **Struts框架**:JForum采用Struts作为MVC框架,处理...

    jforum-2.1.8-src.zip

    完成这些步骤后,就可以启动论坛并进行基本设置了。 5. **社区与开发** JForum有一个活跃的开发者社区,提供技术支持和插件开发,不断推动软件的更新和完善。此外,JForum的源代码开放,允许开发者进行二次开发,...

    jforum-2.5.0安装包+安装方式.rar

    4. **启动服务器**:如果服务器未运行,启动它。当Tomcat检测到新的WAR文件时,它会自动解压文件并创建对应的Web应用目录。 5. **数据库配置**:JForum需要连接到一个数据库来存储论坛数据。根据你的需求,可以是...

    jforum项目

    该文件用于设置MySQL服务器的启动参数,包括端口号、最大连接数、日志设置等。了解这些参数对于优化数据库性能至关重要。 JForum的数据访问层(DAO)通常使用Hibernate框架,它简化了Java与数据库之间的交互。...

Global site tag (gtag.js) - Google Analytics