Jeecms 源码剖析

转载 2011年01月12日 09:30:00

 安装

<meta http-equiv="refresh" content="3;URL=install/index.html"/>

您还没有安装JEECMS3秒钟之后自动跳转到安装页面。<br/>

如果您的浏览器长时间没有反应,请直接点击<a href="install/index.html">JEECMS安装</a>

 

install/index.html:一般是同意安装页

<script type="text/javascript">

function formSubmit() {

    if(document.getElementById('license_agree').checked==false){

       alert('请同意我们的协议');

       return false;

    }

    document.getElementById('license_form').submit();

}

</script>

<form id="license_form" action="install_params.jsp" method="post">

<input type="button" class="btn" onclick="formSubmit();" value="下一步 >"/>

进入安装数据库和参数页:

<form action="install_setup.jsp" method="post" onsubmit="return formSubmit();">

<tr>

        <td height="30" align="right">域名:</td>

        <td align="left"><input name="domain" type="text" class="input" value="<%=request.getServerName()%>"/></td>

              <td align="left">系统已经检测出您的域名,请勿改动</td>

      </tr>

      <tr>

        <td height="30" align="right">部署路径:</td>

        <td align="left"><input name="cxtPath" type="text" class="input" value="<%=request.getContextPath()%>"/></td>

              <td align="left">系统已经检测出您的部署路径,请勿改动</td>

      </tr>

     

安装:

<%@page contentType="text/html; charset=gbk" language="java" import="com.jeecms.core.util.*,java.util.*"%>

<%

String dbFileName = "/install/db/jeecms-db-2.4.2-final.sql";

    String initFileName = "/install/db/jeecms-init-2.4.2-final.sql";

    //创建数据库

    if ("true".equals(isCreateDb)) {

       Install.createDb(dbHost, dbPort, dbName, dbUser, dbPassword);

    } else {

       Install.changeDbCharset(dbHost, dbPort, dbName, dbUser, dbPassword);

    }

    //创建表

    if ("true".equals(isCreateTable)) {

       String sqlPath = application.getRealPath(dbFileName);

       List<String> sqlList = Install.readSql(sqlPath);

       Install.createTable(dbHost, dbPort, dbName, dbUser, dbPassword,

              sqlList);

    }

    //初始化数据

    if ("true".equals(isInitData)) {

       String initPath = application.getRealPath(initFileName);

       List<String> initList = Install.readSql(initPath);

       Install.createTable(dbHost, dbPort, dbName, dbUser, dbPassword,

              initList);

    }

    //更新配置

    Install.updateConfig(dbHost, dbPort, dbName, dbUser, dbPassword,

           domain, cxtPath, port);

    //处理数据库配置文件

    String dbXmlPath = application.getRealPath(dbXmlFileName);

    Install

           .dbXml(dbXmlPath, dbHost, dbPort, dbName, dbUser,

                  dbPassword);

    //处理web.xml

    String webXmlFromPath = application.getRealPath(webXmlFrom);

    String webXmlToPath = application.getRealPath(webXmlTo);

    Install.webXml(webXmlFromPath, webXmlToPath);

//Util里面

/**

 * 安装类

 *

 * @author admin

 *

 */

public class Install {

    public static void dbXml(String fileName, String dbHost, String dbPort,

           String dbName, String dbUser, String dbPassword) throws Exception {

       String s = FileUtils.readFileToString(new File(fileName));

       s = s.replaceFirst("DB_HOST", dbHost);

       s = s.replaceFirst("DB_PORT", dbPort);

       s = s.replaceFirst("DB_NAME", dbName);

       s = s.replaceFirst("DB_USER", dbUser);

       s = s.replaceFirst("DB_PASSWORD", dbPassword);

       FileUtils.writeStringToFile(new File(fileName), s);

    }

 

    public static Connection getConn(String dbHost, String dbPort,

           String dbName, String dbUser, String dbPassword) throws Exception {

       Class.forName("com.mysql.jdbc.Driver").newInstance();

       String connStr = "jdbc:mysql://" + dbHost + ":" + dbPort + "/" + dbName

              + "?user=" + dbUser + "&password=" + dbPassword

              + "&characterEncoding=GBK";

       Connection conn = DriverManager.getConnection(connStr);

       return conn;

    }

 

    public static void webXml(String fromFile, String toFile) throws Exception {

       FileUtils.copyFile(new File(fromFile), new File(toFile));

    }

 

    /**

     * 创建数据库

     *

     * @param dbHost

     * @param dbName

     * @param dbPort

     * @param dbUser

     * @param dbPassword

     * @throws Exception

     */

