目录
UEditor
UEditor 是由百度 web 前端研发部开发所见即所得富文本web编辑器,具有轻量、可定制、注重用户体验等特点。
首先去https://github.com/fex-team/ueditor下载UEditor,然后将文件拷贝至项目中。
接下来通过一个Demo对UEditor进行测试。
通过Controller的TestDemo进行测试。
-
@Controller
-
public
class TestController {
-
-
@RequestMapping("/ueTest")
-
public String test(){
-
return
"ueditortest";
-
}
-
}
新建一个ueditorTest.jsp,在body中调用js
-
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
-
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
<%@ taglib prefix="fm" uri="http://java.sun.com/jsp/jstl/functions" %>
-
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
-
<%
-
String path = request.getContextPath();
-
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
-
%>
-
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
<html>
-
-
<head>
-
<title>富文本编辑器测试
</title>
-
</head>
-
-
<body class="gray-bg">
-
<script id="container" name="content" type="text/plain">这里写你的初始化内容
</script>
-
<script type="text/javascript" src="<%=basePath%>js/ueditor1_4_3/ueditor.config.js">
</script>
-
<script type="text/javascript" src="<%=basePath%>js/ueditor1_4_3/ueditor.all.js">
</script>
-
<!-- 实例化编辑器 -->
-
<script type="text/javascript">
-
var ue = UE.getEditor(
'container');
-
</script>
-
</body>
-
-
</html>
此外,为了加载网页中的静态资源,如图片,js,css,需要对servlet进行配置:
根据自己的服务器选择不同包下的DefaultServlet
-
<?xml version="1.0" encoding="UTF-8"?>
-
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xmlns=
"http://java.sun.com/xml/ns/javaee"
-
xsi:schemaLocation=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
-
version=
"2.5">
-
-
<context-param>
-
<param-name>contextConfigLocation
</param-name>
-
<param-value> classpath:spring-core.xml
</param-value>
-
</context-param>
-
<listener>
-
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
-
</listener>
-
-
<servlet>
-
<servlet-name>Blog
</servlet-name>
-
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
-
<init-param>
-
<param-name>contextConfigLocation
</param-name>
-
<param-value>classpath:spring-mvc.xml
</param-value>
-
</init-param>
-
</servlet>
-
<servlet-mapping>
-
<servlet-name>Blog
</servlet-name>
-
<url-pattern>/
</url-pattern>
-
</servlet-mapping>
-
-
-
<!-- 静态资源的加载-->
-
<servlet>
-
<servlet-name>default
</servlet-name>
-
<!--jetty容器-->
-
<!-- <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>-->
-
<!--Tomcat容器-->
-
<servlet-class>org.apache.catalina.servlets.DefaultServlet
</servlet-class>
-
<init-param>
-
<param-name>debug
</param-name>
-
<param-value>0
</param-value>
-
</init-param>
-
<init-param>
-
<param-name>listings
</param-name>
-
<param-value>false
</param-value>
-
</init-param>
-
<load-on-startup>1
</load-on-startup>
-
</servlet>
-
-
-
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.jpg
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.js
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.css
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.png
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.woff2
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.woff3
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.ttf
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.woff
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.gif
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.map
</url-pattern>
-
</servlet-mapping>
-
<servlet-mapping>
-
<servlet-name>default
</servlet-name>
-
<url-pattern>*.html
</url-pattern>
-
</servlet-mapping>
-
-
</web-app>
启动服务器后如下图,就说明配置成功,接下来就可以对UEditor进行编程了。
博客内容提交与展示功能测试
jsp页面:新增页面:add_ueditor 详情页:ueditor_detail
controller方法:add addContent detail
运行流程:
/add -> add方法 ->add_ueditor.jsp ->提交按钮->/addContent->detail
Controller开发
-
package com.tulun.controller;
-
-
import org.springframework.stereotype.Controller;
-
import org.springframework.ui.Model;
-
import org.springframework.web.bind.annotation.RequestMapping;
-
-
@Controller
-
@RequestMapping("/test")
-
public
class TestController {
-
private String context ;
-
-
@RequestMapping("/add")
-
public String test(){
-
return
"add_ueditor";
-
}
-
-
//点击保存按钮,将内容提交到后台
-
@RequestMapping("/addContent")
-
public String addContent(String description,String content) {
-
System.out.println(
"content:"+content);
-
System.out.println(
"description:"+description);
-
context = content;
-
-
return
"redirect:/test/detail";
-
}
-
-
//详情页面
-
@RequestMapping("/detail")
-
public String detail(Model model){
-
model.addAttribute(
"content", context);
-
return
"ueditor_detail";
-
}
-
}
新增博客页面add_ueditor.jsp
页面中新增两个按钮,点击提交按钮调用js中的saveArticle方法进行提交
-
<%@ page language="java" contentType="text/html; charset=UTF-8" import="java.util.*" %>
-
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
<%@ taglib prefix="fm" uri="http://java.sun.com/jsp/jstl/functions" %>
-
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
-
<% String path = request.getContextPath();
-
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
-
%>
-
-
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-
<html>
-
<head>
-
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
-
<link href="<%=basePath%>css/bootstrap.min.css" rel="stylesheet">
-
<link href="<%=basePath%>css/style.css" rel="stylesheet">
-
<title>新增博客
</title>
-
</head>
-
<body>
-
<div class="ibox-content">
-
<form method="get" class="form-horizontal">
-
<div class="hr-line-dashed">
</div>
-
<div class="form-group">
-
<label class="col-sm-2 control-label">内容:
</label>
-
<div class="col-sm-10">
-
<script id="editor" type="text/plain">
</script>
-
</div>
-
</div>
-
-
<div class="form-group">
-
<div class="col-sm-4 col-sm-offset-2">
-
<button class="btn btn-primary" type="button" onclick="saveArticle()">保存内容
</button>
-
<button class="btn btn-white" type="button" onclick="cancelSaveArticle()">取消
</button>
-
</div>
-
</div>
-
</form>
-
</div>
-
-
<!-- Mainly scripts -->
-
<script src="<%=basePath%>js/jquery-2.1.1.min.js">
</script>
-
<script src="<%=basePath%>js/bootstrap.min.js">
</script>
-
<%--自定义js--%>
-
<script src="<%=basePath%>js/article/add_article_test.js">
</script>
-
<!-- 配置文件 -->
-
<script type="text/javascript" src="<%=basePath%>js/ueditor1_4_3/ueditor.config.js">
</script>
-
<!-- 编辑器源码文件 -->
-
<script type="text/javascript" src="<%=basePath%>js/ueditor1_4_3/ueditor.all.js">
</script>
-
<script type="text/javascript" charset="utf-8" src="<%=basePath%>js/ueditor1_4_3/lang/zh-cn/zh-cn.js">
</script>
-
<script src="<%=basePath%>js/plugins/chosen/chosen.jquery.js">
</script>
-
-
<script type="text/javascript">
-
$(
document).ready(
function () {
-
var ue = UE.getEditor(
'editor');
-
})
-
-
// 初始化多选框
-
$(
".chosen-select").chosen({
-
max_selected_options:
5,
-
no_results_text:
"没有找到",
-
allow_single_deselect:
true
-
});
-
-
</script>
-
</body>
-
</html>
在js文件中对saveArticle进行编写,获取到编辑器的内容,通过post方式进行提交,提交成功就跳转至detail进行显示,失败就返回add界面重新进行添加。
-
// 保存文章
-
function saveArticle(){
-
var arr = [];
-
//获取输入的内容 getContent() (包含和页面相关的标签)
-
arr.push(UE.getEditor(
'editor').getContent());
-
var content = arr.join(
"\n");
-
// alert(content);
-
-
// 简介 (getContentTxt() 获取纯文本内容,并且只截取前10个字)
-
var description = UE.getEditor(
'editor').getContentTxt().substring(
0,
10);
-
-
// 保存文章
-
$.ajax({
-
type :
"POST",
-
url :
'../test/addContent',
//提交内容用这个URL
-
data :
"content="+content+
"&description="+description,
-
success :
function(data) {
-
if(data.resultCode !=
'success'){
-
//成功了就显示详情
-
console.log(
"sssssss"+content);
-
window.location.href =
"../test/detail";
-
autoCloseAlert(data.errorInfo,
1000);
-
return
false;
-
}
else{
-
alert(
"失败哦");
-
// 重新添加
-
window.location.href =
"../test/add";
-
}
-
}
-
});
-
}
-
-
//取消后跳转到add
-
function cancelSaveArticle(){
-
window.location.href =
"../test/add";
-
}
博客详情界面detail.jsp
用$获取到content的值,然后显示在页面上。
-
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
-
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
-
<%
-
String path = request.getContextPath();
-
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
-
%>
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
<html>
-
<head>
-
<link rel="stylesheet" id="main-css" href="<%=basePath%>css/demo/style.css" type="text/css" media="all">
-
<title>博客详情
</title>
-
</head>
-
<body id="contain" class="home blog ui-c3">
-
<div class="content">
-
<article class="article-content">
-
${content}
-
</article>
-
</div>
-
</body>
-
-
</html>
网页界面:
后台打印输入:
博客新增和展示详情功能开发
- 博客新增页面:该页面主要用于新增一篇博客,其中包含了博客类别(可选择已有类别)、博客标签(可选择已有标签)、标题以及内容。
- 展示详情:标题、标签、类别、内容、作者以及发布时间
博客存储
博客内容一般较大,肯定不能用常规数据类型进行存储,因此可以使用MySQL提供的blog类型进行存储,根据具体需求选择不同的类型。
- .tinyblog:仅256个字符
- .blog 最大限制65k字节
- .mediumblog:限制16M字节
- .logblog:限制4G
博客标题开发
标签POJO类
-
package com.tulun.model;
-
-
/**
-
* Description :
-
* Created by Resumebb
-
* Date :2021/4/27
-
*/
-
public
class Tag {
-
private Integer id;
-
private String tagName;
-
-
public Integer getId() {
-
return id;
-
}
-
-
public void setId(Integer id) {
-
this.id = id;
-
}
-
-
public String getTagName() {
-
return tagName;
-
}
-
-
public void setTagName(String tagName) {
-
this.tagName = tagName;
-
}
-
-
}
TagMapper
定义一个接口获取全部tag
-
public
interface TagMapper {
-
public List<Tag> getAllTag();
-
}
TagService
-
package com.tulun.service;
-
-
import com.tulun.dao.TagMapper;
-
import com.tulun.model.Tag;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.stereotype.Service;
-
-
import java.util.List;
-
-
/**
-
* Description :
-
* Created by Resumebb
-
* Date :2021/4/27
-
*/
-
@Service
-
public
class TagService {
-
@Autowired
-
private TagMapper tagMapper;
-
public List<Tag> selectAllTag(){
-
return tagMapper.getAllTag();
-
}
-
}
映射文件TagMapper.xml
从t_tag表中查询所有数据,做一个映射
-
<?xml version="1.0" encoding="UTF-8" ?>
-
<!DOCTYPE mapper
-
PUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
-
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
<mapper namespace="com.tulun.dao.TagMapper">
-
<select id="getAllTag" resultType="com.tulun.model.Tag">
-
select * from t_tag
-
</select>
-
</mapper>
博客类别开发
与标签开发过程一样,分别进行配置。
类别POJO类
-
package com.tulun.model;
-
-
/**
-
* Description :
-
* Created by Resumebb
-
* Date :2021/4/27
-
*/
-
public
class Category {
-
private Integer id;
-
private String categoryName;
-
-
public Integer getId() {
-
return id;
-
}
-
-
public void setId(Integer id) {
-
this.id = id;
-
}
-
-
public String getCategoryName() {
-
return categoryName;
-
}
-
-
public void setCategoryName(String categoryName) {
-
this.categoryName = categoryName;
-
}
-
}
CategoryMapper
-
public
interface CategoryMapper {
-
public List<Category> getAllCategory();
-
}
CategoryService
-
@Service
-
public
class CategoryService {
-
@Autowired
-
private CategoryMapper categoryMapper;
-
public List<Category> selectAllCategory(){
-
return categoryMapper.getAllCategory();
-
}
-
}
CategoryMapper.xml
查询t_category表中的数据
-
<?xml version="1.0" encoding="UTF-8" ?>
-
<!DOCTYPE mapper
-
PUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
-
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
<mapper namespace="com.tulun.dao.CategoryMapper">
-
<select id="getAllCategory" resultType="com.tulun.model.Category">
-
select * from t_category
-
</select>
-
</mapper>
博客内容开发
首先创建对应的POJO类,所有元素均与数据库一一对应
类别POJO类
-
package com.tulun.model;
-
-
import java.util.Date;
-
-
/**
-
* Description :
-
* Created by Resumebb
-
* Date :2021/4/27
-
*/
-
public
class Article {
-
private Integer id;
-
private Integer categoryId;
-
private String title;
-
private String content;
-
private String decription;
-
private Integer status;
-
private String author;
-
private Date createTime;
-
private Integer showCount;
-
-
public Integer getId() {
-
return id;
-
}
-
-
public void setId(Integer id) {
-
this.id = id;
-
}
-
-
public Integer getCategoryId() {
-
return categoryId;
-
}
-
-
public void setCategoryId(Integer categoryId) {
-
this.categoryId = categoryId;
-
}
-
-
public String getTitle() {
-
return title;
-
}
-
-
public void setTitle(String title) {
-
this.title = title;
-
}
-
-
public String getContent() {
-
return content;
-
}
-
-
public void setContent(String content) {
-
this.content = content;
-
}
-
-
public String getDecription() {
-
return decription;
-
}
-
-
public void setDecription(String decription) {
-
this.decription = decription;
-
}
-
-
public Integer getStatus() {
-
return status;
-
}
-
-
public void setStatus(Integer status) {
-
this.status = status;
-
}
-
-
public String getAuthor() {
-
return author;
-
}
-
-
public void setAuthor(String author) {
-
this.author = author;
-
}
-
-
public Date getCreateTime() {
-
return createTime;
-
}
-
-
public void setCreateTime(Date createTime) {
-
this.createTime = createTime;
-
}
-
-
public Integer getShowCount() {
-
return showCount;
-
}
-
-
public void setShowCount(Integer showCount) {
-
this.showCount = showCount;
-
}
-
-
@Override
-
public String toString() {
-
return
"Article{" +
-
"id=" + id +
-
", catagoryId=" + categoryId +
-
", title='" + title +
'\'' +
-
", content='" + content +
'\'' +
-
", decription='" + decription +
'\'' +
-
", status=" + status +
-
", author='" + author +
'\'' +
-
", createTime=" + createTime +
-
", showCount=" + showCount +
-
'}';
-
}
-
}
ArticleMapper.xml
返回类型采用resultMap类型,这里使用到了一个类型转换的处理器类ConvertBlobTypeHandler
-
<?xml version="1.0" encoding="UTF-8" ?>
-
<!DOCTYPE mapper
-
PUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
-
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
<mapper namespace="com.tulun.dao.ArticleMapper">
-
<resultMap id="articleMap" type="com.tulun.model.Article">
-
<result column="content" property="content" typeHandler="com.tulun.util.ConvertBlobTypeHandler">
</result>
-
</resultMap>
-
-
</mapper>
ConvertBlobTypeHandler
该工具类主要用于将博客中的blog类型转换为String类型。
-
package com.tulun.util;
-
-
import org.apache.ibatis.type.BaseTypeHandler;
-
import org.apache.ibatis.type.JdbcType;
-
-
import java.io.ByteArrayInputStream;
-
import java.io.UnsupportedEncodingException;
-
import java.sql.*;
-
-
/**
-
* @desc Blob转换String处理器,解决MyBatis存储blob字段后,出现乱码的问题
-
*/
-
public
class ConvertBlobTypeHandler extends BaseTypeHandler<String> {
-
-
private
static
final String DEFAULT_CHARSET =
"utf-8";
-
-
@Override
-
public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
-
-
Blob blob = rs.getBlob(columnName);
-
if (
null == blob) {
-
return
null;
-
}
-
-
byte[] returnValue =
null;
-
returnValue = blob.getBytes(
1, (
int) blob.length());
-
-
try {
-
// ###把byte转化成string
-
return
new String(returnValue, DEFAULT_CHARSET);
-
}
catch (UnsupportedEncodingException e) {
-
throw
new RuntimeException(
"Blob Encoding Error!");
-
}
-
}
-
-
@Override
-
public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
-
Blob blob = rs.getBlob(columnIndex);
-
if (
null == blob) {
-
return
null;
-
}
-
-
byte[] returnValue =
null;
-
returnValue = blob.getBytes(
1, (
int) blob.length());
-
-
try {
-
// ###把byte转化成string
-
return
new String(returnValue, DEFAULT_CHARSET);
-
}
catch (UnsupportedEncodingException e) {
-
throw
new RuntimeException(
"Blob Encoding Error!");
-
}
-
}
-
-
@Override
-
public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
-
Blob blob = cs.getBlob(columnIndex);
-
if (
null == blob) {
-
return
null;
-
}
-
-
byte[] returnValue =
null;
-
returnValue = blob.getBytes(
1, (
int) blob.length());
-
try {
-
// ###把byte转化成string
-
return
new String(returnValue, DEFAULT_CHARSET);
-
}
catch (UnsupportedEncodingException e) {
-
throw
new RuntimeException(
"Blob Encoding Error!");
-
}
-
}
-
-
@Override
-
public void setNonNullParameter(PreparedStatement ps, int parameterIndex, String parameter, JdbcType jdbcType)
-
throws SQLException {
-
ByteArrayInputStream bis =
null;
-
try {
-
// ###把String转化成byte流
-
bis =
new ByteArrayInputStream(parameter.getBytes(DEFAULT_CHARSET));
-
}
catch (UnsupportedEncodingException e) {
-
throw
new RuntimeException(
"Blob Encoding Error!");
-
}
-
ps.setBinaryStream(parameterIndex, bis, parameter.length());
-
}
-
-
}
ArticleController
同样设计二级映射,方便归类,注入标签与类别的Service实例,通过实例调用select**方法,获取到的对象存储于List中,通过Model类的addAttribute方法进行添加。
-
package com.tulun.controller;
-
-
import com.tulun.model.Category;
-
import com.tulun.model.Tag;
-
import com.tulun.service.CategoryService;
-
import com.tulun.service.TagService;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.stereotype.Controller;
-
import org.springframework.ui.Model;
-
import org.springframework.web.bind.annotation.RequestMapping;
-
-
import java.util.List;
-
-
/**
-
* Description :
-
* Created by Resumebb
-
* Date :2021/4/27
-
*/
-
@Controller
-
@RequestMapping("/article")
-
public
class ArticleController {
-
@Autowired
-
private TagService tagService;
-
-
@Autowired
-
private CategoryService categoryService;
-
-
@RequestMapping("/add")
-
public String add(Model model) {
-
//获取类别数据
-
List<Category> categories = categoryService.selectAllCategory();
-
-
//获取标签数据
-
List <Tag> tags = tagService.selectAllTag();
-
-
model.addAttribute(
"categoryList", categories);
-
model.addAttribute(
"tagList", tags);
-
return
"article/add_article";
-
}
-
}
新增页面jsp开发
-
<%@ page language="java" contentType="text/html; charset=UTF-8" import="java.util.*" %>
-
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
<%@ taglib prefix="fm" uri="http://java.sun.com/jsp/jstl/functions" %>
-
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
-
<%
-
String path = request.getContextPath();
-
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
-
%>
-
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-
<html>
-
<head>
-
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
<meta name="renderer" content="webkit">
-
<link href="<%=basePath%>css/bootstrap.min.css" rel="stylesheet">
-
<link href="<%=basePath%>font-awesome/css/font-awesome.css" rel="stylesheet">
-
<!-- Data Tables -->
-
<link href="<%=basePath%>css/plugins/dataTables/dataTables.bootstrap.css" rel="stylesheet">
-
<link href="<%=basePath%>css/animate.css" rel="stylesheet">
-
<link href="<%=basePath%>css/style.css" rel="stylesheet">
-
<link rel="stylesheet" type="text/css" href="<%=basePath%>js/flavr/flavr/css/animate.css" />
-
<link rel="stylesheet" type="text/css" href="<%=basePath%>js/flavr/flavr/css/flavr.css" />
-
<link href="<%=basePath%>css/plugins/datapicker/datepicker3.css" rel="stylesheet">
-
<link href="<%=basePath%>css/plugins/chosen/chosen.css" rel="stylesheet">
-
-
<style>
-
.input-upload{
position: relative;}
-
.input-upload
input
[type="file"]{
position: absolute;
left:
0px;
top:
0px;
width:
72px;
height:
35px;
opacity:.
0;
filter:
alpha(opacity=
00);}
-
</style>
-
<title>新增博客
</title>
-
</head>
-
<body>
-
<div id="wrapper">
-
-
<div id="page-wrapper" class="gray-bg dashbard-1">
-
<%--<div class="row wrapper border-bottom white-bg page-heading">--%>
-
-
<%--</div>--%>
-
-
-
<div class="wrapper wrapper-content animated fadeInRight">
-
-
<div class="row">
-
<div class="col-lg-12">
-
<div class="ibox float-e-margins">
-
<div class="ibox-content">
-
<form method="get" class="form-horizontal">
-
<div class="form-group">
-
<label class="col-sm-2 control-label">类别:
</label>
-
<div class="col-sm-4">
-
<select class="form-control m-b" id="categoryId">
-
<option value="-1">无
</option>
-
<c:forEach items="${categoryList}" var="category">
-
<option value="${category.id}">${category.categoryName}
</option>
-
</c:forEach>
-
</select>
-
</div>
-
</div>
-
-
<div class="form-group">
-
<label class="col-sm-2 control-label">博客标题
</label>
-
<div class="col-sm-10">
-
<input type="text" id="title" class="form-control" placeholder="请填写博客名">
-
</div>
-
</div>
-
<div class="hr-line-dashed">
</div>
-
<div class="form-group">
-
<label class="col-sm-2 control-label">博客内容:
</label>
-
<div class="col-sm-10">
-
<script id="editor" type="text/plain">
</script>
-
</div>
-
</div>
-
<div class="hr-line-dashed">
</div>
-
-
<div class="form-group">
-
<label class="col-sm-2 control-label">标签:
</label>
-
<div class="col-sm-10">
-
<select data-placeholder="请选择标签" class="chosen-select" multiple style="width:450px;" tabindex="5">
-
<c:forEach items="${tagList}" var="tag">
-
<option value="${tag.id}" hassubinfo="true">${tag.tagName}
</option>
-
</c:forEach>
-
</select>
-
</div>
-
</div>
-
-
<div class="form-group">
-
<div class="col-sm-4 col-sm-offset-2">
-
<button class="btn btn-primary" type="button" onclick="saveArticle()">保存
</button>
-
<button class="btn btn-white" type="button" onclick="cancelSaveArticle()">取消
</button>
-
</div>
-
</div>
-
</form>
-
</div>
-
</div>
-
</div>
-
</div>
-
-
</div>
-
-
</div>
-
</div>
-
-
</div>
-
-
<!-- Mainly scripts -->
-
<script src="<%=basePath%>js/jquery-2.1.1.min.js">
</script>
-
<script src="<%=basePath%>js/bootstrap.min.js">
</script>
-
<script src="<%=basePath%>js/plugins/metisMenu/jquery.metisMenu.js">
</script>
-
<script src="<%=basePath%>js/plugins/slimscroll/jquery.slimscroll.min.js">
</script>
-
<script src="<%=basePath%>js/hplus.js">
</script>
-
<script src="<%=basePath%>js/plugins/pace/pace.min.js">
</script>
-
<script src="<%=basePath%>js/validation.js">
</script>
-
<%--自定义js--%>
-
<script src="<%=basePath%>js/article/add_article.js">
</script>
-
<script type="text/javascript" src="<%=basePath%>js/flavr/flavr/js/flavr.min.js">
</script>
-
<script type="text/javascript" src="<%=basePath%>js/flavr/base.js">
</script>
-
<script type="text/javascript" src="<%=basePath%>js/zTree_v3/js/jquery.ztree.all-3.5.js">
</script>
-
<script src="<%=basePath%>js/plugins/datapicker/bootstrap-datepicker.js">
</script>
-
<script type="text/javascript" src="<%=basePath%>js/ueditor1_4_3/ueditor.config.js">
</script>
-
<script type="text/javascript" src="<%=basePath%>js/ueditor1_4_3/ueditor.all.js">
</script>
-
<script type="text/javascript" charset="utf-8" src="<%=basePath%>js/ueditor1_4_3/lang/zh-cn/zh-cn.js">
</script>
-
<script type="text/javascript" src="<%=basePath%>js/ajaxfileupload.js">
</script>
-
<script src="<%=basePath%>js/plugins/chosen/chosen.jquery.js">
</script>
-
<script type="text/javascript" src="<%=basePath%>js/imageUtils.js">
</script>
-
-
<script type="text/javascript">
-
$(
document).ready(
function () {
-
var UEDITOR_HOME_URL =
"/js/ueditor1_4_3/";
-
var ue = UE.getEditor(
'editor');
-
})
-
-
$(
".chosen-select").chosen({
-
max_selected_options:
5,
-
no_results_text:
"û���ҵ�",
-
allow_single_deselect:
true
-
});
-
-
</script>
-
</body>
-
</html>
部署至服务器
通过select标签可以进行类别与标签的选择。
文章数据提交
博客编辑好了之后,下一步就需要进行数据的提交。
后台JS处理
后台js对数据进行解析,其中的每一项都需要选中信息或填入信息,如果没有信息,就利用ajax进行弹窗提示,时长为500ms。之后再通过param进行数据加密,防止数据明文显示被抓包。如果保存成功将重定位至list。
-
// 保存文章
-
function saveArticle(){
-
var param = {};
-
-
// 收集参数 校验
-
//$("#categoryId").val()
-
var categoryId = $(
"#categoryId").val();
-
if(categoryId ==
'-1'){
-
autoCloseAlert(
"请选择栏目",
500);
-
return
false;
-
}
-
param[
"categoryId"] = categoryId;
-
-
var title = $(
"#title").val();
-
if(isEmpty(title)){
-
autoCloseAlert(
"请输入标题",
500);
-
return
false;
-
}
-
param[
"title"] = title;
-
-
var arr = [];
-
arr.push(UE.getEditor(
'editor').getContent());
-
var content = arr.join(
"\n");
-
-
// 简介
-
var description = UE.getEditor(
'editor').getContentTxt().substring(
0,
500);
-
-
// 标签
-
var tagId = $(
".chosen-select").val();
-
// alert(tagId);
-
if(!isEmpty(tagId)){
-
var ids = (tagId+
"").split(
"\,");
-
var tagArray = [];
-
for(
var i=
0;i<ids.length;i++){
-
tagObj = {
"id":ids[i]};
-
// alert(tagObj.id);
-
tagArray.push(tagObj);
-
}
-
param[
"tagList"] = tagArray;
-
console.info(tagArray);
-
}
else{
-
autoCloseAlert(
"请输入标签",
500);
-
return
false;
-
}
-
// alert('param='+encodeURI(encodeURI(JSON.stringify(param))));
-
// 保存文章
-
$.ajax({
-
type :
"POST",
-
url :
'../article/addContent',
-
data :
'param='+
encodeURI(
encodeURI(
JSON.stringify(param)))+
"&content="+
encodeURI(
encodeURI(content)).replace(
/\&/g,
"%26").replace(
/\+/g,
"%2B")+
"&description="+
encodeURI(
encodeURI(description)),
-
success :
function(data) {
-
if(data.resultCode !=
'success'){
-
autoCloseAlert(data.errorInfo,
1000);
-
return
false;
-
}
else{
-
// 调到列表页
-
window.location.href =
"../article/list";
-
}
-
}
-
});
-
}
-
-
function cancelSaveArticle(){
-
window.location.href =
"../article/list";
-
}
ArticleController
在ArticleController中新增addContent方法,利用URLDecoder进行数据的解密。
-
@RequestMapping("/addContent")
-
@ResponseBody
-
public Result addContent(String param, String content, String description) throws UnsupportedEncodingException {
-
String param1 = URLDecoder.decode(param,
"utf-8");
-
String content1 = URLDecoder.decode(content,
"utf-8");
-
String description1 = URLDecoder.decode(description,
"utf-8");
-
System.out.println(
"content:"+content);
-
System.out.println(
"description:"+description);
-
System.out.println(
"content1:"+content1);
-
System.out.println(
"description1:"+description1);
-
return
new Result(
"success",
"处理成功");
-
}
这里用到一个Result类,它是用于存储返回结果的,属性主要包含操作结果,错误信息,以及附属对象。
-
package com.tulun.model;
-
-
import org.apache.log4j.Logger;
-
-
-
/**
-
* 封装统一的结果集给前端
-
*/
-
public
class Result {
-
-
// 操作结果
-
private String resultCode;
-
-
// 错误信息
-
private String errorInfo;
-
-
// 附属对象
-
private Object object;
-
-
public Result(String resultCode, String errorInfo) {
-
super();
-
this.resultCode = resultCode;
-
//this.errorInfo = "错误";
-
this.errorInfo = errorInfo;
-
System.out.println(errorInfo);
-
}
-
-
public Result(String resultCode, String errorInfo, Object object) {
-
super();
-
this.resultCode = resultCode;
-
this.errorInfo = errorInfo;
-
-
this.object = object;
-
}
-
-
public String getResultCode() {
-
return resultCode;
-
}
-
-
public void setResultCode(String resultCode) {
-
this.resultCode = resultCode;
-
}
-
-
public String getErrorInfo() {
-
return errorInfo;
-
}
-
-
public void setErrorInfo(String errorInfo) {
-
this.errorInfo = errorInfo;
-
}
-
-
public Object getObject() {
-
return object;
-
}
-
-
public void setObject(Object object) {
-
this.object = object;
-
}
-
-
@Override
-
public String toString() {
-
return
"Result{" +
-
"resultCode='" + resultCode +
'\'' +
-
", errorInfo='" + errorInfo +
'\'' +
-
", object=" + object +
-
'}';
-
}
-
}
接下来部署到服务器进行打印测试:
上面为加密信息,下面为解密信息 ,可以看出加密解密成功实现。
文章数据保存至数据库
Json数据转换
该工具类的作用是实现Json字符串与对象的相互转换,因为在插入数据库过程中,将其转换为对象操作起来更加方便,通过Set方法就可以进行设置。
-
package com.tulun.util;
-
-
import com.google.gson.Gson;
-
import com.google.gson.GsonBuilder;
-
import com.google.gson.JsonSyntaxException;
-
-
import javax.servlet.ServletOutputStream;
-
import javax.servlet.http.HttpServletResponse;
-
import java.io.IOException;
-
import java.io.InputStream;
-
import java.io.InputStreamReader;
-
import java.io.UnsupportedEncodingException;
-
-
public
class JsonUtil {
-
-
public static Gson getGson() {
-
return
new Gson();
-
}
-
-
/**
-
* 将对象转为JSON字符串(忽略NULL值)
-
*
-
* @param src
-
* @return
-
*/
-
public static String toJson(Object src) {
-
return getGson().toJson(src);
-
}
-
-
/**
-
* 将对象转为JSON字符串(不忽略NULL值)
-
*
-
* @param src
-
* @param serializeNulls
-
* @return
-
*/
-
public static String toJson(Object src, boolean serializeNulls) {
-
if (serializeNulls)
-
return
new GsonBuilder().serializeNulls().create().toJson(src);
-
return toJson(src);
-
}
-
-
/**
-
* 将JSON字符串转为对象
-
*
-
* @param json
-
* @param classOfT
-
* @return
-
* @throws JsonSyntaxException
-
*/
-
public
static <T>
T fromJson(String json, Class<T> classOfT)
-
throws JsonSyntaxException {
-
return getGson().fromJson(json, classOfT);
-
}
-
-
/**
-
* 从请求体中读取客户端发送的JSON串
-
*
-
* @param stream
-
* 输入流
-
* @return String 类型,接收到的JSON串
-
*/
-
public static String readStringFromRequestBody(InputStream stream) {
-
StringBuffer sb =
new StringBuffer();
-
char[] buf =
new
char[
2048];
-
int len = -
1;
-
try {
-
InputStreamReader reader =
new InputStreamReader(stream,
"UTF-8");
-
while ((len = reader.read(buf)) != -
1) {
-
sb.append(
new String(buf,
0, len));
-
}
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
finally {
-
if (stream !=
null) {
-
try {
-
stream.close();
-
}
catch (IOException e) {
-
}
-
}
-
}
-
return sb.toString();
-
}
-
-
/**
-
* 回写响应
-
* @param json
-
* @param response
-
*/
-
public static void writeString(String json, HttpServletResponse response) {
-
ServletOutputStream os =
null;
-
try {
-
os = response.getOutputStream();
-
os.write(json.getBytes(
"UTF-8"));
-
}
catch (UnsupportedEncodingException e) {
-
e.printStackTrace();
-
}
catch (IOException e) {
-
e.printStackTrace();
-
}
finally{
-
if(
null != os){
-
try {
-
os.close();
-
}
catch (IOException e) {
-
}
-
}
-
}
-
}
-
}
ArticleMapper
主要定义两个方法,一个新增文章,另一个通过id号查询文章数据。
-
public
interface ArticleMapper {
-
public int addArticle(Article article);
-
public Article getArticleById(Integer id);
-
}
ArticleService
-
@Service
-
public
class ArticleService {
-
@Autowired
-
ArticleMapper articleMapper;
-
public int addArticle(Article article){
-
return articleMapper.addArticle(article);
-
}
-
-
public Article getArticleById(Integer id){
-
return articleMapper.getArticleById(id);
-
}
-
}
ArticleController
调用JsonUtil类将字符串转换为Article类,通过set方法进行传参,根据Service的返回结果进行判断,i>0就插入成功,后台打印信息,数据库的数据也插入成功。
-
@RequestMapping("/addContent")
-
@ResponseBody
-
public Result addContent(String param, String content, String description) throws UnsupportedEncodingException {
-
String param1 = URLDecoder.decode(param,
"utf-8");
-
String content1 = URLDecoder.decode(content,
"utf-8");
-
String description1 = URLDecoder.decode(description,
"utf-8");
-
//将String字符串解析为对象
-
Article article = JsonUtil.fromJson(param1, Article.class);
-
article.setContent(content1);
-
article.setDescription(description1);
-
article.setStatus(
0);
-
article.setCreateTime(
new Date());
-
article.setAuthor(
"杜甫");
-
System.out.println(article);
-
-
int i = articleService.addArticle(article);
-
if(i>
0){
-
return
new Result(
"success",
"处理成功");
-
}
-
return
new Result(
"fail",
"处理失败");
-
}
ArticleMapper.xml
映射文件中进行ResultMap的配置以及SQL语句的书写,注意配置过程中每一个属性映射的时候要保证前后端名称一致,否则就会报错。
-
<?xml version="1.0" encoding="UTF-8" ?>
-
<!DOCTYPE mapper
-
PUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
-
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
<mapper namespace="com.tulun.dao.ArticleMapper">
-
<resultMap id="articleMap" type="com.tulun.model.Article">
-
<result column="id" property="id">
</result>
-
<result column="categoryId" property="categoryId">
</result>
-
<result column="title" property="title">
</result>
-
<result column="content" property="content">
</result>
-
<result column="description" property="description">
</result>
-
<result column="status" property="status">
</result>
-
<result column="author" property="author">
</result>
-
<result column="createTime" property="createTime">
</result>
-
<result column="showCount" property="showCount">
</result>
-
<result column="content" property="content" typeHandler="com.tulun.util.ConvertBlobTypeHandler">
</result>
-
</resultMap>
-
-
<insert id="addArticle" parameterType="com.tulun.model.Article">
-
insert into t_article (categoryId,title,content,description,status,author,createTime)
-
values (#{categoryId},#{title},#{content},#{description},#{status},#{author},#{createTime})
-
</insert>
-
-
<select id="getArticleById" parameterType="int" resultMap="articleMap">
-
select * from t_article where id = #{id}
-
</select>
-
</mapper>
部署至服务器
博客内容展示
内容展示的jsp如下,分别获取到博客的名称,作者,内容,分类等等信息,其中要注意的是发表时间以及分类,因为通过Date获取的时间并不是一个格式化时间,需要对它进行转换,另一个是分类从数据库读取的是分类号,而不是类名,同时也要做相应的转换。
article_detail.jsp
-
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
-
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
-
<%
-
String path = request.getContextPath();
-
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
-
%>
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
<html>
<head>
-
<link rel="stylesheet" id="main-css" href="<%=basePath%>css/demo/style.css" type="text/css" media="all">
-
<link href="<%=basePath%>js/ueditor1_4_3/third-party/SyntaxHighlighter/shCoreDefault.min.css" rel="stylesheet" type="text/css" />
-
<meta charset="UTF-8">
-
<meta http-equiv="X-UA-Compatible" content="IE=11,IE=10,IE=9,IE=8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
-
<meta name="baidu-site-verification" content="emEdenaBVA">
-
<meta http-equiv="Cache-Control" content="no-siteapp">
-
<title> 博客系统
</title>
-
-
</head>
-
-
<body id="contain" class="home blog ui-c3">
-
<section class="container">
-
<header class="header">
-
<div class="logo_right">
<span class="glyphicon glyphicon-search degfy_search">
</span>
</div>
-
<div class="logo_left">
</div>
-
<h1 class="logo">
<a href="">博客系统
</a>
</h1>
-
<div class="widget_head">
</div>
-
</header>
-
<div class="content-wrap">
-
<div class="content">
-
<header class="article-header">
-
<h1 class="article-title">${article.title}
</h1>
-
<ul class="article-meta">
-
<li>作者:${article.author}
发布于:${article.time}
</li>
-
<li>分类:
<a rel="category tag" data-original-title="" title="">${article.categoryName}
</a>
</li>
-
</ul>
-
</header>
-
<article class="article-content">
-
${article.content}
-
</article>
-
-
<div class="article-tags">
-
标签:
-
<c:forEach items="${article.id}" var="tag">
-
<a href="javascript:void(0)" rel="tag" data-original-title="" title="">${tag.tagName}
</a>
-
</c:forEach>
-
</div>
-
-
</div>
-
</section>
-
-
<div id="back_hidden">
</div>
-
<script type="text/javascript" src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js">
</script>
-
<script src="//cdn.bootcss.com/jquery.lazyload/1.9.1/jquery.lazyload.js">
</script>
-
</body>
-
-
</html>
时间格式化
在Article的POJO类中新增time属性,通过SimpleDateFormat类格式化时间,然后通过get方法进行返回。
-
public String getTime() {
-
SimpleDateFormat simpleDateFormat =
new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
-
return simpleDateFormat.format(createTime);
-
}
分类ID与类名转换
在Article的POJO类中新增categoryName属性,通过数据库的联合查询来返回一个categoryName。
-
<?xml version="1.0" encoding="UTF-8" ?>
-
<!DOCTYPE mapper
-
PUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
-
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
<mapper namespace="com.tulun.dao.ArticleMapper">
-
<resultMap id="articleMap" type="com.tulun.model.Article">
-
<result column="id" property="id">
</result>
-
<result column="categoryId" property="categoryId">
</result>
-
<result column="title" property="title">
</result>
-
<result column="content" property="content">
</result>
-
<result column="description" property="description">
</result>
-
<result column="status" property="status">
</result>
-
<result column="author" property="author">
</result>
-
<result column="createTime" property="createTime">
</result>
-
<result column="categoryName" property="categoryName">
</result>
-
<result column="showCount" property="showCount">
</result>
-
<result column="content" property="content" typeHandler="com.tulun.util.ConvertBlobTypeHandler">
</result>
-
</resultMap>
-
-
<insert id="addArticle" parameterType="com.tulun.model.Article">
-
insert into t_article (categoryId,title,content,description,status,author,createTime)
-
values (#{categoryId},#{title},#{content},#{description},#{status},#{author},#{createTime})
-
</insert>
-
-
<select id="getArticleById" parameterType="int" resultMap="articleMap">
-
select a.*,c.categoryName categoryName from t_article a, t_category c where a.categoryId = c.id and a.id = #{id}
-
</select>
-
</mapper>
最后部署至服务器可以看见初步效果
报错汇总
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
原因是POJO类的与mapper.xml中select标签上的id名不一致导致的
转载:https://blog.csdn.net/qq_41573860/article/details/116168392