您的位置:首页 > 其它

jforum二次开发中常见问题及解决方法

2014-05-09 17:44 330 查看
1.JForum 直接搜索关键字,跳到错误页面,显示关键字解析错误。

解决办法:

LuceneSearch.java 的 performSearch 方法内,我们改为对于搜索中发生的任何异常都返回空的结果集,替换代码如下:

1
throw
new

SearchException(e);
改为

1
result =
new

SearchResult(
new
ArrayList(),
0
);
附:JForum 的索引默认存放在 /WEB-INF/jforumLuceneIndex 路径下。

重建 JForum 的 Lucene 索引的方法

JForum 提供两种重建 Lucene 索引的方法:

1. 管理控制台:Admin Panel -> Lucene Statistics -> Re-Index

2. 命令行方式:

JForum 的 tools/luceneIndexer 目录下有一个 LuceneCommandLineReindexer 的脚本,该脚本参数如下:
Usage: LuceneCommandLineReindexer
--path full_path_to_JForum_root_directory
--type {date|message}--firstPostId a_id
--lastPostId a_id
--fromDate dd/MM/yyyy
--toDate dd/MM/yyyy
[--recreateIndex]
[--avoidDuplicatedRecords]

使用示例:

sh LuceneCommandLineReindexer.sh --path=/home/www/jforum --recreateIndex --type=message --firstPostId=1 --lastPostId=368000

其中 lastPostId 只需要指定一个足够大的 id 即可,不一定是数据库真实的最大帖子编号。

JForum 这个论坛系统在处理中文的时候,还是多多少少有一些问题。

特别是当程序出错的时候,JForum 的错误页面就会显示乱码,包括页面上的所有带中文提示的信息都变成黑块块了。

经过研究 JForum 的程序处理流程,找到了问题的根源:

JForum.java 的 handleException 方法中,有一个错误用法

首先它对错误页面的content-type 做了设置,这步没错

response.setContentType("text/html; charset=" + encoding);
但是它在写错误信息到页面的时候用了一个 OutputStreamWriter ,大家知道 Java 的 IO 包中,Reader 和 Writer 相关的类是与编码相关的,但是你看它这个方法的原始代码:

new OutputStreamWriter(response.getOutputStream())

说实在的,这是一个愚蠢的错误,对于外国人来说可能没什么问题,但中文的内容就成了乱码,因此只要把这句改成

new OutputStreamWriter(response.getOutputStream(), encoding)

问题就解决了!

附:读别人的代码,也是一种乐趣。

限制匿名发帖的方法:

JForum默认匿名用户是可以发帖的,要限制这个操作首先建立一个匿名用户组,然后给这个用户组指派权限不允许所有的论坛发帖,然后将JForum自动创建的匿名用户放到这个组中即可。

最近的项目用到了jforum,于是就研究了下jorum的权限管理机制。

刚刚看到jforum的ER图还真有点奇怪,从ER图上看,jforum是使用group和role来管理权限,但是只有gorup和user有关联关系, 竟然和forum没有关联关系,后来才明白是在jforum_role_values这张表里,把forumId作为role_value字段保 存了,估计设计者也是为了简少表之间的外键关联关系。

jforum里对权限分得很细,大体有一下几种:

Jforum 权限对应表

perm_administration$single
是否为越级管理员
perm_category 限制的分类

perm_forum 限制的版块

perm_anonymous_post 禁止匿名用户发帖

perm_reply_only 禁止发主体帖,允许回复帖子

perm_create_sticky_announcement_topics$single 允许将主题设置为公告或置顶主题

perm_create_poll$single 可发起投票帖

perm_vote$single 允许投票

perm_read_only_forums 只读版块.选择允许所有表示禁止标签,也就是可回复。

perm_reply_without_moderation
选择 '允许全部'将不限制对所有版块的回复,选中指定的版块代表不允许在选择的版本中回复信息.
perm_html_disabled 选中的版块代表不允许使用HTML标签 .选择‘允许所有’代表允许所有版面使用HTML标签

perm_karma_enabled$single
使用文章评分
perm_bookmarks_enabled$single
允许使用书签
perm_attachments_enabled
是否允许使用附件,选择'允许全部'代表可以使用,选择指定版块代表不允许在选中的版块中使用附件
perm_attachments_download
允许下载附件
perm_moderation_log$single
可以查阅管理活动日志
perm_full_moderation_log$single
可以查阅完整的管理活动日志
perm_moderation$single 是否允许设置为版主

perm_moderation_approve_messages$single
是否在允许的版块里审核/封锁贴子
perm_moderation_forums 不能修改的论坛

perm_moderation_post_remove$single
删除贴子
perm_moderation_post_edit$single
修改贴子
perm_moderation_topic_move$single 移动贴子

