在roller中如何实现一个blog有多个主题?


背景

当前获取信息的设备越来越多,比如平板电脑、智能手机,已经不是过去PC统治的年代了。所以很多网站为了提高用户体验根据不同的设备用不同的主题展现相同的数据。那么在roller中如何实现一个网站实现不同的主题呢?要考虑哪些因素?


有同学或许会说,这没什么的,用js+css或者借助一些框架就能根据不同的设备实现不同的主题。这是一种常见的方法,但在roller中可能要考虑的因素不同,机制不同。


原理

根据请求的URL不同让blog选择不同的主题。比如我们用域名www.example.com为PC访问展现内容,用m.example.com为智能手机展现内容。那么在roller中要根据域名的差异选择不同的主题。


怎么为roller设置域名映射参考我的文章:http://blog.youkuaiyun.com/rol2er/article/details/19081799


实现方法及说明


1、在类Weblog.java中增加一个参数用于传递请求的域名,以便后面做判断,以便达到修改代码最少的目的。

public String requestDomain;

用public是因为jpa如果有get/set方法就必须在db表中有对应的字段。


2、在合适的地方设置requestDomain

如果看过我前面的文章,你可能了解在roller中所有的页面请求都通过PageServlet.java 这个类。因此跟踪代码后知道要修改WeblogRequest类的getWeblog方法:

    public Weblog getWeblog() {
        
        if(weblog == null && weblogHandle != null) {
            try {
                UserManager umgr = WebloggerFactory.getWeblogger().getUserManager();
                weblog = umgr.getWebsiteByHandle(weblogHandle, Boolean.TRUE);
            } catch (WebloggerException ex) {
                log.error("Error looking up weblog "+weblogHandle, ex);
            }
        }
        //add
        weblog.requestDomain = request.getServerName();
        
        return weblog;
    }

3、根据请求域名的不同选择不同的主题。在本文章前roller中weblog跟主题的关系是一对一的。在PageServlet中充满类似这样获取页面模板的调用:

page = weblog.getTheme().getTemplateByAction(ThemeTemplate.ACTION_PERMALINK);


我们要做的是进入getTheme()方法,看看后面的是什么逻辑。经过跟踪代码我们找到可以修改的地方ThemeManagerImpl.java的方法getTheme,如下:


    public WeblogTheme getTheme(Weblog weblog) throws WebloggerException {
        
        if(weblog == null)
            return null;
        
        WeblogTheme weblogTheme = null;
        
        // if theme is custom or null then return a WeblogCustomTheme
        if(weblog.getEditorTheme() == null || 
                WeblogTheme.CUSTOM.equals(weblog.getEditorTheme())) {
            weblogTheme = new WeblogCustomTheme(weblog);
            
        // otherwise we are returning a WeblogSharedTheme
        } else {
            ThemeManager themeMgr = roller.getThemeManager();
            SharedTheme staticTheme =
                    (SharedTheme) this.themes.get(weblog.getEditorTheme());
            //add
            String otherTheme = WebloggerConfig.getProperty(weblog.requestDomain + ".other.theme.name");
            
            if(otherTheme != null) {
            	staticTheme =
                        (SharedTheme) this.themes.get(otherTheme);
            }//end 
            
            if(staticTheme != null) {
                weblogTheme = new WeblogSharedTheme(weblog, staticTheme);
            } else {
                log.warn("Unable to lookup theme "+weblog.getEditorTheme());
            }
        }
        
        return weblogTheme;
    }

红色的是我增加的代码(add/end),通过配置文件来确定博客是否有多个主题,否则就按照原来的逻辑执行。


4、修改roller的缓存系统。

roller为了提高性能对页面做了缓存,如果不对缓存的内容根据domain做区别处理,那么被缓存的一份内容可能被不同的设备获取到,届时智能手机将看到pc专用页面,pc将获取智能手机的专用页面。这种情况是非常糟糕的。

