这篇文章主要介绍了Jspxcms无侵入式二次开发的方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Jspxcms无侵入式二次开发的方法是什么文章都会有所收获,下面我们一起来看看吧。
第1章概述
作为通用的网站内容管理系统,只能尽可能的满足大部分需求,却很难满足所有的需求,这时就需要对系统进行二次开发。对于一些可以公用的二次开发程序可以做成插件,提供给其他开发者或客户使用。
1.1配置文件
1.1.1配置文件目录
/WEB-INF/classes/conf/plugin
二次开发的核心就是配置文件,通过配置文件将不同模块和插件整合到一起。所有的配置文件都必须在这个目录,在该目录下的配置文件会自动加载。
在该目录下新建自己的文件夹,可以是任何名字,如:abc、novel等,本例为plug。即/WEB-INF/classes/conf/plugin/plug。
1.1.2配置文件介绍
application.properties:功能菜单、权限、国际化、Entity都与这个文件相关。
context-dao.xml:Dao的加载。
context-service.xml:Service的加载。
controller-back.xml:后台Controller的加载。
controller-fore.xml:前台Controller的加载。
context-directive.xml:标签的加载。
1.2源代码包名
源代码可以放在任何包下,只要与配置文件中设置相对应即可。
本例为:com.jspxcms.plug。
1.3后台JSP文件
后台JSP文件的根目录为:/WEB-INF/views。
详细的路径取决于Controller返回的地址,如返回plug/resume/resume_list,则对应的JSP文件为:/WEB-INF/views/plug/resume/resume_list.jsp。
本例的后台JSP所在目录:/WEB-INF/views/plug/resume
1.4前台模版文件
前台模版使用freemarker技术,模版根目录为:/template/1/default。
其中1是站点ID。default是模版主题,后台“系统-网站设置-基本设置”可以修改本项设置(前提是/template/1目录下有多个文件夹)。
本例的前台模版是:/template/1/default/plug_resume.html。该地址取决于Controller返回地址。
1.5国际化文件
编辑和查看国际化文件,请安装Eclipse的PropertiesEditor插件。否则不能看到中文,只能看到\u5217\u8868之类的代码;编辑时直接输入中文,则会出现乱码。
国际化文件根目录为:/WEB-INF/messages。
本例的国际化路径为:/WEB-INF/messages/plugin。
第2章菜单和权限
菜单和权限是插件(二次)开发的最核心的部分,也是最难做到无缝整合的部分。大部分系统会将菜单信息保存到数据库中,这对升级和维护带来一定的困难。
Jspxcms的菜单和权限信息存放在配置中,方便管理、维护和升级;只需要在一个配置文件中设置好,即可以无缝整合系统的菜单、权限、赋权等问题,无需另外修改代码和页面。
开发时可以根据需要,将新功能菜单加到任意的一级菜单下的任意位置,也可以自己新增一级菜单,新增的一级菜单也可以放在任何你想要的位置上。
2.1菜单介绍
Jspxcms系统菜单分为两级。
一级菜单:
二级菜单:
2.2配置文件
配置文件为:application.properties
在本例中的完整路径:/WEB-INF/classes/conf/plugin/plug/application.properties
与菜单和权限相关的配置内容(分号为分割符):
menu.650=navigation.plug;nav.do?menuId=650;nav_plug
menu.650.100=resume.management;plug/resume/list.do;plug:resume:list;create@plug:resume:create;copy@plug:resume:copy;edit@plug:resume:edit;save@plug:resume:save;update@plug:resume:update;delete@plug:resume:delete
menu.650.200=dbBackup.management;plug/db_backup/list.do;plug:db_backup:list;dbBackup.backup@plug:db_backup:backup;dbBackup.restore@plug:db_backup:restore;delete@plug:workflow_group:delete
2.2.1一级菜单配置
配置分为三部分:菜单位置及名称、菜单链接地址、权限值。
菜单位置及名称
menu.650=navigation.plug
650:是后台导航一级菜单的编号,编号大小决定菜单的前后位置。其值可以根据需要调整,如330、970,但不要与系统菜单或其他插件菜单重复。系统菜单通常为menu.100、menu.200、menu.600等,系统菜单定义文件在/WEB-INF/classes/conf/application-menu.properties。
navigation.plug:菜单名称。这里使用了国际化代码,也可以直接用中文,比如“menu.650=我的插件”。(在properties文件中直接写中文,需要安装PropertiesEditor插件,否则会出现乱码)
菜单链接地址
nav.do?menuId=650
其中650需与menu.650的值一样。
权限值
nav_plug
其中plug通常与配置文件目录名称一样。如目录为abc,则应为nav_abc。也可不一样,但不能与其他一级菜单权限名称一样。
2.2.2二级菜单配置
配置分为四部分:菜单位置及名称、菜单链接地址、菜单权限值、功能名称及权限值。
菜单位置及名称
menu.650.100=resume.management
650:二级菜单所属的一级菜单编号。
100:二级菜单编号。其值的意义和一级菜单编号一样,用于确定二级菜单的前后位置。
resume.management:二级菜单名称。可以直接用中文,如“小说管理”。
菜单链接地址
plug/resume/list.do
需与Controller中的地址对应,否则会找不到页面。
菜单权限值
plug:resume:list
需与Controller中list方法的权限对应,否则会报没有权限。
功能名称及权限值
create@plug:resume:create;copy@plug:resume:copy;edit@plug:resume:edit;save@plug:resume:save;update@plug:resume:update;delete@plug:resume:delete
create@plug:resume:create:新增按钮的权限值。其中create是国际化代码,可以用直接用中文,如“新增@plug:resume:create”。其中plug:resume:create是该按钮的权限值,需与Controller中对应的create方法权限值一致。
edit@plug:resume:edit:意义和上面一样,后面的以此类推。
2.2.3菜单配置与权限管理
按照上面步骤设置好菜单之后,权限管理部分就会读取配置文件,无需修改权限管理页面及代码。
第3章Controller
Controller是MVC中的控制部分,主要的功能是接收客户端提交的请求,然后调用Service的功能及获取数据,最后返回View(视图,即JSP或freemarker页面)。
在Jspxcms中,Controller分为前台和后台。前台是普通用户浏览的页面,使用freemarker作为视图,通常不需要登录,比如网站首页、栏目页、专题页、搜索页等;后台一般为管理功能,使用JSP作为视图,需要管理员登录后台,才能访问。
3.1配置文件
3.1.1后台配置文件
/WEB-INF/classes/conf/plugin/plug/controller-back.xml。
其中com.jspxcms.plug.web.back是后台Controller所在包,在这个包下的Controller都会被spring扫描到。
3.1.2前台配置文件
/WEB-INF/classes/conf/plugin/plug/controller-fore.xml。
其中com.jspxcms.plug.web.fore是前台Controller所在包,在这个包下的Controller都会被spring扫描到。
3.2后台Controller类
packagecom.jspxcms.plug.web.back;
@Controller
@RequestMapping("/plug/resume")
public classResumeController {
@RequiresPermissions("plug:resume:list")
@RequestMapping("list.do")
public String list(
@PageableDefaults(sort ="id", sortDir = Direction.DESC) Pageable pageable,
HttpServletRequest request,org.springframework.ui.Model modelMap) {
Integer siteId =Context.getCurrentSiteId(request);
Map<String, String[]>params = Servlets.getParameterValuesMap(request,
Constants.SEARCH_PREFIX);
Page<Resume>pagedList = service.findAll(siteId, params, pageable);
modelMap.addAttribute("pagedList",pagedList);
return"plug/resume/resume_list";
}
@RequiresPermissions("plug:resume:create")
@RequestMapping("create.do")
public Stringcreate(Integer id, org.springframework.ui.Model modelMap) {
if (id != null) {
Resume bean =service.get(id);
modelMap.addAttribute("bean",bean);
}
modelMap.addAttribute(OPRT,CREATE);
return"plug/resume/resume_form";
}
@Autowired
private ResumeServiceservice;
}
其中RequestMapping为访问地址,RequiresPermissions为权限代码,需与application.properties中的菜单权限配置相吻合。
3.3前台Controller类
packagecom.jspxcms.plug.web.fore;
@Controller
public classResumeController {
public static final StringTEMPLATE = "plug_resume.html";
@RequestMapping(value ="/resume.jspx")
public StringresumeForm(Integer page, HttpServletRequest request,
org.springframework.ui.ModelmodelMap) {
Site site =Context.getCurrentSite(request);
Map<String, Object>data = modelMap.asMap();
ForeContext.setData(data,request);
ForeContext.setPage(data,page);
returnsite.getTemplate(TEMPLATE);
}
@RequestMapping(value ="/resume.jspx", method = RequestMethod.POST)
public StringresumeSubmit(@Valid Resume bean, HttpServletRequest request,
HttpServletResponseresponse, org.springframework.ui.Model modelMap) {
Response resp = newResponse(request, response, modelMap);
Site site =Context.getCurrentSite(request);
service.save(bean,site.getId());
return resp.post();
}
@Autowired
private ResumeServiceservice;
}
第4章Entity
4.1配置文件
/WEB-INF/classes/conf/plugin/plug/application.properties
entityManagerFactory.packagesToScan.plug=com.jspxcms.plug.domain
plug:通常与配置文件所在目录一样,也可不一样,但不能与其他相关配置同名。
com.jspxcms.plug.domain:Entity所在包名。
4.2数据库表
不使用主键自增策略,将主键放到数据库中的一个表里。
create table plug_resume
(
f_resume_id intnot null,
f_site_id intnot null,
f_name varchar(100) not null comment '姓名',
f_post varchar(100) not null comment '应聘职位',
f_creation_date datetime not null comment '投递日期',
f_gender char(1) not null default 'M' comment '性别',
f_birth_date datetime comment '出生日期',
f_mobile varchar(100) comment '手机',
f_email varchar(100) comment '邮箱',
f_expected_salary intcomment '期望薪水',
f_education_experiencelongtext comment '教育经历',
f_work_experience longtext comment '工作经历',
f_remark longtext comment '备注',
primary key(f_resume_id)
)
engine = innodb;
alter table plug_resumecomment '简历表';
alter table plug_resume addconstraint fk_plug_resume_site foreign key (f_site_id)
references cms_site(f_site_id) on delete restrict on update restrict;
4.3实体类
需注意以下三个值,其中plug_resume为表名:
name= "tg_plug_resume", pkColumnValue = "plug_resume"
generator= "tg_plug_resume"
@Entity
@Table(name ="plug_resume")
public class Resumeimplements java.io.Serializable {
private Integer id;
……
@Id
@Column(name ="f_resume_id", unique = true, nullable = false)
@TableGenerator(name ="tg_plug_resume", pkColumnValue = "plug_resume",table = "t_id_table", pkColumnName = "f_table",valueColumnName = "f_id_value", initialValue = 1,allocationSize = 1)
@GeneratedValue(strategy =GenerationType.TABLE, generator = "tg_plug_resume")
public Integer getId() {
return this.id;
}
public void setId(Integerid) {
this.id = id;
}
……
}
第5章DAO
5.1配置文件
/WEB-INF/classes/conf/plugin/plug/context-dao.xml
<jpa:repositoriesbase-package="com.jspxcms.plug.repository"
transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory"
factory-class="com.jspxcms.common.orm.MyJpaRepositoryFactoryBean"
repository-impl-postfix="Impl">
</jpa:repositories>
其中com.jspxcms.plug.repository为dao接口所在包。
5.2DAO类
Dao使用了SpringDataJPA技术。
SpringDataJPA官网:http://projects.spring.io/spring-data-jpa/
packagecom.jspxcms.plug.repository;
public interface ResumeDaoextends Repository<Resume, Integer>, ResumeDaoPlus {
public Page<Resume>findAll(Specification<Resume> spec, Pageable pageable);
public List<Resume>findAll(Specification<Resume> spec, Limitable limitable);
public ResumefindOne(Integer id);
public Resume save(Resumebean);
public void delete(Resumebean);
}
ResumeDao接口中的方法不用实现。以下接口中的方法均可放到ResumeDao,且无需实现:
org.springframework.data.repository.CrudRepository
org.springframework.data.repository.PagingAndSortingRepository
org.springframework.data.jpa.repository.JpaRepository
com.jspxcms.common.orm.MyJpaRepository
需要实现的dao方法,放到ResumeDaoPlus接口中。
packagecom.jspxcms.plug.repository;
public interfaceResumeDaoPlus {
public List<Resume>getList(Integer[] siteId, Limitable limitable);
}
packagecom.jspxcms.plug.repository.impl;
public class ResumeDaoImplimplements ResumeDaoPlus {
@SuppressWarnings("unchecked")
public List<Resume>getList(Integer[] siteId, Limitable limitable) {
JpqlBuilder jpql = newJpqlBuilder();
jpql.append("fromResume bean where 1=1");
if(ArrayUtils.isNotEmpty(siteId)) {
jpql.append(" andbean.site.id in (:siteId)");
jpql.setParameter("siteId",Arrays.asList(siteId));
}
return jpql.list(em,limitable);
}
private EntityManager em;
@PersistenceContext
public voidsetEm(EntityManager em) {
this.em = em;
}
}
其中JpqlBuilder用于拼装jqpl语句、设置参数,并可处理分页问题。
com.jspxcms.common.orm.JpqlBuilder
第6章Service
6.1配置文件
/WEB-INF/classes/conf/plugin/plug/context-service.xml
<context:component-scanbase-package="com.jspxcms.plug.service.impl">
<context:exclude-filtertype="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
其中com.jspxcms.plug.service.impl为Service的实现类所在包。
packagecom.jspxcms.plug.service.impl;
@Service
@Transactional(readOnly =true)
public classResumeServiceImpl implements ResumeService {
public Page<Resume>findAll(Integer siteId, Map<String, String[]> params,
Pageable pageable) {
returndao.findAll(spec(siteId, params), pageable);
}
public RowSide<Resume>findSide(Integer siteId,
Map<String, String[]>params, Resume bean, Integer position,
Sort sort) {
if (position == null) {
return newRowSide<Resume>();
}
Limitable limit =RowSide.limitable(position, sort);
List<Resume> list =dao.findAll(spec(siteId, params), limit);
returnRowSide.create(list, bean);
}
privateSpecification<Resume> spec(final Integer siteId,
Map<String, String[]>params) {
Collection<SearchFilter>filters = SearchFilter.parse(params).values();
finalSpecification<Resume> fsp = SearchFilter.spec(filters,
Resume.class);
Specification<Resume>sp = new Specification<Resume>() {
public PredicatetoPredicate(Root<Resume> root,
CriteriaQuery<?>query, CriteriaBuilder cb) {
Predicate pred =fsp.toPredicate(root, query, cb);
if (siteId != null) {
pred = cb.and(pred,cb.equal(root.get("site")
.<Integer>get("id"), siteId));
}
return pred;
}
};
return sp;
}
private ResumeDao dao;
@Autowired
public voidsetDao(ResumeDao dao) {
this.dao = dao;
}
}
该类使用到JPA的Specification查询方式。
可实现后台列表点击表头,按任意列排序;列表页按任意字段查询;编辑页面上一条、下一条功能。
第7章标签
7.1配置文件
/WEB-INF/classes/conf/plugin/plug/controller-back.xml
<beanid="PlugResumeList"
class="com.jspxcms.plug.web.directive.ResumeListDirective"/>
在/WEB-INF/classes/conf/plugin/plug/application.properties中加上配置:
freemarkerVariables.ResumeList=PlugResumeList
其中ResumeList为标签名。
7.2标签类
packagecom.jspxcms.plug.web.directive;
public classResumeListDirective implements TemplateDirectiveModel {
public static final StringSITE_ID = "siteId";
@SuppressWarnings({"rawtypes", "unchecked" })
public voidexecute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBodybody) throws TemplateException, IOException {
if (loopVars.length <1) {
throw newTemplateModelException("Loop variable is required.");
}
if (body == null) {
throw newRuntimeException("missing body");
}
Integer[] siteId =Freemarkers.getIntegers(params, SITE_ID);
if (siteId == null &¶ms.get(SITE_ID) == null) {
siteId = new Integer[] {ForeContext.getSiteId(env) };
}
Sort defSort = newSort(Direction.DESC, "creationDate", "id");
Limitable limitable =Freemarkers.getLimitable(params, defSort);
List<Resume> list =service.findList(siteId, limitable);
loopVars[0] =env.getObjectWrapper().wrap(list);
body.render(env.getOut());
}
@Autowired
private ResumeServiceservice;
}
第8章国际化
8.1配置
在/WEB-INF/classes/conf/plugin/plug/application.properties中加上如下配置:
后台国际化文件
messageSource.basenames.plug=/WEB-INF/messages/plugin/plug/plug
前台国际化文件
messageSource.basenames.plugfore=/WEB-INF/messages/plugin/plugfore/plugfore
其中messageSource.basenames.plug中的plug通常为配置文件所在文件夹的名称,可以改为其他名字,但不能与其他相关配置重名。
8.2国际化文件
/WEB-INF/messages/plugin/plug/plug为国际化文件所在文件夹和文件名。
关于“Jspxcms无侵入式二次开发的方法是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Jspxcms无侵入式二次开发的方法是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。