    public static void createDb(String dbHost, String dbPort, String dbName,

           String dbUser, String dbPassword) throws Exception {

       Class.forName("com.mysql.jdbc.Driver").newInstance();;

       String connStr = "jdbc:mysql://" + dbHost + ":" + dbPort + "?user="

              + dbUser + "&password=" + dbPassword + "&characterEncoding=GBK";

       Connection conn = DriverManager.getConnection(connStr);

       Statement stat = conn.createStatement();

       String sql = "drop database if exists " + dbName;

       stat.execute(sql);

       sql = "create database " + dbName

              + " CHARACTER SET GBK";

       stat.execute(sql);

       stat.close();

        conn.close();

    }

 

    public static void changeDbCharset(String dbHost, String dbPort,

           String dbName, String dbUser, String dbPassword) throws Exception {

       Connection conn = getConn(dbHost, dbPort, dbName, dbUser, dbPassword);

       Statement stat = conn.createStatement();

       String sql = "ALTER DATABASE " + dbName

              + " CHARACTER SET GBK";

       stat.execute(sql);

       stat.close();

       conn.close();

    }

 

    /**

     * 创建表

     *

     * @param dbHost

     * @param dbName

     * @param dbPort

     * @param dbUser

     * @param dbPassword

     * @param sqlList

     * @throws Exception

     */

    public static void createTable(String dbHost, String dbPort, String dbName,

           String dbUser, String dbPassword, List<String> sqlList)

           throws Exception {

       Connection conn = getConn(dbHost, dbPort, dbName, dbUser, dbPassword);

       Statement stat = conn.createStatement();

       for (String dllsql : sqlList) {

           stat.addBatch(dllsql);

       }

       stat.executeBatch();

       stat.close();

       conn.close();

    }

 

    /**

     * 更新配置

     *

     * @param dbHost

     * @param dbName

     * @param dbPort

     * @param dbUser

     * @param dbPassword

     * @param domain

     * @param cxtPath

     * @param port

     * @throws Exception

     */

    public static void updateConfig(String dbHost, String dbPort,

           String dbName, String dbUser, String dbPassword, String domain,

           String cxtPath, String port) throws Exception {

       Connection conn = getConn(dbHost, dbPort, dbName, dbUser, dbPassword);

       Statement stat = conn.createStatement();

       String sql = "update CORE_WEBSITE set DOMAIN='" + domain + "'";

       stat.executeUpdate(sql);

       sql = "update CORE_GLOBAL set CONTEXT_PATH='" + cxtPath + "',PORT="

              + port;

       stat.executeUpdate(sql);

       stat.close();

       conn.close();

    }

 

    /**

     * 读取sql语句。“/*”开头为注释,“;”sql结束。

     *

     * @param fileName

     *            sql文件地址

     * @return list of sql

     * @throws Exception

     */

    public static List<String> readSql(String fileName) throws Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader(

                new FileInputStream(fileName), Constants.ENCODING));

        List<String> sqlList = new ArrayList<String>();

        StringBuilder sqlSb = new StringBuilder();

        String s = null;

        while ((s = br.readLine()) != null) {

            if (s.startsWith("/*")) {

                continue;

            }

            if (s.endsWith(";")) {

                sqlSb.append(s);

                sqlSb.setLength(sqlSb.length() - 1);

                sqlList.add(sqlSb.toString());

                sqlSb.setLength(0);

            } else {

                sqlSb.append(s);

            }

        }

        br.close();

        return sqlList;

    }

}

jcaptcha 自定义验证码

(略)

Xml

<!-- Spring 刷新Introspector防止内存泄露 -->

    <listener>      <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>

    </listener>

 

    <!-- session超时定义,单位为分钟 -->

    <session-config>

        <session-timeout>20</session-timeout>

    </session-config>

    <error-page>

        <error-code>404</error-code>

        <location>/404.html</location>

    </error-page>

    <error-page>

        <error-code>403</error-code>

        <location>/403.html</location>

    </error-page>

    <welcome-file-list>

        <welcome-file>index.jspa</welcome-file>

        <welcome-file>index.do</welcome-file>

        <welcome-file>index.html</welcome-file>

    </welcome-file-list>

目录:之一

总共40张表 Spring里面可以用这种方式:

<property name="mappingLocations">

