cms是对内容管理系统,第一个项目cms开发主要是对于企业网站多个模块进行curd操作,这其中包括了后台对于article文章模块slide轮播图模块等进行crud操作,并在前台页面进行展示。
整个项目的需求是在官网中的内容或者信息启用或者不启用均来自后台,需要做一个后台内容管理系统。
整个项目的架构属于bs架构,有前台页面的展示,和后台页面管理;在项目中我们用的技术选型为主要开发工具为eclipse,数据库用到mysql,后端框架ssm,前端框架jQuery、bootstrap、gridmanager等。
本次项目中分为article模块和slide轮播图模块,自选评论模块及问题展示模块和视频展示模块。
在article模块中前台页面运用gridmanager框架向后台发送数据,并接受后台发送回来的数据,展示到表格中。返回到前台是需要由totals和data数据,我在后台需要封装一个实体类pageBean作为对象将数据返回到前端。
在后台页面进行展示的时候我们根据对article判断,需要高级查询的字段,设计一个articleQurey实体类继承baseQuery,其中basequery是对当前页localpage和页长pagesize的封装;
在前端数据发送到后台之后,需要后台利用controller层进行逐一反向变成,再创建相关service层接口,并创建接口实现类;然后在创建mapper层中接口,最后在去mapper.xml文件中编写sql语句,其中在高级查询中需要用到动态查询语句。
<select id="findAll" resultType="cn.itsource.domain.Article">
select * from t_article
//引入sql语句
<include refid="query">include>
//进行分页处理
limit #{begin},#{pageSize}
select>
<sql id="query">
<where>
<if test="typeId != null">
and typeId = #{typeId}
if>
<if test="enable != null">
and enable = #{enable}
if>
<if test="title != null and !''.equals(title.trim())">
and title like concat ('%',trim(#{title}),'%')
if>
where>
sql>
对于article模块中的增删改:在后台页面中点击添加或者删除修改按钮时,触发点击事件弹出模态框,然后在进行相关操作
<div class="modal fade bs-example-modal-lg" id="saveModel">
<div class="modal-dialog modal-lg">
<div class="modal-content message_align">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×span>
button>
div>
<div class="modal-body">
<form action="/system/article/save" method="post"
class="form-horizontal" id="saveForm">
<input type="hidden" name="id" id="hid">
<div class="form-group row">
<label for="title" class="control-label col-md-3">文章标题label>
<div class="col-md-9">
<input class="form-control" type="text" name="title">
div>
div>
<div class="form-group row">
<label for="typeId" class="control-label col-md-3">文章类型label>
<div class="col-md-9">
<select name="typeId" class="form-control">
<c:forEach items="${list}" var="t">
<option value="${t.id}">${t.name}option>
c:forEach>
select>
div>
div>
<div class="form-group row">
<label for="enable" class="control-label col-md-3">是否启用label>
<div class="col-md-9">
<div class="form-check">
<label class="form-check-label"> <input
class="form-check-input" type="radio" checked="checked"
id="enable" name="enable" value="1">启用
label>
div>
<div class="form-check">
<label class="form-check-label"> <input
class="form-check-input" type="radio" name="enable" value="0">禁用
label>
div>
div>
div>
<div class="form-group row">
<label for="content" class="control-label col-md-3">文章内容label>
<div class="col-md-9">
<script id="container" name="content" type="text/plain">
这里写你的初始化内容
script>
div>
div>
form>
div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消button>
<a href='javascript:void(0);' id="saveButton"
class="btn btn-success">确定a>
div>
div>
div>
div>
<!--------------------------------------------------------------------!>
/* 绑定添加事件 */
$("#table-demo-ajaxPageCode").on("click","#addBtn",function(){
$("#saveForm")[0].reset();
$("#hid").val("");
//清空富文本内容
var ue = UE.getEditor('container');
$(document).ready(function () {
ue.ready(function () {
ue.setContent('');//赋值给UEditor
});
});
$("#saveModel").modal("show");
});
/* 绑定修改事件 */
$("#table-demo-ajaxPageCode").on("click","a[data-obj]",function(){
var objs = $(this).data("obj");
//console.debug(objs);
$("#saveForm").setForm(objs);
//回显富文本
var ue = UE.getEditor('container');
$(document).ready(function () {
ue.ready(function () {
ue.setContent(objs.content);//赋值给UEditor
});
});
$("#saveModel").modal("show");
});
$("#saveButton").on("click",function(){
$.ajax({
type:"post",
url:"/system/article/save",
data:$("#saveForm").serialize(),
dataType:"json",
success:function(msg){
if(msg.result){
$("#saveModel").modal("hide");
GridManager.refreshGrid("demo-ajaxPageCode");
}else{
alert(msg.msg)
}
}
});
})
在整个后台进行的curd操作中需要我们注意在模态框弹出时可能会因为没有对隐藏域或者模态框中的表单数据进行清空从而造成在修改时数据回显不对或者添加是进行之前序号那排数据的修改命令。
在完成后台管理系统页面的curd之后需要我们把后台数据展示到前台home网页中;我们需要home前台网页向后台发送请求全部查询并其返回一个list集合,然后通过前台遍历拼接,最终展示的前台。
在本项目中我们按照article不同类型分为了三种type:分别是technology、industry和subject。
<script>
$(function() {
// 发送请求
$.ajax({
type: "post",
url: "/home/article/list",
dataType: "json",
success: function(msg){
//console.debug(msg);
// 技术文章
var technology = msg.technology;
$.each(technology,function(i,obj){
var tec = '+obj.url+'">+obj.title+'">'+obj.createDate+' '
// 获取ul
/* console.debug(obj.url); */
$("#technology").append(tec);
});
// 行业新闻
var industry = msg.industry;
$.each(industry,function(i,obj){
var ind = '+obj.url+'">+obj.title+'">'+obj.createDate+' '
// 获取ul
$("#industry").append(ind);
});
// 学科咨询
var subject = msg.subject;
$.each(subject,function(i,obj){
var sub = '+obj.url+'">+obj.title+'">'+obj.createDate+' '
// 获取ul
$("#subject").append(sub);
});
}
});
// Title proxy.
$("#tech-zone .wrapper ul >a").each(function() {
$(this).attr("title", $(this).find(".ellipsis-line").attr("title"));
});
});
script>
注意在后台进行业务判断是我们需要知道在前台展示出来的文章enable属性都是启用状态,所以在sql语句中进行条件选择
@Override
public Map<String, Object> findAll() {
Map<String, Object> map = new HashMap<String, Object>();
List<Article> technology = articleMapper.findByCode(ArticleCode.TECHNOLOGY);
List<Article> industry = articleMapper.findByCode(ArticleCode.INDUSTRY);
List<Article> subject = articleMapper.findByCode(ArticleCode.SUBJECT);
map.put("technology", technology);
map.put("industry", industry);
map.put("subject", subject);
return map;
}
<select id="findByCode" resultType="cn.itsource.domain.Article">
select * from t_article t1, t_article_type t2 where t1.typeId=t2.id and
t2.code=#{code} and t1.enable=1 order by createDate desc limit 8
select>
前台展示出文章article列表之后,需要对相应数据进行静态化页面生成处理。这里我们运用到了freemarker框架,并对其进行封装。
public static String createFreeMarker(String templatepath,String pathName,Object data,String suffix){
FileWriter out = null;
try {
Configuration config = new Configuration(Configuration.VERSION_2_3_28);
File file = new File(templatepath);
config.setDirectoryForTemplateLoading(file);
config.setDefaultEncoding("utf-8");
Template template = config.getTemplate(pathName);
String url = System.currentTimeMillis()+suffix;
out = new FileWriter(new File(file, url));
template.process(data, out);
return url;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out!=null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
在静态化页面中浏览次数的实现我们是通过获取当前页面的url,然后后端通过url找到与之对应的数据,拿到clickCount之后对其进行+1操作,然后通过set方法修改article和修改数据库,并传送到前端页面展示出效果。
@Override
public Article findByUrl(String url) {
Article article= articleMapper.findByUrl(url);
Integer clickCount = article.getClickCount()+1;
article.setClickCount(clickCount);
articleMapper.update(article);
return article;
}
<script type="text/javascript">
$(function(){
var path = window.location.href;
var url = path.substring(path.lastIndexOf("/")+1);
$.ajax({
type:"post",
url:"/home/video/updateClickCount",
data:{
"url":url},
dataType:"json",
success:function(msg){
console.debug(msg);
$("#clickCount").html(msg.clickCount);
$("#path").html('msg.path+'" controls="controls">');
}
});
})
</script>
在这个项目中我们还涉及到了关于轮播图的curd和展示、在登录和注销操作通过session和cookie并对响应进行拦截。
在项目也出现了很多问题:
由于自己不造成的sql语句拼写错误,会导致操作数据是直接抛出异常;
相关小问题有很多,印象最深的问题是:java.lang.NoSuchMethodException:‘Arrearage’ on class 'class com.yunrun.swys.archives.domain.feedback’这个问题是我最近遇到的,
说的是在这个实体类里面有一个属性出问题了;
解决方法:我是使用的是在实体类中添加构造无参函数。
项目心得就是代码不仅要敲,还要有感情的去敲······