那么如何解决呢?只要修改两个地方。对SiteWideCache类和WeblogPageCache类的下面方法增加红色代码即可。


    public String generateKey(WeblogPageRequest pageRequest) {
        
        StringBuffer key = new StringBuffer();
        //add
        key.append(pageRequest.getWeblog().requestDomain);//end
        key.append(this.CACHE_ID).append(".").append(pageRequest.getLocaleInstance().toString()).append(":");
        key.append("page/");
        key.append(pageRequest.getWeblogHandle());
        //....

}


最后


大概的思路是这样,如果你对roller比较好的了解,有更好的方案,欢迎交流。






<think>我们正在处理一个SQLServer的错误消息:消息102,级别15,状态1,第2行“FLUSH”附近有语法错误。用户已经明确他们使用了`FLUSH`命令(很可能是`FLUSHPRIVILEGES;`)导致错误,因为这是在MySQL中使用的,而SQLServer不支持。用户还提到了一个用户名“roller”,可能是他们在尝试操作用户权限。根据之前的历史对话,我们已经知道:-在SQLServer中,权限修改是实时生效的,不需要像MySQL那样执行`FLUSHPRIVILEGES;`。-如果用户执行了权限修改(如GRANT,DENY,REVOKE)后遇到权限未更新的问题,可能是因为当前会话的权限缓存,解决方法可以是重新连接或者使用一些系统命令刷新缓存。但用户现在的问题是语法错误,所以我们的首要任务是移除错误的`FLUSH`语句,并提供在SQLServer中正确刷新权限缓存的方法(如果需要的话)。此外,用户提到“roller”用户名,所以我们需要考虑可能是在为这个用户设置权限。步骤:1.删除FLUSH语句:因为SQLServer中不存在这个命令。2.如果用户需要刷新权限缓存,我们可以提供替代方法(如重新连接,或者使用系统存储过程刷新单个对象,或者清除整个计划缓存)。3.提供完整的操作示例,包括如何授予权限、如何验证权限以及如何刷新(如果需要)。但是,请注意:权限修改(GRANT/DENY/REVOKE)在SQLServer中是立即生效的,不需要额外的刷新操作。不过,对于存储过程的权限,如果存储过程已经被缓存,可能需要刷新其元数据(使用`sp_refreshsqlmodule`)。另外,对于已经存在的连接,权限的更改可能不会立即影响(因为连接建立时的权限信息会被缓存),此时重新连接即可。因此,我们的操作过程如下:1.删除`FLUSHPRIVILEGES;`这样的语句。2.确保权限语句正确。例如,授予用户“roller”对表“rollerInfos”(假设表名,因为之前提到过)的SELECT权限:```sqlGRANTSELECTONdbo.rollerInfosTOroller;```3.如果需要立即验证,可以尝试重新连接或者使用EXECUTEAS来模拟用户权限进行测试。4.如果修改的是存储过程或函数的权限,或者修改了表结构导致存储过程需要重新编译,可以使用`sp_refreshsqlmodule`。完整操作过程(以用户roller为例):步骤1:授予权限(以SELECT权限为例)```sqlUSEYourDatabaseName;--替换为实际的数据库名GRANTSELECTONdbo.rollerInfosTOroller;--注意:这里表名应该是完整的,包括架构名(如dbo)```步骤2:如果需要刷新存储过程(假如有一个存储过程使用了这个表,且之前已经存在,现在需要重新编译以获取新的权限),则:```sqlEXECsp_refreshsqlmodule'存储过程名';```但是,注意:清除整个计划缓存是非常重量级的操作,会影响所有查询,所以在生产环境中谨慎使用:```sqlDBCCFREEPROCCACHE;--不推荐在生产环境随意使用```步骤3:验证权限可以使用EXECUTEAS来模拟用户进行权限测试:```sqlEXECUTEASUSER='roller';SELECT*FROMdbo.rollerInfos;--测试查询REVERT;--切换回原始用户```如果在测试中遇到权限问题,检查是否有DENY权限覆盖了GRANT,或者用户是否在角色中拥有权限等。步骤4:如果权限修改后,用户roller在已经存在的连接中仍然有旧的权限,那么需要断开重新连接。注意:通常新建立的连接会立即获得新的权限。因此,解决语法错误的完整操作过程就是删除FLUSH语句,然后按照上述步骤执行权限修改和验证。我们不需要在SQLServer中执行任何FLUSH操作。同时,我们生成一些相关问题:§§相关问题§§1.在SQLServer中,如何撤销一个用户的权限?2.如何查看SQLServer中特定用户(例如'roller')的权限?3.在SQLServer中,权限变更后为什么有时需要重新连接才生效?</think> ### SQL Server 消息 102 错误完整解决流程 ("FLUSH"语法错误) #### 🛠️ 错误原因分析 在 SQL Server 中执行 `FLUSH PRIVILEGES` 时出现的语法错误(消息 102),是因为 **`FLUSH` 是 MySQL 特有的命令,不被 SQL Server 支持**。SQL Server 的权限管理系统与 MySQL 完全不同,权限变更通过事务日志实时提交[^1]。 --- #### ✅ 完整操作过程 (以用户 `roller` 为例) 1. **删除错误命令** ```sql -- 错误代码 (MySQL 语法) FLUSH PRIVILEGES; -- 解决方案: 完全删除此行 ``` 2. **授权用户 `roller`** ```sql USE YourDatabase; -- 替换为实际数据库名 GRANT SELECT, INSERT ON dbo.rollerInfos TO roller; ``` 3. **验证权限生效 (无需刷新)** ```sql -- 方法1: 直接测试 EXECUTE AS USER = 'roller'; INSERT INTO dbo.rollerInfos (column1) VALUES ('test'); -- 测试插入 REVERT; -- 方法2: 使用系统函数 SELECT HAS_PERMS_BY_NAME('dbo.rollerInfos', 'OBJECT', 'INSERT') AS CanInsert, HAS_PERMS_BY_NAME('dbo.rollerInfos', 'OBJECT', 'SELECT') AS CanSelect; ``` 4. **特殊场景处理 (需强制刷新时)** ```sql -- 刷新单个存储过程 EXEC sp_refreshsqlmodule 'usp_YourProcedure'; -- 清除整个计划缓存 (谨慎使用!) DBCC FREEPROCCACHE; ``` 5. **权限冲突诊断** ```sql -- 检查 DENY 覆盖 SELECT permission_name, state_desc FROM sys.database_permissions WHERE grantee_principal_id = USER_ID('roller') AND major_id = OBJECT_ID('dbo.rollerInfos'); ``` --- #### ⚠️ 关键注意事项 1. **架构限定必须明确** SQL Server 要求所有对象引用包含架构名: ✅ 正确写法:`GRANT SELECT ON dbo.rollerInfos` ❌ 错误写法:`GRANT SELECT ON rollerInfos` 2. **连接级权限缓存机制** 现有连接可能需重启会话才能更新权限[^2],新连接自动继承新权限 3. **避免使用 MySQL 语法** SQL Server 等价命令对照: | MySQL 命令 | SQL Server 等效操作 | |------------|-------------------| | `FLUSH PRIVILEGES` | 权限自动生效 (无需操作) | | `GRANT ...` | 使用相同语法但需架构限定 | --- #### 🌟 权限验证技巧 ```sql -- 自动化权限测试脚本 BEGIN TRY EXECUTE AS USER = 'roller'; DECLARE @test INT = (SELECT TOP 1 1 FROM dbo.rollerInfos); INSERT INTO dbo.rollerInfos DEFAULT VALUES; REVERT; PRINT '[SUCCESS] 用户 roller 权限验证通过'; END TRY BEGIN CATCH PRINT '[ERROR] 权限错误: ' + ERROR_MESSAGE(); END CATCH ``` ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值