perm_moderation_topic_lockUnlock$single
锁定和解锁主题

以上都定义在SecurityConstants中,全部权限其实可以大体分为三部分,管理员,游客,会员。

通过不同的组合可以定义不同的group,不过最终的权限(role),只能分配给gorup,然后把用户加入不同的group来获得role.

(在jforum的管理界面看到group有层次关系,可以有parent,也激动 了下,难道group的role也可以继承?后来实验了下发现并没有

这样的机制~。~ 不过一个用户可以属于不同的gorup,role是全部gorup的合集,通过这个还是可以做些文章的 ^.^ )

jforum并没有为二次开发提供比较好的文档和API只有读源代码了,jforum并没有使用流行的MVC框架,似乎是自己实现了一个~后台使用的

是JDBC,所以想要进行二次开发还是得花点力气的。但是jforum的代码比较好 读,处处都有封装,虽然注释不多,看懂代码还是比较简单的。

下面终结些权限控制可以用的方法,jforum并没有提供API,很多好用的方法在 action里面都是private的,所以最好自己可以写个类,

这样使用起来比较方便:

添加一个权限:

GroupAction >>
添加权限控制为group控制 permissionsSave

1
GroupSecurityDAO gmodel = DataAccessDriver.getInstance().newGroupSecurityDAO();
//提示使用gorup管理,看来以后还有扩展
2
 
3
PermissionControl pc =
new

PermissionControl();
4
pc.setSecurityModel(gmodel);
PermissionProcessHelper

1
Role role =
new

Role();
2
role.setName(paramName);
3
this
.pc.addRole(
this
.groupId, role, roleValues);
// 》》》 pc = PermissionControl
4
 
5
this
.addRole(pc, SecurityConstants.PERM_FORUM, f.getId(), groups);
>> Forumaction (推荐用这个比较方便)

roleValues 是forum id, 可以访问的话就加上。(注意这里和管理界面上的概念是相反的,界面上选中的是禁止,而在DB中存在这个字段就表允许)

添加一个组:

GroupAction >> insertSave

把一个人加入某一个群组:

UserAction 》》 groupsSave

GenericUserDAO 》》 addToGroup

添加一个Forum:

ForumAction >> insertSave

01
this
.logNewRegisteredUserIn(userId, u );
// add the user info to session
02
private
void

addManagerRoleForGroup(Forum f, PermissionControl pc,

int
[] gorupIds) {
03
    
this
.addRole(pc, SecurityConstants.PERM_MODERATION_LOG, f.getId(), gorupIds);
04
    
this
.addRole(pc, SecurityConstants.PERM_FULL_MODERATION_LOG, f.getId(), gorupIds);
05
    
this
.addRole(pc, SecurityConstants.PERM_MODERATION, f.getId(), gorupIds);
06
    
this
.addRole(pc, SecurityConstants.PERM_MODERATION_APPROVE_MESSAGES, f.getId(), gorupIds);
07
    
this
.addRole(pc, SecurityConstants.PERM_MODERATION_POST_REMOVE, f.getId(), gorupIds);
08
    
this
.addRole(pc, SecurityConstants.PERM_MODERATION_POST_EDIT, f.getId(), gorupIds);
09
    
this
.addRole(pc, SecurityConstants.PERM_MODERATION_TOPIC_MOVE, f.getId(), gorupIds);
10
    
this
.addRole(pc, SecurityConstants.PERM_MODERATION_TOPIC_LOCK_UNLOCK, f.getId(), gorupIds);
11
   
//------manager role
12
}
13
 
14
private
void

addNormalRoleForGroup(Forum f, PermissionControl pc,
int
[] gorupIds) {
15
    
this
.addRole(pc, SecurityConstants.PERM_ANONYMOUS_POST, f.getId(), gorupIds);
16
    
this
.addRole(pc, SecurityConstants.PERM_REPLY_ONLY, f.getId(), gorupIds);
17
    
this
.addRole(pc, SecurityConstants.PERM_CREATE_STICKY_ANNOUNCEMENT_TOPICS, f.getId(), gorupIds);
18
    
this
.addRole(pc, SecurityConstants.PERM_CREATE_POLL, f.getId(), gorupIds);
19
    
this
.addRole(pc, SecurityConstants.PERM_VOTE, f.getId(), gorupIds);
20
    
this
.addRole(pc, SecurityConstants.PERM_BOOKMARKS_ENABLED, f.getId(), gorupIds);
21
    
this
.addRole(pc, SecurityConstants.PERM_ATTACHMENTS_ENABLED, f.getId(), gorupIds);
22
    
this
.addRole(pc, SecurityConstants.PERM_ATTACHMENTS_DOWNLOAD, f.getId(), gorupIds);
23
    
this
.addRole(pc, SecurityConstants.PERM_ATTACHMENTS_DOWNLOAD, f.getId(), gorupIds);
24
}
在jforum的论坛看到作者正在为jforum3努力,期待jforum3啊~~ 现在最新的jforum2.1.8功能相比一些PHP的论坛还是比较简单的。