<list>          <value>classpath:/com/jeecms/core/entity/*.hbm.xml</value>          <value>classpath:/com/jeecms/cms/entity/*.hbm.xml</value>           <value>classpath:/com/jeecms/article/entity/*.hbm.xml</value>       <value>classpath:/com/jeecms/download/entity/*.hbm.xml</value>      <value>classpath:/com/jeecms/auxiliary/entity/*.hbm.xml</value>

</list>

</property>

同样Hibernate也可以这样:

<property name="hibernateProperties">

            <value>

            hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect

            hibernate.show_sql=true

            hibernate.format_sql=false

            hibernate.query.substitutions=true 1, false 0

            hibernate.jdbc.batch_size=20

hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider

hibernate.cache.provider_configuration_file_resource_path=/ehcache-hibernate.xml

            </value>

        </property>

 Spring事务

<!-- 事务配置 -->

       <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

              <property name="sessionFactory" ref="sessionFactory" />

       </bean>

 

       <!-- 使用annotation 自动注册bean,并检查@Required,@Autowired的属性已被注入 -->

       <context:component-scan base-package="com.jeecms" />

      

       <!-- 使用annotation定义事务 -->

       <tx:annotation-driven transaction-manager="txManager" />

Spring注解@Component@Repository@Service@Controller区别

Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository@Service @Controller。在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这 3 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用 @Repository@Service @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。

@Service用于标注业务层组件,@Controller用于标注控制层组件(如struts中的action,@Repository用于标注数据访问组件,即DAO组件,而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

 

Spring事务处理

 

@Repository

public abstract class BaseDaoImpl<T extends Serializable> implements BaseDao<T> {

         protected Logger log = LoggerFactory.getLogger(getClass());

 

         protected SessionFactory sessionFactory;

 

         @Autowired

         public void setSessionFactory(SessionFactory sessionFactory) {

                   this.sessionFactory = sessionFactory;

         }

 

         protected Session getSession() {

                   return sessionFactory.getCurrentSession();

         }

 

         public T save(T entity) {

                   Assert.notNull(entity);

                   getSession().save(entity);

                   return entity;

         }

 

         public Object update(Object entity) {

                   Assert.notNull(entity);

                   getSession().update(entity);

                   return entity;

         }

 

         public Object saveOrUpdate(Object entity) {

                   Assert.notNull(entity);

                   getSession().saveOrUpdate(entity);

                   return entity;

         }

 

         public void delete(Object entity) {

                   Assert.notNull(entity);

                   getSession().delete(entity);

         }

 

         public T deleteById(Serializable id) {

                   Assert.notNull(id);

                   T entity = load(id);

                   getSession().delete(entity);

                   return entity;

         }

 

         @SuppressWarnings("unchecked")

         public T get(Serializable id) {

                   Assert.notNull(id);

                   return (T) getSession().get(getPersistentClass(), id);

         }

 

         @SuppressWarnings("unchecked")

         public T load(Serializable id, boolean lock) {

                   Assert.notNull(id);

                   T entity = null;

                   if (lock) {

                            entity = (T) getSession().load(getPersistentClass(), id,

                                               LockMode.UPGRADE);

                   } else {

                            entity = (T) getSession().load(getPersistentClass(), id);

                   }

                   return entity;

         }

         public List<T> findAll() {

                   return findByCriteria();

         }

         @SuppressWarnings("unchecked")

         public List<T> findAll(OrderBy... orders) {

                   Criteria crit = createCriteria();

                   if (orders != null) {

                            for (OrderBy order : orders) {

                                     crit.addOrder(order.getOrder());

                            }

                   }

                   return crit.list();

         }

 

         public Pagination findAll(int pageNo, int pageSize, OrderBy... orders) {

                   Criteria crit = createCriteria();

                   return findByCriteria(crit, pageNo, pageSize, null, OrderBy

                                     .asOrders(orders));

         }

IMPL类:加:@Repository

Action中:加:@Repository

目前对jeecms的事务还有点不清楚,因为jeecms用了大量的注解:

@Service

@Transactional

public class FunctionMngImpl

@Autowired 是自动生成set方法:

@Autowired

private ContextPvd contextPvd;

则不用写set了,但get还要写。

Struts2Spring之间URL跳转

 

<struts>

    <include file="com/jeecms/cms/struts-default.xml" />

   

    <include file="com/jeecms/cms/struts-core-admin.xml" />

    <include file="com/jeecms/cms/struts-core-ajax.xml" />

    <include file="com/jeecms/cms/struts-core-front.xml" />

</struts>

//struts-login.xml 登录

<package name="cms.login" namespace="/login" extends="core-default">

       <global-results>

           <result name="logout" type="redirectAction">

              <param name="namespace">/login</param>

              <param name="actionName">Jeecms</param>

           </result>

           <result name="loginInput">/WEB-INF/cms_sys/login.html</result>

       </global-results>

       <action name="Jeecms" method="loginInput" class="cms.adminLoginAct"/>

       <action name="CmsLogout" method="logout" class="cms.adminLoginAct"/>

      

使用annotation 自动注册bean spring整合Struts2的一种:

1,  spring xml

<!-- 使用annotation 自动注册bean,并检查@Required,@Autowired的属性已被注入 -->

    <context:component-scan base-package="com.lch.spring.auto" />

2,  Struts2里面:

<action name="auto" class="into.autoSpringAction" method="autoMethod" >

 

3,写一个接口,和一个实现类

public interface InterfaceTest {

 

@Repository

public class AutoImpl implements InterfaceTest{

 

3,  Struts2中用@Controller @Autowrited

@Scope("prototype")

@Controller("into.autoSpringAction")

public class AutoSpringAction extends ActionSupport{

@Autowired

    private InterfaceTest ift;

public String autoMethod(){

       ift.sayHelloAuto();

       return SUCCESS;

    }

 如上面连set 都不用写,且spring里面没有Bean的配置用注解将接口和实现类装配进了。

以后台登陆为例:

http://localhost:8080/jeecms/login/Jeecms.do   //从上面可以知道是cms.adminLoginAct

这时Jeecms用注解来跳转的。如下

 

@Scope("prototype")

@Controller("cms.adminLoginAct")

public class AdminLoginAct extends JeeCoreAction {

 

后台登陆

<global-results>

<result name="loginInput">/WEB-INF/cms_sys/login.html</result>

</global-results>

Next<action name="CmsSubmit" method="login" class="cms.adminLoginAct">

    下面是登录设计:good

public String login() {

        boolean isHuman = imageCaptchaService.validateResponseForID(contextPvd

                .getSessionId(false), checkCode);

        if (!isHuman) {

            addActionError("验证码错误!");

            return loginInput();

        }

        User user = userMng.authenticate(loginName, password);

        if (user == null) {

            addActionError("用户名不存在或密码错误!");

            return loginInput();

        }

        Admin admin = adminMng.getByUserId(getWebId(), user.getId());

        if (admin == null) {

            addActionError("您没有本站的管理权限!");

            return loginInput();

        } else if (admin.getAdminDisabled()) {

            addActionError("您的帐号已经被禁止!");

            return loginInput();

        }

        // 清除以前登录信息

        contextPvd.logout();

        // 保存当前登录信息

        contextPvd.setSessionAttr(User.USER_KEY, user.getId());

        contextPvd.setSessionAttr(Admin.ADMIN_KEY, admin.getId());

        userMng.updateLoginInfo(user);

        // 将权限集放入session

        Set<String> fiSet = functionMng.getFunctionItems(admin.getId());

        contextPvd.setSessionAttr(Admin.RIGHTS_KEY, fiSet);

        // 处理次级域名单点登录

        Website web = getWeb();

        if (!StringUtils.isBlank(web.getBaseDomain())) {

            Cookie c = new Cookie(JSESSION_COOKIE, contextPvd

                    .getSessionId(false));

            c.setPath("/");

            c.setDomain(web.getTopDomain(true));

            contextPvd.addCookie(c);

        }

        return SUCCESS;

    }

    上面清除Session方法:

public void logout() {

    HttpSession session = ServletActionContext.getRequest().getSession(

              false);

       if (session != null) {

           session.invalidate();

       }

    }

登录成功之后的跳转:这个很好:将进入另外一个namespace

<result name="success" type="redirectAction">

              <param name="actionName">Com_index</param>

              <param name="namespace">/admin/cms</param>

</result>

进入这里

<!--后台首页-->

    <package name="cms.console" namespace="/admin/cms" extends="core-default">

       <action name="Com_*" method="{1}" class="cms.adminConsoleAct">

           <result name="index">/WEB-INF/cms_sys/index.html</result>

           <result name="main">/WEB-INF/cms_sys/main.html</result>

           <result name="left">/WEB-INF/cms_sys/left.html</result>

           <result name="right">/WEB-INF/cms_sys/right.html</result>

       </action>

    </package>

进入:一个叫 index的方法里面

@SuppressWarnings("serial")

@Scope("prototype")

@Controller("cms.adminConsoleAct")

public class AdminConsoleAct extends JeeCoreAction {

    public String index() {

        // @ TODO 检查管理员是否属于该系统。

        // 多站点管理

        websiteList = websiteMng.getListByUserId(getUserId());

        sessionAppend = ";" + JSESSION_URL + "="

                + contextPvd.getSessionId(false);

        return INDEX;

    }

 

    public String main() {

        return "main";

    }

 

    public String left() {

        return LEFT;

    }

 

    public String right() {

        if (pwdEncoder.isPasswordValid(getUser().getPassword(), "password")) {

            pwdWarn = true;

        }

        props = System.getProperties();

        Runtime runtime = Runtime.getRuntime();

        freeMemoery = runtime.freeMemory();

        totalMemory = runtime.totalMemory();

        usedMemory = totalMemory - freeMemoery;

        maxMemory = runtime.maxMemory();

        useableMemory = maxMemory - totalMemory + freeMemoery;

        return RIGHT;

    }

 

后台使用frame T字形结构 进入index.html 之后 调用main方法

<!--主体框架Begin-->

<iframe id="mainFrame" name="mainFrame" src="Com_main.do" frameborder="0" scrolling="no" style="width:100%;"></iframe>

<!--主体框架End-->

进入main.html

<frameset cols="170,*" frameborder="0" border="0" framespacing="0">

    <frame src="Com_left.do" name="leftFrame" noresize="noresize" id="leftFrame" />

    <frame src="Com_right.do" name="rightFrame" id="rightFrame" />

</frameset>

<noframes><body></body></noframes>

注意right方法里面修改初始密码

当此时URL:还是Com_index.do??OK I know it. 也就是在index html里面还有很多处理,所有数据:

当是初始密码时会弹出一个很漂亮的对话框,在 right html

<#include "/WEB-INF/cms_sys/head.ftl"/>

<#if pwdWarn>

<script type="text/javascript">

$(document).ready( function() {

    jAlert("您还在使用初始密码,请及时修改密码!","温馨提示");

});

</script>

</#if>

进入cms_sys/head.ftl 发现是query UI

jcaptcha 自定义验证码例子

http://hi.baidu.com/laihua2006/blog/item/e3af00002462df007bec2cd7.html

我将jcaptcha的使用写在这里。Jeecms就是用这个。

Hibernate Interceptor

及当系统运行时就执行

public class TreeIntercptor extends EmptyInterceptor {

    protected SessionFactory sessionFactory;

 

    protected SessionFactory getSessionFactory() {

        if (sessionFactory == null) {

            WebApplicationContext wac = WebApplicationContextUtils

                    .getRequiredWebApplicationContext(ServletActionContext

                            .getServletContext());

            sessionFactory = (SessionFactory) wac.getBean("sessionFactory",

                    SessionFactory.class);

        }

        return sessionFactory;

    }

 

    protected Session getSession() {

        return getSessionFactory().getCurrentSession();

    }

 

Spring xml

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

        <property name="dataSource" ref="dataSource"/>

   

        <property name="entityInterceptor">  

            <ref local="treeInterceptor"/>

        </property>

    </bean>

<bean id="treeInterceptor" class="com.jeecms.TreeIntercptor"/>

这点还不清楚

Spring jdbc

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

    <property name="location">

        <value>classpath:jdbc.properties</value>

       </property>

    </bean>   

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

       <property name="driverClass" value="com.mysql.jdbc.Driver" />

       <property name="jdbcUrl" value="${jdbc.url}" />

       <property name="user" value="${jdbc.username}" />

       <property name="password" value="${jdbc.password}" />

       <property name="autoCommitOnClose" value="true"/>

       <property name="checkoutTimeout" value="${cpool.checkoutTimeout}"/>

       <property name="initialPoolSize" value="${cpool.minPoolSize}"/>

       <property name="minPoolSize" value="${cpool.minPoolSize}"/>

       <property name="maxPoolSize" value="${cpool.maxPoolSize}"/>

       <property name="maxIdleTime" value="${cpool.maxIdleTime}"/>

       <property name="acquireIncrement" value="${cpool.acquireIncrement}"/>

       <property name="maxIdleTimeExcessConnections" value="${cpool.maxIdleTimeExcessConnections}"/>

    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

       <property name="dataSource" ref="dataSource"/>

<property name="mappingLocations">

           <list>

              <value>classpath:/com/jeecms/core/entity/*.hbm.xml</value>

    <value>classpath:/com/jeecms/cms/entity/*.hbm.xml</value>          <value>classpath:/com/jeecms/article/entity/*.hbm.xml</value>      <value>classpath:/com/jeecms/download/entity/*.hbm.xml</value>     <value>classpath:/com/jeecms/auxiliary/entity/*.hbm.xml</value>

           </list>

       </property>

       <property name="hibernateProperties">

           <value>

           hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect

           hibernate.show_sql=true

           hibernate.format_sql=false

           hibernate.query.substitutions=true 1, false 0

           hibernate.jdbc.batch_size=20

hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider

hibernate.cache.provider_configuration_file_resource_path=/ehcache-hibernate.xml

           </value>

       </property>

       <property name="entityInterceptor">  

           <ref local="treeInterceptor"/>

       </property>

    </bean>

<!--下面是事务à

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

       <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    <context:component-scan base-package="com.jeecms" />

    <tx:annotation-driven transaction-manager="transactionManager" />

用:c3p0.ComboPooledDataSource 更快classpath:jdbc.properties如下:

jdbc.driverClassName=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://127.0.0.1:3306/jeecms_2_4?characterEncoding=gbk

jdbc.username=root

jdbc.password=root

 

cpool.checkoutTimeout=5000

#cpool.minPoolSize=20

#cpool.maxPoolSize=50

cpool.minPoolSize=1

cpool.maxPoolSize=5

 

cpool.maxIdleTime=7200

cpool.maxIdleTimeExcessConnections=1800

#cpool.acquireIncrement=10

cpool.acquireIncrement=1

进入前台

注后台栏目将在下一文档解析

Web xml

<welcome-file-list>

              <welcome-file>index.jspa</welcome-file>

              <welcome-file>index.do</welcome-file>

              <welcome-file>index.html</welcome-file>

       </welcome-file-list>

默认首页是先index.jspa is nothing  and  next page :index.do  and next page: index.html  so:

Into index.do

Struts-core-font.xml

<action name="**" class="core.dynamicSystemAct">

           <result type="chain">

              <param name="namespace">${namespace}</param>

              <param name="actionName">${actionName}</param>

           </result>

           <interceptor-ref name="startTime"/>

           <interceptor-ref name="exception"/>

           <interceptor-ref name="domain"/>

           <interceptor-ref name="cookieIdentity"/>

           <interceptor-ref name="url"/>

       </action> 

Next into  Action:

@Scope("prototype")

@Controller("core.dynamicSystemAct")

public class DynamicSystemAct implements Action, DomainNameAware, UrlAware {

    public String execute() {

        Website web = websiteMng.getWebsite(domainName);

        if (web == null) {

            // 检查别名

            web = websiteMng.getByAlias(domainName);

            if (web != null) {

                redirectUrl = web.getWebUrl();

                return Constants.REDIRECT;

            } else {

                return Constants.WEBSITE_NOT_FOUND;

            }

        }

        String sys = web.getCurrentSystem();

        namespace = "/jeedynamic/" + sys;

        actionName = "Page";

        return SUCCESS;

    }  

Next into struts-font.xml

<!--JEECMS前台页面-->

    <package name="cms.front.page" namespace="/jeedynamic/jeecms" extends="empty-default">       

        <action name="Page" class="cms.cmsPageAct">

            <result>${tplPath}</result>

            <result name="pageCache" type="pageCache">${tplPath}</result>

            <interceptor-ref name="exception"/>

            <interceptor-ref name="chain"/>

        </action>

    </package>

Next into action:

package com.jeecms.cms.action.front;

CmsPageAct extends PageBaseAction

这里有一个很好的设计,首页是在父类中打开的

public abstract class PageBaseAction extends IntegrityAction {

 

@Override

    public String execute() throws Exception {

        handlePathParams();

        pageName = pathParams[len - 1];

        if (len == 1 && pageName.equals(INDEX)) {

            // 首页

            return sysIndex();//而这些是由子类去实现CmsPageAct

        } else if (len == 1 && NumberUtils.isDigits(pageName)) {

            // 内容

            try {

                return content(null, Long.parseLong(pageName));

            } catch (NumberFormatException nfe) {

                return pageNotFound();

            }

        } else if (len == 1) {

            return alone(pageName);

        } else if (len == 2 && pageName.equals(INDEX)) {

            return chnlIndex(pathName);

        } else if (len == 2 && NumberUtils.isDigits(pageName)) {

            try {

                return content(pathName, Long.parseLong(pageName));

            } catch (NumberFormatException nfe) {

                return pageNotFound();

            }

        } else {

            return pageNotFound();

        }

    }

/**

     * 系统首页

     */

    protected abstract String sysIndex() throws IOException;

    /**

     * 栏目页

     */

    protected abstract String chnlIndex(String chnlName) throws IOException;

    /**

     * 内容页

     */

    protected abstract String content(String chnlName, Long id)

           throws IOException;

 

    /**

     * 单页

     */

    protected abstract String alone(String chnlName) throws IOException;

 

    /**

     * 页面找不到

     *

     * @return

     */

    protected abstract String pageNotFound();

