首先说明的一点,JForum3 Beta确实under heavy development,但功能上都是有的,需要自己做测试,并把所有Bug干掉。
一、技术架构
- MVC框架:Vraptor3.5
- 依赖注入:Spring 3.0.5
- 持久化:Hibernate 3.6.10
- 页面:jsp+jstl+el-functors+jQuery
- 全文检索:Hibernate Search 3.2.0
- Entities:不是我们常用的POJO,而类似于 业务对象 的概念,实体构造时注入了dao对象。
- 由于用了Vraptor,配置文件很少,全是约定。spring配置文件只用来引入SystemGlobals.properties,hibernate配置文件只配了数据库和映射。Vraptor本身没有配置文件。
@Entity
@Table(name = "jforum_categories")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Component
@PrototypeScoped
public class Category implements Serializable {
@Id
@SequenceGenerator(name = "sequence", sequenceName = "jforum_categories_seq")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "sequence")
@Column(name = "category_id")
private int id;
@Column(name = "category_order")
private int displayOrder;
@Column(name = "category_moderated")
private boolean moderated;
@Column(name = "category_title")
private String name;
@Transient
private CategoryRepository repository;
public Category() {}
@Autowired
public Category(CategoryRepository repository) {
this.repository = repository;
}
public List<Forum> getForums() {
return this.repository.getForums(this);
}
……
}
- 因为实体使用了@Entity注解,所以要有个无参的构造函数给Hibernate反射用。
- 因为在页面上会这么写"${category.forums}",通过EL表达式可以直接从实体对象的方法中拿数据,感觉很直接,所以实体里会有构造函数注入对应的DAO对象CategoryRepository。这与Vraptor有点交相呼应的意思,它的Controller里面也是构造函数注入所需要的一切。
- Vraptor3.5是不能完成2这件事的,因为有一个无参的构造函数,它会忽略掉其他的构造函数(详见这里)。所以用了Spring注解的方式在有参构造函数中注入了CategoryRepository,但这样出现了两个SessionFactory,一个是Vraptor的,一个是Spring的。这大概是JForum3最变态的地方了.....
- 为了能让Hibernate能用上已经注入了对象的Spring的Bean,所以SpringInterceptor横空出世:
public class SpringInterceptor extends EmptyInterceptor {
private final SessionFactory sessionFactory;
private final ApplicationContext beanRegistry;
public SpringInterceptor(ApplicationContext beanRegistry, SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
this.beanRegistry = beanRegistry;
}
@Override
public Object instantiate(String entityName, EntityMode entityMode, Serializable id) {
if (!EntityMode.POJO.equals(entityMode)) {
return null;
}
Class<?> c = getClassByName(entityName);
Object instance = this.beanRegistry.getBean(c);
sessionFactory.getClassMetadata(c).setIdentifier(instance, id, EntityMode.POJO);
return instance;
}
private Class<?> getClassByName(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
throw new ForumException(e);
}
}
}
二、具体问题
1.好好看一下Vraptor3.5的文档(http://vraptor.caelum.com.br/en/docs/one-minute-guide/)会节约你很多时间,文档精简的很,没多少。
2.包的问题,用Vraptor3.5里的包,大部分都有了。
3.从Hibernate3.2升级后,有一些小问题要改,最多的是uniqueResult()的结果是Long型,不能再转Integer了。
4.JForumTag里需要自己从springContext里拿Bean:
springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(this.pageContext().getServletContext());
5.页面有些小问题,改改链接就好了,zh_CN.properties里有些字段没有,补齐即可。
6.上传文件大小的问题,Vraptor3.5默认上传文件的大小是两兆,需要重新配置(用代码):
@Component
@ApplicationScoped
public class CustomMultipartConfig extends DefaultMultipartConfig{
public long getSizeLimit() {
return 50 * 1024 * 1024; // 50MB
}
}