源码免费下载地址:关注微信公众号“虾米聊吧”,回复关键字“博客”
推荐更完善功能更强大的java web个人博客系统高级版:https://blog.csdn.net/zwx19921215/article/details/102665020
最近利用闲暇时间简单重构了一个java web版本的个人博客系统项目(参考codingyun),属于前后端一体的项目,前端jsp,后端为springmvc + spring jdbc,简单易用好上手!
一个基本的个人博客系统包括:文章、分类、用户等基本功能。
目前设计的数据库表:文章表、分类表、系统用户表、前端用户表;(后续会继续完善)、
效果图如下:
前端文章列表展示页(风格样式我是参考的)
留言页
关于页面
文章详情页
后台登录页
后台管理
项目结构
文章管理Controller:
package com.xiaofeng.blog.action.system;
import com.google.gson.Gson;
import com.xiaofeng.blog.action.BaseController;
import com.xiaofeng.blog.entity.JsonResult;
import com.xiaofeng.blog.entity.PageBean;
import com.xiaofeng.blog.entity.QueryCondition;
import com.xiaofeng.blog.entity.bo.BlogArticleBo;
import com.xiaofeng.blog.entity.vo.BlogArticleVo;
import com.xiaofeng.blog.exception.ServiceException;
import com.xiaofeng.blog.service.BlogArticleService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/system/article")
public class SysArticleController extends BaseController {
private static Logger logger = Logger.getLogger(SysArticleController.class);
@Autowired
private BlogArticleService blogArticleService;
@RequestMapping(value = "", method = RequestMethod.GET)
public String getArticleList(HttpServletRequest request, QueryCondition queryCondition) throws Exception{
PageBean blogArticlePageBean = null;
try{
blogArticlePageBean = blogArticleService.getSysArticleList(queryCondition);
} catch (Exception e){
e.printStackTrace();
}
request.setAttribute("articleList", blogArticlePageBean !=null ? blogArticlePageBean.getDatas() : null);
request.setAttribute("pageInfo", blogArticlePageBean);
request.setAttribute("queryCondition" , queryCondition);
logger.info("get articleList size:" + blogArticlePageBean.getDatas().size());
return "system/blogArticleList";
}
@RequestMapping(value = "addArticle", method = RequestMethod.POST)
@ResponseBody
public Object addArticle(HttpServletRequest request, BlogArticleBo article){
logger.info("addArticle info:" + article.toString());
boolean flag = false;
String errorMessage = "新增文章成功!";
try{
flag = blogArticleService.addArticle(article);
}catch (ServiceException serviceE){
logger.error("addArticle failed!" , serviceE);
errorMessage = serviceE.getMessage();
}catch (Exception e){
logger.error("addArticle failed!" , e);
errorMessage = "新增文章失败!";
}
if(flag){
return "";
}
return "";
}
@RequestMapping(value = "updateArticle", method = RequestMethod.POST)
@ResponseBody
public Object updateArticle(HttpServletRequest request, BlogArticleBo article){
logger.info("updateArticle info:" + article.toString());
boolean flag = false;
String errorMessage = "修改文章成功!";
try{
flag = blogArticleService.updateArticle(article);
}catch (ServiceException serviceE){
logger.error("updateArticle failed!" , serviceE);
errorMessage = serviceE.getMessage();
}catch (Exception e){
logger.error("updateArticle failed!" , e);
errorMessage = "修改文章失败!";
}
if(flag){
return "";
}
return "";
}
@RequestMapping(value = "uploadJson", method = RequestMethod.POST)
@ResponseBody
public String uploadJson(HttpServletRequest request , HttpServletResponse response, BlogArticleVo blogArticleVo){
Map returnMap = new HashMap();
try {
returnMap.put("error", 0);
returnMap.put("url", blogArticleService.saveArticleImg(blogArticleVo));
} catch (Exception e) {
returnMap.put("error", 1);
returnMap.put("message", "图片格式不正确");
return new Gson().toJson(returnMap);
}
return new Gson().toJson(returnMap);
}
@RequestMapping(value = "getArticleByArticleId", method = RequestMethod.POST)
@ResponseBody
public String getArticleByArticleId(HttpServletRequest request, @RequestBody BlogArticleVo blogArticleVo) throws Exception{
JsonResult jsonResult = new JsonResult();
BlogArticleBo blogArticleBo = blogArticleService.getArticleById(blogArticleVo.getId());
jsonResult.setResultCode(0);
jsonResult.setResultMessage("获取文章内容成功");
jsonResult.setData(blogArticleBo);
return new Gson().toJson(jsonResult);
}
@RequestMapping(value = "del", method = RequestMethod.POST)
@ResponseBody
public String del(HttpServletRequest request,@RequestBody BlogArticleVo blogArticleVo){
logger.info("del info:" + blogArticleVo.toString());
boolean flag = false;
String errorMessage = "删除文章失败";
JsonResult jsonResult = new JsonResult();
try{
flag = blogArticleService.delArticle(blogArticleVo.getId());
}catch (ServiceException serviceE){
logger.error("del article failed!", serviceE);
errorMessage = serviceE.getMessage();
}catch (Exception e) {
logger.error("del article failed!", e);
}
jsonResult.setResultCode(flag ? 0 : 1);
jsonResult.setResultMessage(flag ? "删除文章成功" : errorMessage);
return new Gson().toJson(jsonResult);
}
}
文章管理service:
package com.xiaofeng.blog.service.impl;
import com.xiaofeng.blog.constant.ConstantUtil;
import com.xiaofeng.blog.dao.BlogArticleDao;
import com.xiaofeng.blog.entity.PageBean;
import com.xiaofeng.blog.entity.QueryCondition;
import com.xiaofeng.blog.entity.bo.BlogArticleBo;
import com.xiaofeng.blog.entity.vo.BlogArticleVo;
import com.xiaofeng.blog.service.BlogArticleService;
import com.xiaofeng.blog.service.UploadFileService;
import com.xiaofeng.blog.util.DateUtil;
import com.xiaofeng.blog.util.MD5Util;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.Date;
import java.util.List;
@Service
public class BlogArticleServiceImpl implements BlogArticleService {
private static final Logger logger = LoggerFactory.getLogger(BlogArticleServiceImpl.class);
@Autowired
private BlogArticleDao blogArticleDao;
@Autowired
private UploadFileService uploadFileService;
@Override
public PageBean getArticleList(QueryCondition queryCondition) throws Exception {
queryCondition.setPageSize("15");
return blogArticleDao.getArticleList(queryCondition);
}
@Override
public PageBean getSysArticleList(
QueryCondition queryCondition) throws Exception {
queryCondition.setPageSize("15");
return blogArticleDao.getSysArticleList(queryCondition);
}
@Override
public boolean siteMapFile(QueryCondition queryCondition) throws Exception {
List articleList = blogArticleDao.getArticleList(queryCondition).getDatas();
StringBuilder sb = new StringBuilder();
for (BlogArticleVo article : articleList) {
sb.append("http://www.xiaofeng.com/article/" + article.getId() + ".html");
sb.append("\r\n");
}
// File file = new File("F:"+File.separator+"test"+File.separator+"siteMap.txt");
File file = new File("/alidata/dataFile/sitemap.txt");
FileUtils.writeStringToFile(file, sb.substring(0, sb.length() - 2));
return true;
}
@Override
public PageBean getTagArticleList(
QueryCondition queryCondition, String tag) throws Exception {
return blogArticleDao.getTagArticleList(queryCondition, tag);
}
@Override
public PageBean getArticleList(int category, QueryCondition queryCondition)
throws Exception {
return blogArticleDao.getArticleList(category, queryCondition);
}
@Override
public boolean addArticle(BlogArticleBo article) throws Exception {
article.saveVlidate();
if (article.getContent().indexOf("", 200) > 0) {
article.setContentDesc(article.getContent().substring(0, article.getContent().indexOf("", 200)));
} else {
article.setContentDesc(article.getContent());
}
} else {
article.setContentDesc(article.getContent());
}
article.setContent(article.getContent().replace("
", "") + ConstantUtil.ARTICLE_FOOTER_ADD);
return blogArticleDao.addArticle(article);
}
@Override
public boolean updateArticle(BlogArticleBo article) throws Exception {
article.saveVlidate();
if (article.getContent().indexOf("", 200) > 0) {
article.setContentDesc(article.getContent().substring(0, article.getContent().indexOf("", 200)));
} else {
article.setContentDesc(article.getContent());
}
} else {
article.setContentDesc(article.getContent());
}
// article.setContent(article.getContent() + ConstantUtil.ARTICLE_FOOTER_ADD);
article.setContent(article.getContent().replace("
", ""));
return blogArticleDao.updateArticle(article, new String[]{"title", "content", "contentDesc", "category", "showFlag", "tag", "keyWords", "description"});
}
@Override
public boolean delArticle(int articleId) throws Exception {
return blogArticleDao.delArticle(articleId);
}
@Override
public BlogArticleVo getArticleById(int articleId) throws Exception {
BlogArticleVo article = blogArticleDao.getArticleById(articleId);
if (article != null) {
article.setUserReadCount(article.getUserReadCount() + 1);
BlogArticleBo articleBo = new BlogArticleBo();
BeanUtils.copyProperties(article, articleBo);
blogArticleDao.updateArticle(articleBo, "userReadCount");
}
return article;
}
@Override
public String saveArticleImg(BlogArticleVo blogArticleVo)
throws Exception {
String realPath = ConstantUtil.DATA_REAL_PATH_ARTICLE_IMG;
String path = ConstantUtil.SERVER_URL + "/articleDirectory/"; //www.xiaofeng.com/articleDirectory/supernatural.jpg
MultipartFile multipartFile = blogArticleVo.getImgFile();
String fileName = MD5Util.GetMD5Code("" + DateUtil.getTimeInMillis(new Date())) +
multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf("."));
logger.info("upload handout imgfile url:" + realPath);
uploadFileService.uploadFile(realPath, multipartFile, fileName);
return path + fileName;
}
}
文章管理Dao:
package com.xiaofeng.blog.dao.impl;
import com.xiaofeng.blog.dao.BlogArticleDao;
import com.xiaofeng.blog.dao.GeneralDao;
import com.xiaofeng.blog.entity.PageBean;
import com.xiaofeng.blog.entity.QueryCondition;
import com.xiaofeng.blog.entity.bo.BlogArticleBo;
import com.xiaofeng.blog.entity.vo.BlogArticleVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class BlogArticleDaoImpl implements BlogArticleDao {
private static Logger logger = LoggerFactory.getLogger(BlogArticleDaoImpl.class);
@Autowired
private GeneralDao generalDao;
@Override
public PageBean getArticleList(QueryCondition queryCondition) throws Exception {
return generalDao.getPageBeans(
BlogArticleVo.class,
" SELECT article.*, category.categoryName FROM blog_article article LEFT JOIN `category` category ON article.`category` = category.`id` WHERE article.showFlag = ? ORDER BY article.ID DESC ",
Integer.parseInt(queryCondition.getPageNo()),
Integer.parseInt(queryCondition.getPageSize()),
new Object[]{1});
}
@Override
public PageBean getSysArticleList(QueryCondition queryCondition) throws Exception {
return generalDao.getPageBeans(
BlogArticleVo.class,
" select * from blog_article ORDER BY ID DESC ",
Integer.parseInt(queryCondition.getPageNo()),
Integer.parseInt(queryCondition.getPageSize()),
new Object[]{});
}
@Override
public PageBean getTagArticleList(
QueryCondition queryCondition, String tag) throws Exception {
return generalDao.getPageBeans(
BlogArticleVo.class,
" SELECT article.*, category.categoryName FROM blog_article article LEFT JOIN `category` category ON article.`category` = category.`id` "
+ " WHERE article.showFlag = ? and article.tag like ? ORDER BY article.userReadCount DESC ",
Integer.parseInt(queryCondition.getPageNo()),
Integer.parseInt(queryCondition.getPageSize()),
new Object[]{1, "%"+ tag +"%"});
}
@Override
public PageBean getArticleList(int category, QueryCondition queryCondition)
throws Exception {
logger.info("getArticleList");
return generalDao.getPageBeans(
BlogArticleVo.class,
" SELECT article.*, category.categoryName FROM blog_article article LEFT JOIN `category` category ON article.`category` = category.`id` "
+ " WHERE article.showFlag = ? and article.category = ? ORDER BY article.ID DESC ",
Integer.parseInt(queryCondition.getPageNo()),
Integer.parseInt(queryCondition.getPageSize()),
new Object[]{1, category});
}
@Override
public boolean addArticle(BlogArticleBo article) throws Exception {
return generalDao.saveEntity(article);
}
@Override
public boolean updateArticle(BlogArticleBo article, String...updateFields) throws Exception {
return generalDao.updateEntity(article, updateFields);
}
@Override
public boolean delArticle(int articleId) throws Exception {
BlogArticleBo bo = new BlogArticleBo();
bo.setId(articleId);
return generalDao.delEntity(bo);
}
@Override
public BlogArticleVo getArticleById(int articleId) throws Exception {
return generalDao.getEntity(
BlogArticleVo.class,
" SELECT article.*, category.categoryName FROM blog_article article LEFT JOIN `category` category ON article.`category` = category.`id` WHERE article.id = ?",
new Object[]{articleId});
}
}
GeneralDaoImpl:
package com.xiaofeng.blog.dao.impl;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.xiaofeng.blog.constant.TableConstant;
import com.xiaofeng.blog.dao.GeneralDao;
import com.xiaofeng.blog.entity.PageBean;
import com.xiaofeng.blog.exception.DaoException;
import com.xiaofeng.blog.util.ObjectUtil;
import com.xiaofeng.blog.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.ArgumentPreparedStatementSetter;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterDisposer;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
@Repository
public class GeneralDaoImpl implements GeneralDao {
private static Logger logger = LoggerFactory.getLogger(GeneralDaoImpl.class);
/**
* 在讲解依赖注入的3种实现方式之前,这里先澄清一下依赖注入的意义:
* 让组件依赖于抽象,当组件要与其他实际对象发生依赖关系时,通过抽象来注入依赖的实际对象。
* 依赖注入的3种实现方式分别是:接口注入(interface injection)、Set注入(setter injection)和构造注入(constructor injection)。
*/
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public List getEntityList(Class beanClass, String sql, Object[] values) throws Exception{
List beanList = new ArrayList();
try{
beanList = jdbcTemplate.query(sql.toString(), BeanPropertyRowMapper.newInstance(beanClass), values);
}catch (DataAccessException e){
logger.error("GeneralDao getEntityList has failed!" + e);
}
return beanList;
}
@Override
public PageBean getPageBeans(Class beanClass, String sql, int pageNo, int pageSize, Object...objs) throws Exception{
PageBean page = new PageBean();
if(pageNo<1){
pageNo = 1;
}
if(pageSize<1){
pageSize = 10;
}
try {
sql = sql.toLowerCase();
String countsql = " select count(1) " + sql.substring(sql.indexOf("from"));
Integer count = jdbcTemplate.queryForObject(countsql, objs, Integer.class);
String limitsql = sql+" limit "+(pageNo-1)*pageSize +","+pageSize;
List dataList = (List) getEntityList(beanClass, limitsql, objs);
page.setPageNo(pageNo+"");
page.setPageSize(pageSize);
page.setRowsCount(count != null ? count.intValue() : 0);
page.setDatas(dataList);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
return page;
}
@Override
public T getEntity(Class beanClass, String sql, Object[] values)
throws Exception {
List beanList = null;
try{
// bean = jdbcTemplate.queryForObject(sql.toString(), BeanPropertyRowMapper.newInstance(beanClass), values);
beanList = jdbcTemplate.query(sql.toString(), BeanPropertyRowMapper.newInstance(beanClass), values);
}catch(EmptyResultDataAccessException e){
return null;
}catch(DataAccessException e){
logger.error("GeneralDao getEntity with sql has failed!"+ sql + e);
}
return beanList != null && beanList.size() > 0 ? beanList.get(0) : null;
}
/**
* 通过主键值查出对象
* @param beanClass
* @param primaryKeyValue 主键的值,根据该值查出对象数据
*/
@Override
public T getEntity(Class beanClass, Object primaryKeyValue) throws Exception{
T bean = null;
String tableName = TableConstant.TABLE_BEAN.get(beanClass.getName());
String primaryKey = TableConstant.TABLE_PRIMARY_KEY.get(tableName);
if(StringUtil.isEmpty(tableName)){
logger.info("对象实体bean未与数据库表名称映射,请维护TableConstant.java");
return null;
}
if(StringUtil.isEmpty(primaryKey)){
logger.info("数据库表名称未与表主键字段映射,请维护TableConstant.java");
return null;
}
StringBuilder sql = new StringBuilder(" select * from ");
sql.append(tableName).append(" where ").append(primaryKey).append(" = ? ");
try{
bean = jdbcTemplate.queryForObject(sql.toString(), BeanPropertyRowMapper.newInstance(beanClass), primaryKeyValue);
}catch(EmptyResultDataAccessException e){
logger.info("There is no result,Incorrect result size: expected 1, actual 0");
return null;
}catch (DataAccessException e){
logger.error("GeneralDao getEntity by primaryKeyValue has failed!" + e);
}
return bean;
}
/**
* 获取Map集合值
* @param sql
* @param obj
* @return
*/
@Override
public Map getMap(String sql,Object[] obj) throws Exception{
Map map = null;
try {
map = jdbcTemplate.queryForMap(sql, obj);
} catch (Exception e) {
logger.info("获取Map集合值失败!" + e);
throw new DaoException("数据库操作失败!",e);
}
return map;
}
@Override
public boolean delEntity(Object entity) throws Exception {
String tableName = TableConstant.TABLE_BEAN.get(entity.getClass().getName());
String primaryKey = TableConstant.TABLE_PRIMARY_KEY.get(tableName);
if(StringUtil.isEmpty(tableName)){
logger.info("对象实体bean未与数据库表名称映射,请维护TableConstant.java");
return false;
}
if(StringUtil.isEmpty(primaryKey)){
logger.info("数据库表名称未与表主键字段映射,请维护TableConstant.java");
return false;
}
StringBuilder sql = new StringBuilder(" delete from ");
sql.append(tableName).append(" where ");
sql.append(primaryKey).append(" = ? ");
List
以上是文章管理的大体实现,其它模块类同。
项目源码地址:http://www.zyshare.cn/resource/detail/2
qq群技术交流与支持:557911445
关注微信公众号“虾米聊吧”,后续持续放送“技术架构和资料”干货!!!
一个热衷于分享技术和生活的程序猿,让我们一起交流吧~
微信扫描二维码,关注我的公众号