myeclipse debug find tplPath 模板地址 :如下

/WEB-INF/user_base/jeecms_com_www/template/article/default/index.html

Next into template index.html copte xecerpt:

<!--页头Begin-->

[@cms.Include name='head.html' solution='default'/]

<!--页头End-->

<!--搜索栏Begin-->

[@cms.Include name='search.html' solution='default'/]

<!--搜索栏End-->

<!--共同关注Begin-->

<div class="page_row">

  <div class="left"><img alt="" src="${root}/default/article/img/myjon.gif" /></div>

  <div class="left run_news"> [@cms.ArtiList chnlId='' attr='5' count='10' sysContent='2-1' titLen='20' dateFormat='3' datePosition='3' headMark='2' target='1' rollCols='2' rollSpeed='3' rollSleepTime='100'/]</div>

  <div style="clear: both"></div>

</div>

<!--共同关注End-->

Jeecms used freemarker template ,that is the same used the most template technical in PHP. If you want to change the index.html header ,you could open the page head.html edit which you want.

Then we  will start to pay attention the jeecms Tag.

标签解读

例如:[@cms.Include name='search.html' solution='default'/]

    [@cms.ChnlList id='' inner='1';c]<li class="thisclass"><a href="${c.url}">${c.name}</a></li>[/@cms.ChnlList]

