一、插件新增功能页面jsp的添加
(1)创建一个jsp页面,命名plugin-add.jsp
(2)plugin-add.jsp内容
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
(3)需要注意的几个地方
A.富文本编辑器的引用添加
B.easyUI风格的表单引用
C.表单的name要与数据表Plugin的字段列名对应,后期表单数据【POST参数】序列化成Plugin对象很重要
1.
2.
D.表单数据ajax-post提交
二、运行项目,查看效果
(1)
(2)
(3)我们看下ide中控制台中的输出信息
找不到/plugin-add的http映射请求,说白了,就是Controller没有处理好URI映射
(4)解决办法
A.
B.
IndexPageController.java
package com.appleyk.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 后台管理首页展示
* @author Appleyk
* @date 2017年11月14日12:10:45
*/
@Controller
public class IndexPageController {
@RequestMapping("/")
public String ShowIndex(){
return "index";
}
//添加一个Handler 用来返回XX相关的页面
@RequestMapping("/{page}")
public String ShowPage(@PathVariable String page){
return page;
}
}
三、统一定义【技能任务单后台管理系统】返回数据格式
(1)
(2)DataResult.java【实现序列化】
package com.appleyk.result;
import java.io.Serializable;
import java.util.List;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* 技能任务单后台管理自定义响应数据结构
*/
public class DataResult implements Serializable {
private static final long serialVersionUID = 1L;
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
// 响应业务状态
private Integer status;
// 响应消息
private String msg;
// 响应中的数据
private Object data;
public static DataResult build(Integer status, String msg, Object data) {
return new DataResult(status, msg, data);
}
public static DataResult ok(Object data) {
return new DataResult(data);
}
public static DataResult ok() {
return new DataResult(null);
}
public DataResult() {
}
public static DataResult build(Integer status, String msg) {
return new DataResult(status, msg, null);
}
public DataResult(Integer status, String msg, Object data) {
this.status = status;
this.msg = msg;
this.data = data;
}
public DataResult(Object data) {
this.status = 200;
this.msg = "OK";
this.data = data;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* 将json结果集转化为DataResult对象
*
* @param jsonData json数据
* @param clazz DataResult中的object类型
* @return
*/
public static DataResult formatToPojo(String jsonData, Class> clazz) {
try {
if (clazz == null) {
return MAPPER.readValue(jsonData, DataResult.class);
}
JsonNode jsonNode = MAPPER.readTree(jsonData);
JsonNode data = jsonNode.get("data");
Object obj = null;
if (clazz != null) {
if (data.isObject()) {
obj = MAPPER.readValue(data.traverse(), clazz);
} else if (data.isTextual()) {
obj = MAPPER.readValue(data.asText(), clazz);
}
}
return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
} catch (Exception e) {
return null;
}
}
/**
* 没有object对象的转化
*
* @param json
* @return
*/
public static DataResult format(String json) {
try {
return MAPPER.readValue(json, DataResult.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Object是集合转化
*
* @param jsonData json数据
* @param clazz 集合中的类型
* @return
*/
public static DataResult formatToList(String jsonData, Class> clazz) {
try {
JsonNode jsonNode = MAPPER.readTree(jsonData);
JsonNode data = jsonNode.get("data");
Object obj = null;
if (data.isArray() && data.size() > 0) {
obj = MAPPER.readValue(data.traverse(),
MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
}
return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
} catch (Exception e) {
return null;
}
}
}
四、先实现,图片上传功能【Java客户端+Nginx+FastDFS】
上传的操作请参考我的博文 --> 点击打开链接
(1)启动装有Nginx+FastDFS环境的Linux系统
A.启动Nginx反向代理服务器
B.启动FastDFS的tracker调度器
C.启动FastDFS的storage存储器
D.停掉防火墙服务【避免本地上传图片至Linux系统,出现对应端口号无法访问的问题,索性直接停掉】
E.暂未上传任何图片
稍后,我们会折返回来,验证一下我们上传图片的功能,怎么验证,就是上图中存储图片的目录下面不在等于空白
(2)FastDFS客户端jar包依赖【已依赖】
(3)SpringMVC配置文件中注入多媒体解析器bean【已注入】
(4)添加FastDFS的tracker调度器节点的地址属性配置文件【IP+Port】
A.
B.
(5)配置FastDFS上传成功后的图片访问的http地址头
(6)定义图片上传请求的的响应消息数据格式
A.
B.
PictureResult实体类
package com.appleyk.result;
/*
返回格式(JSON)
//成功时
{
"error" : 0,
"url" : "http://www.example.com/path/to/file.ext
"
}
//失败时
{
"error" : 1,
"message" : "错误信息"
}
*/
public class PictureResult {
private int error;
private String url;
private String message;
public int getError() {
return error;
}
public void setError(int error) {
this.error = error;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
(7)创建FastDFS客户端上传工具类以及对象转JSON串工具类
A.
B.
C.
FastDFSClient.java
package com.appleyk.utils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
public class FastDFSClient {
private TrackerClient trackerClient = null;
private TrackerServer trackerServer = null;
private StorageServer storageServer = null;
private StorageClient1 storageClient = null;
public FastDFSClient(String conf) throws Exception {
if (conf.contains("classpath:")) {
conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
}
ClientGlobal.init(conf);
trackerClient = new TrackerClient();
trackerServer = trackerClient.getConnection();
storageServer = null;
storageClient = new StorageClient1(trackerServer, storageServer);
}
/**
* 上传文件方法
* Title: uploadFile
* Description:
* @param fileName 文件全路径
* @param extName 文件扩展名,不包含(.)
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
String result = storageClient.upload_file1(fileName, extName, metas);
return result;
}
public String uploadFile(String fileName) throws Exception {
return uploadFile(fileName, null, null);
}
public String uploadFile(String fileName, String extName) throws Exception {
return uploadFile(fileName, extName, null);
}
/**
* 上传文件方法
* Title: uploadFile
* Description:
* @param fileContent 文件的内容,字节数组
* @param extName 文件扩展名
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {
String result = storageClient.upload_file1(fileContent, extName, metas);
return result;
}
public String uploadFile(byte[] fileContent) throws Exception {
return uploadFile(fileContent, null, null);
}
public String uploadFile(byte[] fileContent, String extName) throws Exception {
return uploadFile(fileContent, extName, null);
}
}
D.
E.
JsonUtils.java
package com.appleyk.utils;
import java.util.List;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* JOSN转化工具
*/
public class JsonUtils {
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 将对象转换成json字符串。
* Title: pojoToJson
* Description:
* @param data
* @return
*/
public static String objectToJson(Object data) {
try {
String string = MAPPER.writeValueAsString(data);
return string;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* 将json结果集转化为对象
*
* @param jsonData json数据
* @param clazz 对象中的object类型
* @return
*/
public static T jsonToPojo(String jsonData, Class beanType) {
try {
T t = MAPPER.readValue(jsonData, beanType);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将json数据转换成pojo对象list
* Title: jsonToList
* Description:
* @param jsonData
* @param beanType
* @return
*/
public static List jsonToList(String jsonData, Class beanType) {
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
try {
List list = MAPPER.readValue(jsonData, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
(8)编写图片上传的Service 接口+实现
A.
<1>
<2>
PictureService.Java
package com.appleyk.service;
import org.springframework.web.multipart.MultipartFile;
import com.appleyk.result.PictureResult;
public interface PictureService {
PictureResult uploadPic(MultipartFile picFile);
}
<1>
<2>
PictureServiceImpl.java
package com.appleyk.service.Impl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.appleyk.utils.FastDFSClient;
import com.appleyk.result.PictureResult;
import com.appleyk.service.PictureService;
/**
* 图片上传Service接口 实现
* @author Appleyk
* @Time 2017年12月4日15:30:20
*
*/
@Service
public class PictureServiceImpl implements PictureService {
//spring容器一启动,就会加载*.properties文件中的信息
//利用@Value注解,拿到属性文件里面的 指定变量的值
@Value("${FASTDFS_IMG_HTTP_HEADER}")
private String http_url_header;
@Override
public PictureResult uploadPic(MultipartFile picFile) {
PictureResult picResult = new PictureResult();
if(picFile.isEmpty()){
//如果等于空,失败
picResult.setError(1);
picResult.setMessage("图片为空");
return picResult;
}
//如果不等于空的话,获得url
//获得文件的原始名称
String originalFilename = picFile.getOriginalFilename();
//截取文件的后缀名 ==> 也就是FastDFS uploadfile方法的第二个参数,不要"."
String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1);
try {
FastDFSClient fClient = new FastDFSClient("classpath:properties/client.conf");
//如果没问题 直接 upload
//返回上传成功后的图片名(准确来说,还需要拼接成http url地址)
String url = fClient.uploadFile(picFile.getBytes(), extName);
picResult.setError(0);
picResult.setUrl(http_url_header+url);
} catch (Exception e) {
e.printStackTrace();
//抛异常 就是FastDFS的tracker server 的配置文件 有问题(IP:Port)
picResult.setError(1);
picResult.setMessage("FastDFS的tracker server 的配置文件 有问题,图片上传失败!");
return picResult;
}
return picResult;
}
}
(9)编写图片上传的Controller
A.
B.
C.
PictureUpLoadController.java
package com.appleyk.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.appleyk.result.PictureResult;
import com.appleyk.service.PictureService;
import com.appleyk.utils.JsonUtils;
@Controller
public class PictureUpLoadController {
//装载PictureService 实例
@Autowired
private PictureService picService ;
@RequestMapping("/pic/upload")
@ResponseBody //解决浏览器不兼容的问题 直接 返回一个json string
public String picUpload(MultipartFile uploadFile){
PictureResult picResult = picService.uploadPic(uploadFile);
String json = JsonUtils.objectToJson(picResult);
System.out.println(json);
return json;
}
}
(10)运行项目,图片上传测试
A.
B.
C.Linux中,在storage存储文件的目录下面验证一下这两张图是否成功了
D.上传成功后,插入图片
E.点击图片,进行大图的地址浏览查看
图片上传功能配置好后,接下来就是实现Plugin的插入Service层接口的创建+业务实现
五、Plugin插件数据操作对应的Service层编写
A.
B.
PluginService.java
package com.appleyk.service;
import com.appleyk.pojo.Plugin;
import com.appleyk.result.DataResult;
public interface PluginService {
//向Plugin表添加一条记录
DataResult savePlugin(Plugin plugin,String userName);
}
C.
PluginServiceImpl.java
package com.appleyk.service.Impl;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.appleyk.mapper.PluginMapper;
import com.appleyk.mapper.UsersMapper;
import com.appleyk.pojo.Plugin;
import com.appleyk.pojo.Users;
import com.appleyk.pojo.UsersExample;
import com.appleyk.pojo.UsersExample.Criteria;
import com.appleyk.result.DataResult;
import com.appleyk.service.PluginService;
/**
* 根据用户名查询插件信息
* @author 余坤
* @date 2017年11月10日:下午5:31:07
*/
@Service
public class PluginServiceImpl implements PluginService {
@Autowired
private UsersMapper uMapper = null;
@Autowired
private PluginMapper pMapper = null;
@Override
public DataResult savePlugin(Plugin plugin,String userName) {
//这里要判断一下,用户名对应的Users表里是否存在记录
//因为plugin表和users表关联ID == u_id
/** 表单提交数据参数 除了第一个外,其他都可看成是一个Plugin对象
userName appleyk111
name ddd
type ddd
image null
pre ddd
keyword ddd
description 你们不知道的事,是什么呢
fileAddress dddd.txt
*/
UsersExample example = new UsersExample();
Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo(userName);
List list = uMapper.selectByExample(example);
int uID = 0;
if(list!=null && list.size()>0){
//这里取出对应用户名的 uId
uID = list.get(0).getId();
}
if(uID!=0){
//如果在Users表中查到对应的记录,则向plugin表插入一条记录,记录由jsp页面的表单数据js--post提交
plugin.setuId(uID);
plugin.setCreatetime(new Date());
pMapper.insert(plugin);
return DataResult.ok();
}
else{
DataResult dataResult = new DataResult();
dataResult.setStatus(400);//400:表示在Users表中找不到对应的用户信息
return dataResult;
}
}
}
六、编写Plugin对应的Controller控制器
A.
B.
PluginController.java
package com.appleyk.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.appleyk.pojo.Plugin;
import com.appleyk.result.DataResult;
import com.appleyk.service.PluginService;
/**
* Plugin插件表 Controller
*
* @author Appleyk
* @blob http://blog.csdn.net/appleyk
* @date 2017年12月4日16:22:15
*/
@Controller
@RequestMapping("/plugin") // url地址窄化
public class PluginController {
@Autowired
private PluginService pService;
@RequestMapping(value = "/save", method = RequestMethod.POST)
@ResponseBody
public DataResult createItem(Plugin plugin, String userName) {
DataResult result = pService.savePlugin(plugin, userName);
return result;
}
}
七、Plugin插件信息插入前端测试
A.先测试用户不存在的情况【上述图中显示了当前系统注册的用户有哪些】
(1)
(2)点击提交,发生了什么呢?
B.测试用户存在的情况
(1)
(2)提交表单后,会发生什么呢?
八、Plugin插件信息插入成功后,后台数据库查询验证
由于,Plugin插件信息的查询列表展示我们本篇还没涉及到,放到以后再加,因此,新增了一条插件信息后,我们只能手动的去数据库进行查询:
本篇完。