关于配置了 URIEncoding 后,jforum 无法搜索中文关键字的问题

招财猫 发布于 2010年02月25日

在 Tomcat 中部署 jforum 项目,

如果 Tomcat 的 Connector 配置了 URIEncoding="UTF-8" 参数的话,

那么 jforum 搜索任何中文关键字都无法搜索到帖子。

解决的办法:

将 SystemGlobals.properties 中的 default.container.encoding 项改为 UTF-8 ,默认值是 ISO-8859-1

搜索的功能无法实现,英文中文都是不行,都是0个结果。

添加两张表:jforum_search_words和jforum_search_wordmatch

1. 檢查目錄權限是否正確

JForum自2.1.8版起改用Lucene作為搜尋引擎,會自動建立索引檔,產生的索引檔存放的預設目錄是$JFORUM_HOME/WEB-INF/jforumLuceneIndex,如果該目錄不存在JForum會自動建立,故需要將WEB-INF目錄設定為tomcat可寫入才行。

在Unix-like系統上可做如下的設定

chgrp tomcat WEB-INF

chmod 775 WEB-INF

2.檢查編碼設定是否正確

資料庫使用的編碼建議設定為UTF-8,並注意jforum-custom.conf裡面的設定是否也設定正確:

dbencoding=utf-8

encoding=UTF-8

3.檢查Tomcat系統設定是否正確

請勿對Connector加上URIEncoding="UTF-8"的參數,這樣會造成二次轉碼,反而找不到。

4.檢查作業系統預設編碼是否正確

檢查/etc/sysconfig/i18n內容,例如:

LANG="zh_TW.UTF-8"

SUPPORTED="zh_TW.UTF-8:zh_TW:zh"

SYSFONT="latarcyrheb-sun16"

5.search.htm請維持原來的GET method,不要改成POST method。

6.重建索引

到系統管理控制台,點選Lucene統計功能,輸入以時間區間方式,重建一次索引,如果上方的文件數不為0即表示索引建立成功。

最近一個案子是在Windows Server 2003上安裝JForum,也遇到了中文搜尋的問題,不過這次的問題是字元字編碼的問題。

首先在WebRequestContext.java中插入幾行輸出(System.out.println())以便提供除錯資訊

 

01
/**    
02
  
* Default constructor.    
03
  
* @param superRequest Original <code>HttpServletRequest</code> instance    
04
  
* @throws IOException    
05
  
*/
 
06
public
WebRequestContext(HttpServletRequest superRequest)
throws
IOException    

07
{  
08
     
super
(superRequest);    
09
     
this
.query =
new
HashMap();  
10
     
boolean

isMultipart =
false
;
11
     
String requestType = superRequest.getMethod().toUpperCase();    
12
     
String contextPath = superRequest.getContextPath();    
13
     
String requestUri =
this
.extractRequestUri(superRequest.getRequestURI(), contextPath);    
14
     
String encoding = SystemGlobals.getValue(ConfigKeys.ENCODING);    
15
     
System.out.println(
"encoding="

+ encoding);
16
     
String servletExtension = SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION);
17
     
boolean

isPost =
"POST"
.equals(requestType);
18
     
boolean

isGet = !isPost;        
19
     
boolean

isQueryStringEmpty = (superRequest.getQueryString() ==

null
|| superRequest.getQueryString().length() ==
0
);           
20
    
if

(isGet &&isQueryStringEmpty &&requestUri.endsWith(servletExtension)) {    
21
         
superRequest.setCharacterEncoding(encoding);     
22
         
this
.parseFriendlyURL(requestUri, servletExtension);   
23
     
}

else
if

(isPost) {  
24
         
isMultipart =ServletFileUpload.isMultipartContent(
new

ServletRequestContext(superRequest));
25
         
if

(isMultipart) {    
26
             
this
.handleMultipart(superRequest, encoding); 
27
         
}    
28
     
}    

29
           
 
30
     
if