是怎么来的,为什么@cms.ChnlList 就能输出导航数据。

Tag是在Struts2里面定义的,struts-front xml

<!--栏目标签-->

    <package name="cms.front.tag" namespace="/jeecms/tag/cms" extends="tag-default">

        <action name="ChnlList" method="chnlList" class="cms.chnlPartAct">

            <result name="sysTpl">/WEB-INF/ftl_lib/jeecms/cms/chnl_list.ftl</result>

            <result>${tplPath}</result>

        </action>

    </package>

extends="tag-default" 跟踪:

<package name="tag-default" abstract="true" extends="core-default">

              <default-interceptor-ref name="tagStack" />

       </package>

tagStack跟踪:

<!--标签栈-->

            <interceptor-stack name="tagStack">

                <interceptor-ref name="startTime"/>

                <interceptor-ref name="exception">

                    <param name="logEnabled">true</param>

                    <param name="logLevel">warn</param>

                </interceptor-ref>

                <interceptor-ref name="url"/>

                <interceptor-ref name="params">

                    <param name="excludeParams">dojo/..*</param>

                </interceptor-ref>

            </interceptor-stack>

 

主要说一下在程序里面自定义的几个比较重要的拦截器(定义在jeecms/src/struts-default.xml文件中)。DomainNameInterceptorUrlInterceptorCookieIdentityInterceptor然后执行action自己的execute方法,产生 2个参数:namespace = "/jeedynamic/" + sys;actionName = "Page";2个参数决定了程序的走向,组成转发路径:/jeedynamic /jeecms/Page.do,然后通过查找下面的配置信息    ${tplPath}    ${tplPath}   注:其他的请求过程类似,先找到命名空间,然后找到对应的 acting进行处理。将请求转发给cms.cmsPageAct对象,同上的道理,对应到控制器:com.jeecms.cms.action.front.CmsPageAct。拦截器处理完毕后,执行自己的 execute方法,判断若是首页,则执行sysIndex()方法,返回一个模板路径tplPath/WEB-INF/user_base/jeecms_com_www/template /article/default/index.html,找到这个文件,

