Java Web后端--入职技能任务单(新增插件信息)八

一、插件新增功能页面jsp的添加


(1)创建一个jsp页面,命名plugin-add.jsp



(2)plugin-add.jsp内容


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<link href="/js/kindeditor-4.1.10/themes/default/default.css" type="text/css" rel="stylesheet">
<script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/kindeditor-all-min.js"></script>
<script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/lang/zh_CN.js"></script>
<div style="padding:10px 10px 10px 10px">
	<form id="pluginAddForm" class="pluginForm" method="post">
	    <table cellpadding="5">
	        <tr>
	            <td>用户名:</td>
	            <td><input class="easyui-textbox" type="text" name="userName" data-options="required:true" style="width: 100px;"></input></td>
	        </tr>
	        <tr>
	            <td>插件名称:</td>
	            <td><input class="easyui-textbox" type="text" name="name" data-options="required:true" style="width: 280px;"></input></td>
	        </tr>
	        <tr>
	            <td>插件类型:</td>
	            <td><input class="easyui-textbox" type="text" name="type" data-options="required:true" style="width: 100px;"></input></td>
	        </tr>
	        <tr>
	            <td>插件图标:</td>
	            <td>
	               <a href="javascript:void(0)" class="easyui-linkbutton picFileUpload">上传图片</a>
	               <input type="hidden" name="icon"/>
	            </td>
	        </tr>
	        <tr>
	            <td>运行环境:</td>
	            <td><input class="easyui-textbox" type="text" name="pre" data-options="required:true" style="width: 280px;"></input></td>
	        </tr>
	        <tr>
	            <td>关键字:</td>
	             <td><input class="easyui-textbox" type="text" name="keyword" data-options="required:true" style="width: 100px;"></input></td>
	        </tr>
	        <tr>
	            <td>描述:</td>
	            <td>
	                <textarea style="width:800px;height:300px;visibility:hidden;" name="description"></textarea>
	            </td>
	        </tr>
	       <tr>
	           <td><input type="button"  οnclick="myfile.click();" value="文件地址" ></input></td>
	           <td><input id="file_address" type="text" name="fileAddress" style="width: 280px;"></input></td>            
               <td><input type="file" id="myfile" οnchange="file_address.value=this.value" style="display:none"></input></td>
	        </tr> 
	    </table>
	</form>
	<div style="padding:5px">
	    <a href="javascript:void(0)" class="easyui-linkbutton" οnclick="submitForm()">提交</a>
	    <a href="javascript:void(0)" class="easyui-linkbutton" οnclick="clearForm()">重置</a>
	</div>
</div>
<script type="text/javascript">

	var pluginAddEditor ;
	//页面初始化完成后 调用此方法
	$(function(){
		//创建富文本编辑器
		pluginAddEditor = YuKun.createEditor("#pluginAddForm [name=description]");
		var data = {
				fun:function(node){				
					YuKun.changeItemParam(node, "pluginAddForm");
				}
		};
		//初始化类目选择和图片上传器
		YuKun.init(data);
	});
	
	//提交表单 --> pluginAddForm,   json数据格式转换
	function submitForm(){
		if(!$('#pluginAddForm').form('validate')){
			$.messager.alert('提示','表单还未填写完成!');
			return ;
		}
		//将编辑器中的内容同步到隐藏多行文本中
		pluginAddEditor.sync();

		$.post("/plugin/save",$("#pluginAddForm").serialize(), function(data){
			if(data.status == 200){
				$.messager.alert('提示','新增一条插件信息成功!');
			}
			if(data.status == 400){
				$.messager.alert('提示','你输入的用户名不存在,插入记录失败!');
			}
		});
				
	function clearForm(){
		$('#pluginAddForm').form('reset');
		pluginAddEditor.html('');
	}
}
</script>

(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;
  }
}


C.运行项目后,再次刷新页面,就可以看到效果了





三、统一定义【技能任务单后台管理系统返回数据格式


(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;
        }
    }

}

(3)关键数据节点说明





四、先实现,图片上传功能【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);
    }

    /**
     * 上传文件方法
     * <p>Title: uploadFile</p>
     * <p>Description: </p>
     * @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);
    }

    /**
     * 上传文件方法
     * <p>Title: uploadFile</p>
     * <p>Description: </p>
     * @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字符串。
     * <p>Title: pojoToJson</p>
     * <p>Description: </p>
     * @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> T jsonToPojo(String jsonData, Class<T> beanType) {
        try {
            T t = MAPPER.readValue(jsonData, beanType);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将json数据转换成pojo对象list
     * <p>Title: jsonToList</p>
     * <p>Description: </p>
     * @param jsonData
     * @param beanType
     * @return
     */
    public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) {
        JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
        try {
            List<T> 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);
}



B.接口实现


<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<Users> 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插件信息的查询列表展示我们本篇还没涉及到,放到以后再加,因此,新增了一条插件信息后,我们只能手动的去数据库进行查询:






本篇完。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值