(!isMultipart) {
31
         
boolean

isAjax =
"XMLHttpRequest"
.equals(superRequest.getHeader(
"X-Requested-With"
));
32
         
if

(!isAjax) {
33
             
superRequest.setCharacterEncoding(encoding); 
34
             
System.out.println(
"request.encoding="

+ encoding);    
35
         
}
else

{    
36
             
// Ajax requests are *usually* sent using application/x-www-form-urlencoded;charset=UTF-8.  
37
             
// In JForum, we assume this as always true.
38
             
superRequest.setCharacterEncoding(
"UTF-8"
); 
39
         
}
40
         
String containerEncoding = SystemGlobals.getValue(ConfigKeys.DEFAULT_CONTAINER_ENCODING);            
41
         
if

(isPost) {     
42
             
containerEncoding = encoding;    
43
         
}    
44
         
System.out.println(
"containerEncoding="

+ containerEncoding); 
45
         
for

(Enumeration e = superRequest.getParameterNames(); e.hasMoreElements(); ) {    
46
             
String name = (String)e.nextElement();
47
             
String[] values = superRequest.getParameterValues(name);  
48
             
if

(values !=
null
&&values.length >
1
) {  

49
                 
for

(
int
i =
0
; i < values.length; i++) {    
50
                     
System.out.println(
"before: "
+name+
"["
+i+
"]="
+values[i]);  
51
                     
this
.addParameter(name,
new
String(values[i].getBytes(containerEncoding), encoding));                           
52
                     
System.out.println(
"after: "
+name+
"["
+i+
"]="
+
new

String(values[i].getBytes(containerEncoding), encoding));  

53
         
}    
54
      
}
else
{    
55
        
System.out.println(
"before: "
+name+
"="
+superRequest.getParameter(name)); 
56
        
this
.addParameter(name,
new
String(superRequest.getParameter(name).getBytes(containerEncoding), encoding));
57
 
58
        
System.out.println(
"after: "
+name+
"="
+
new

String(superRequest.getParameter(name).getBytes(containerEncoding), encoding));  
59
      
}
60
   
}             
61
    
if

(
this
.getModule() ==
null
&&
this
.getAction() ==
null
) {  
62
        
int

index = requestUri.indexOf(
'?'
);
63
        
if

(index > -
1
) {
64
            
requestUri = requestUri.substring(
0
, index); 
65
        
}
66
        
this
.parseFriendlyURL(requestUri, servletExtension);    
67
    
}
68
   
}    

69
 
}
 

然後在搜尋頁面上的關鍵字欄位輸入「中文」,然後按下搜尋,會出現下列的錯誤訊息:
An error has occurred.

For detailed error information, please see the HTML source code, and contact the forum Administrator.

org.apache.lucene.queryParser.ParseException: Cannot parse '': Encountered "EOF" at line 1, column 0.
Was expecting one of:
NOT ...
"+" ...
"-" ...
"(" ...
"*" ...
QUOTED ...
TERM ...
PREFIXTERM ...
WILDTERM ...
"[" ...
"{" ...
NUMBER ...

在Tomcat的logs目錄下的stdout.log檔案內可以發現到下列的資訊:
encoding=UTF-8
request.encoding=UTF-8
containerEncoding=ISO-8859-1
before: search_keywords=中文
after: search_keywords=??
before: module=search
after: module=search
before: sort_by=relevance
after: sort_by=relevance
before: match_type=all
after: match_type=all
before: action=search
after: action=search
before: search_forum=
after: search_forum=

可以發現,在做轉碼前我們get到的參數值是正確的,但在轉碼後就變成問號了,於是就變成Lucene剔除的符號字元,結果變成搜尋用的關鍵字串是空的。

修改方式就是在迴圈中判斷requestType是否為post,如果是(isPost == true)才轉碼,不然就用原來的值。 

view sourceprint?

01
for
(Enumeration e = superRequest.getParameterNames(); e.hasMoreElements();){    
02
     
String name = (String)e.nextElement();
03
     
String[] values = superRequest.getParameterValues(name);          
04
     
if

(values !=
null
&&values.length >
1
) {
05
         
for

(
int
i =
0
; i < values.length; i++) {                            
06
             
if

(isPost) {
07
                 
this
.addParameter(name,
new
String(values[i].getBytes(containerEncoding), encoding));    
08
             
}
else
09
                 
this
.addParameter(name, values[i]);    
10
             
}   
11
           
}    
12
     
}

else
{
13
         
if

(isPost) {  
14
             
this
.addParameter(name,
new
String(superRequest.getParameter(name).getBytes(containerEncoding), encoding));
15
         
}

else
{
16
            
this
.addParameter(name, superRequest.getParameter(name));
17
         
}
18
     
}    

19
 
}
 

這樣再去搜尋就可以了。

请问一个JFORUM 搜索的问题:

我发表新的主题贴后,LUCENCE可以搜索到,但是我把jforumLuceneIndex的索引删掉之后,JFORUM就不把原来的主题贴做索引引擎了 ,也就是从启动后新发表的主题贴才做索引引擎,请问要怎么修改代码才能够全部重新都做索引引擎

可以修改 net/jforum/search/LuceneReindexer.java

將 

1
luceneIndexer.batchCreate(post);
替代為 

1
luceneIndexer.create(post);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jforum问题 jforum