Freemark:对于jeecms来说标签主要是freemark在支配。URL则是身是Struts2

freemarker.properties:auto_import="/WEB-INF/ftl_lib/ponyjava.com/index.ftl" as p, "/WEB-INF/ftl_lib/jeecms/index.ftl" as cms @cms标签所用的ftl模板文件为index.ftl 打开index.ftl文件,includes了多个ftl,其中有action_cms.ftl,该文件用标签#macro,自定义许多directiveChnlListCommentList 等。里面使用struts2标签@s.action来请求数据,整个的index.html页面就是这么加载出来的。通过 freemarker引擎来解析数据模型,最后显示到前台,展现给客户。index.html include head.html[@cms.ChnlList id='' inner='1';c]

 

OK:我们打开/WEB-INF/ftl_lib/jeecms/cms/chnl_list.ftl</result>看看

<ul>

<#list list as chnl>

<li><a href="${chnl.url}" class="${linkClass}"<#if linkTarget=="1"> target="_blank"</#if>>${chnl.name}</a></li>

</#list>

</ul>

发现里面就是freemark生成的代码;

Jeecms标签参数说明:(部分)

id:父栏目ID。(默认为空:自动获取当前栏目ID
orderBy
:排序方式。【0:优先级升序;1:优先级降序;2:点击次数升序;3:点击次数降序】(默认0
isDisplay
:是否只获取显示的栏目。【0:获取所有;1:只获取显示的栏目】(默认1
hasContent
:是否只获取可以有内容的栏目。【0:获取所有;1:只获取可以有内容的栏目】(默认0
linkClass
:链接class
linkTarget
:链接打开方式。【0:当前窗口;1:新窗口】(默认0
style
:标签内部样式。如果指定sysContentuserContent,则该项无效。【1:普通链接列表;】(默认1
sysTpl
:使用系统模板。【0:不使用;1:使用】(默认1
sysContent
:系统内容样式。(默认0
userContent
:自定义内容样式。如果指定了系统内容样式,则该项无效。(默认0
sysPage
:系统分页样式。【0:不分页;1:样式一;2:样式二】(默认0
userPage
:自定义分页样式。如果指定了系统分页样式,则该项无效。【0:不分页;1:样式一;2:样式二】(默认0
custom
:字符串数组。用于个性化处理。(默认空数组)------

freemarker+struts2应用

http://hi.baidu.com/laihua2006/blog/item/e83d3b098c6a11d862d98694.html

http://hi.baidu.com/laihua2006/blog/item/4684441fe6ad80fa1ad57668.html

上面是我写下的两个例子:一个是freemarker+servlet的例子建议先看这个

Action

@Scope("prototype")
@Controller("spring.springCpoTest")
public class SpringCpoTest extends ActionSupport {


private List<Member> mlist;

private String    mk="mkkk";

@Autowired
private MemberDAO mdao;
public String method(){
  mlist=mdao.findAll();
   return SUCCESS;
}

public List<Member> getMlist() {
   return mlist;
}
public void setMlist(List<Member> mlist) {
   this.mlist = mlist;
}

public String getMk() {
   return mk;
}
public void setMk(String mk) {
   this.mk = mk;
}

}

struts.xml------

   <action name="c3pSpring" class="spring.springCpoTest" method="method" >
    <result name="success" type="freemarker" >/template/hello.ftl</result>
    <result name="error" >/error.jsp </result>
   </action>

template:hello.ftl----

<html>

<head>

<title>Welcome!</title>

</head>

<body>

<h1>Welcome</h1>
${mk}

<#list mlist as mem>
${mem.id}| ${mem.uname}|${mem.password}<br>

</#list>

</body>

</html>

当然可以在src下面建一个叫freemarker.properties的文件写入如下:

url_escaping_charset=UTF-8

template_update_delay=1
datetime_format=yyyy-MM-dd HH:mm:ss
date_format=yyyy-MM-dd
time_format=HH:mm:ss

这些是干什么用的请看freemarker文档

最近jeecms3.0 去掉了struts2 ,用的是springMVC

 

 

 

相关文章推荐

在Myeclipse中重构Jeecms v7为Maven项目

一、下载并解压apache-maven-3.3.1,在myeclipse中进行配置。根据自己的需要,选择本地maven库的位置。二、新建Web Project项目,并添加Maven支持。项目目录结构如...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

JEECMS源码剖析

安装 您还没有安装JEECMS,3秒钟之后自动跳转到安装页面。 如果您的浏览器长时间没有反应,请直接点击JEECMS安装。 install/index.html...

jeecms 2012 源码分析(四)------ 验证码-jcaptcha分析

本文主要介绍jeecms中使用的验证码 jcapthcha.   这是个开源的软件,下载地址:   http://jcaptcha.sourceforge.net/   在jeecms中使...
  • jun0052
  • jun0052
  • 2013年03月01日 15:56
  • 1738

基于Java的门户网站管理系统——JEECMS源码版的搭建步骤

工作的关系发现了JEECMS这个网站管理系统,这个CMS系统提供的功能比较全,个人建站完全免费。...

jeecms 2012 源码分析(8) 相关配置文件分析

application-context.xml

jeecms 2012 源码分析(三)------ Spring + FreeMarker的集成。

本节主要分析Spring + FreeMarker的集成。 先介绍一下 spring+freemarker的集成主要涉及以下配置项: 1、配置FreeMarkerConfigurer ...
  • jun0052
  • jun0052
  • 2013年03月01日 15:50
  • 2240

JEECMS v3.0.1 beta版源码分析2

转  http://1985wanggang.blog.163.com/blog/static/776383320101113115750146/ JEECMS v3.0.1 beta版发布...

jeecms无法修改子栏目顺序,引出的源码漏洞

老哥最近正在做一个cms的小项目(www.uni-orange.com),验收前期,逐一解决系统bug,直到一个bug的出现,害得老哥老老实实地坐了一天!! 简单介绍一下使用的cms框架:jeecm...
  • Soongp
  • Soongp
  • 2017年02月21日 11:41
  • 576
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Jeecms 源码剖析
举报原因:
原因补充:

(最多只允许输入30个字)