笔记三(完成新增操作)

新增操作

        当登陆成功之后会跳转到frameset框架中,点击左侧的新增书籍链接跳转到新增页面,本次的新增页面中包含了书籍类型,书籍出版社,作者的所在地,这几个内容都要从表中进行读取,所以会单独建立相关的操作,在新增的时候,还需要添加操作的用户信息,所以会在控制层中读取登录时设置的session属性“uid”,然后将其设置到书籍信息中。

书籍类型,书籍出版社设置

1、建立BookType.java类

package cn.mldn.szq.model;

import java.io.Serializable;

public class BookType implements Serializable{
	private Integer typeId;
	private String typeName;
}

2、建立IBookTypeDAO.java接口

package cn.mldn.szq.mapper;

import java.util.List;
import org.apache.ibatis.annotations.Select;
import cn.mldn.szq.model.BookType;

public interface IBookTypeDAO {
	@Select("SELECT type_id AS typeId,type_name AS typeName FROM p_booktype")
	public List<BookType> findAll();
}

3、建立IBookTypeService.java接口以及实现类BookTypeServiceImpl.java类

package cn.mldn.szq.service;

import java.util.List;
import cn.mldn.szq.model.BookType;

public interface IBookTypeService {
	public List<BookType> list();
}
package cn.mldn.szq.service.impl;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import cn.mldn.szq.mapper.IBookTypeDAO;
import cn.mldn.szq.model.BookType;
import cn.mldn.szq.service.IBookTypeService;

@Service
public class BookTypeServiceImpl implements IBookTypeService{
	@Resource
	private IBookTypeDAO typeDAO;
	@Override
	public List<BookType> list() {
		return this.typeDAO.findAll();
	}
}

4、建立BookTypeController.java类

package cn.mldn.szq.controller;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.mldn.szq.model.BookType;
import cn.mldn.szq.service.IBookTypeService;

@Controller
@RequestMapping("booktype")
public class BookTypeController {
	@Resource
	private IBookTypeService typeService;
	@RequestMapping("listAll")
	@ResponseBody
	public List<BookType> list(){
		return this.typeService.list();
	}
}

由于出版社的操作与类型的操作完全一样,所以此处只是列出实体类BookPress.java以及

package cn.mldn.szq.model;

import java.io.Serializable;

public class BookPress implements Serializable{
	private Integer pressId;
	private String pressName;
}
package cn.mldn.szq.mapper;

import java.util.List;
import org.apache.ibatis.annotations.Select;
import cn.mldn.szq.model.BookPress;

public interface IBookPressDAO {
	@Select("SELECT press_id AS pressId,press_name AS pressName FROM p_bookpress")
	public List<BookPress> findAll();
}

地址设置

        地址操作中,包括了坐着的省地址和市地址,正如数据库表“p_area”所设计的思路,所有的省的“area_parid ”设置为“0”,而每个省所属的市区的“area_parid ”设置为所在省的“area_id”的值,按照如下的方式设置,在地区的时候,如果分别查询省和市,需要查询两次,而如果每次在查询的时候,判断一下,就可以省很多事。具体设置如下:

1、创建实体类Location.java

package cn.mldn.szq.model;

import java.io.Serializable;

@SuppressWarnings("serial")
public class Location implements Serializable {
	private int locationID;
	private String locationName;
	private int locationPID;
}

        其中将“locationID”和“locationPID”设置为“int”类型,是考虑到,每次查询的时候,如果页面会给后台传递一个location实体对象,如果没有传递,则表示按照默认值进行查询,也就是省信息的查询

2、创建ILocationDAO.java接口

package cn.mldn.szq.mapper;

import java.util.List;
import org.apache.ibatis.annotations.Select;
import cn.mldn.szq.model.Location;

public interface ILocationDAO {
	@Select("SELECT area_id AS locationID,area_title AS locationName FROM p_area"
			+" where area_parid = #{locationPID}")
	public List<Location> findAll(Location location);
}

        其中判断条件“area_parid = #{locationPID}”中,“locationPID”是从页面中传递过来的“locationID”,具体如下设置

3、创建ILocationService.java接口以及LocationServiceImpl.java实现类

package cn.mldn.szq.service;

import java.util.List;
import cn.mldn.szq.model.Location;

public interface ILocationService {
	public List<Location> list(Location vo);
}
package cn.mldn.szq.service.impl;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import cn.mldn.szq.mapper.ILocationDAO;
import cn.mldn.szq.model.Location;
import cn.mldn.szq.service.ILocationService;

@Service
public class LocationServiceImpl implements ILocationService {

	@Resource
	private ILocationDAO locationDAO; 
	
	@Override
	public List<Location> list(Location vo) {
		return this.locationDAO.findAll(vo);
	}
}

4、创建LocationController.java

package cn.mldn.szq.controller;

import java.util.List;
import javax.annotation.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.mldn.szq.model.Location;
import cn.mldn.szq.service.ILocationService;

@Controller
@RequestMapping("location")
public class LocationController {

	@Resource
	private ILocationService locationServcice;
	@RequestMapping("list")
	@ResponseBody
	public List<Location> listlocation(Location location){
		location.setLocationPID(location.getLocationID());
		return this.locationServcice.list(location);
	}	
}

        页面会给控制层传递一个省的“locationID”值,以方便查询相关的市区,所以此处将页面传递过来的“locationID”的值,赋值给“locationPID”,是为了方便思路上的对应关系。如果不设置此处的话,其实也是可以进行正常执行的,只不过在DAO层调用的属性就应该是“locationID”。

新增设置

        有了之前的准备,在接下来就可以直接针对于Book来进行操作,只要在页面中将所需要的信息进行整合即可传递过来。

1、建立实体类

package cn.mldn.szq.model;

import java.io.Serializable;
import cn.mldn.szq.util.PageUtil;

public class Book implements Serializable{
	private Integer bookId;
	private String bookName;
	private String bookAuthor;
	private String bookCover;
	private Double bookPrice;
	private Integer bookTypeId;
	private Integer bookPressId;
	private Integer bookStatus;
	private String bookAddTime;
	private String bookLabel;
	private String bookDesc;
	private Integer authorProId;
	private Integer authorCityId;
	private Integer userId;
}

        上面的信息都只是对应于数据库表“p_book”的基础字段

2、建立IBookDAO.java

package cn.mldn.szq.mapper;

import java.util.List;
import cn.mldn.szq.model.Book;

public interface IBookDAO {
	
    public void doCreate(Book vo);

}

        由于book的操作比较多,所以此处会使用映射文件进行相关方法的实现比较方便

3、建立book-mapper.xml文件

<?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="cn.mldn.szq.mapper.IBookDAO"><!--此处设置相应的持久层接口-->
	
<insert id="doCreate" parameterType="Book">
	INSERT INTO p_book(book_id,book_name,book_author,book_cover,
				book_price,book_type_id,book_press_id,book_status,book_add_time,
				book_label,book_desc,author_proid,author_cityid,user_id)
		VALUES(mo_sq.nextval,#{bookName},#{bookAuthor},#{bookCover},
			#{bookPrice},#{bookTypeId},#{bookPressId},#{bookStatus},to_date(#{bookAddTime},'yyyy-MM-dd'),
			#{bookLabel},#{bookDesc},#{authorProId},#{authorCityId},#{userId})
</insert>
	
</mapper>

        此处的“<insert>”标签中的“id”属性,需要与“IBookDAO.java”接口中相应的方法设置相同,同时设置好相应的参数“parameterType”设置要传递的参数类型,因为在spring-mybatis.xml文件中配置好了具体的model路径,所以此处的实体类参数不需要设置具体的包路径,只需要写类名即可。

4、建立IBookService.java以及实现类BookServiceImpl.java

package cn.mldn.szq.service;

import java.util.Map;
import cn.mldn.szq.model.Book;

public interface IBookService {
	public void add(Book vo);
}	
package cn.mldn.szq.service.impl;

import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import cn.mldn.szq.mapper.IBookDAO;
import cn.mldn.szq.model.Book;
import cn.mldn.szq.service.IBookService;

@Service
public class BookServiceImpl implements IBookService {
	@Resource
	private IBookDAO bookDAO;
	@Override
	public void add(Book vo) {
		this.bookDAO.doCreate(vo);
	}
}

5、建立BookController.java

        在添加数据的时候,需要进行文件的上传操作,所以需要设置相应的上传文件的操作,同时由于前台页面的上传操作使用的是layui的上传组件,所以需要单独设置一个文件上传的控制层路径。
        要访问“addBook.ftl”文件,由于拦截器的存在,所以需要单独设置访问路径,否则不能访问到页面。
        新增操作的时候需要记录用户的信息,而保存用户信息的内容放在了session属性范围“uid”,所以不会再前台页面传递过来,需要在控制层取出该属性值,并未前台接收过来的Book实体类中的“userId”设置对应的内容。

package cn.mldn.szq.controller;

import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import cn.mldn.szq.model.Book;
import cn.mldn.szq.service.IBookService;
import cn.mldn.szq.util.UpDownPicture;

@Controller
@RequestMapping("book")
public class BookController {
	@Resource
	private IBookService bookService;
	
	@RequestMapping("add")
	@ResponseBody
	public String add(HttpServletRequest request,Book vo){
		Integer uid = (Integer) request.getSession().getAttribute("uid");
		if(vo != null){
			vo.setUserId(uid);
			this.bookService.add(vo);
		}
		return "{}";
	}

	@RequestMapping("toAddftl")
	public String toAddftl(){
		return "book/addBook";
	}
	
	@RequestMapping("uploadBookCover")
	@ResponseBody
	Map<String,Object> uploadBookCover(HttpServletRequest request,MultipartFile bookCover) {
		return UpDownPicture.uploadPhoto(request, bookCover);
	}
	
}

       至此,后台的基本内容编写完毕,接下来,需要在前台的“addBook.ftl”文件中将所需要的内容进行整合显示。

完成addBook.ftl文件

1、设置基本的添加字段,并且引入所需要的laiui的js脚本和样式,并且将jQuery的开发包也导入进来。

<#assign base=request.contextPath />
<!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">
<title>Insert title here</title>
<link rel="stylesheet" href="${base}/plugins/layui/css/layui.css">
<link rel="stylesheet" href="${base}/plugins/layui/css/modules/layer/default/layer.css">
</head>
<body>

    <form id="add_book_form">
	<input type="hidden" id="add_book_cover" name="bookCover">
	<table border="1">
		<tr>
			<td>书籍名称</td>
			<td>
				<input name="bookName">
			</td>
		</tr>
		<tr>
			<td>书籍作者</td>
			<td>
				<input name="bookAuthor">
			</td>
		</tr>
		<tr>
			<td>书籍封面</td>
			<td>
				<button type="button" class="layui-btn" id="uploadPic">
	        		<i class="layui-icon">&#xe67c;</i>上传头像
	    		</button>
			</td>
		</tr>
		<tr>
			<td> 预览图:</td>
			<td>
				<blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
			        <div class="layui-upload-list" id="demo1">
			            <p id="demoText"></p>
			        </div>
    			</blockquote>
			</td>
		</tr>
		<tr>
			<td>书籍价格</td>
			<td>
				<input name="bookPrice">
			</td>
		</tr>
		<tr>
			<td>书籍类型</td>
			<td>
				<select id="bookTypeId" name="bookTypeId">
					<option value="-1">--请选择--</option>
				</select>
			</td>
		</tr>
		<tr>
			<td>书籍出版社</td>
			<td>
				<select id="bookPressId" name="bookPressId">
					<option value="-1">--请选择--</option>
				</select>
			</td>
		</tr>
		
		<tr>
			<td>文章状态</td>
			<td>
				<input type="radio" name="bookStatus" value="1"/>上架
				<input type="radio" name="bookStatus" value="2"/>下架
			</td>
		</tr>
		<tr>
			<td>发布日期</td>
			<td>
				<input id="add_book_date" name="bookAddTime">
			</td>
		</tr>
		<tr>
			<td>文章标签</td>
			<td>
				<input type="checkbox" name="bookLabel" value="1"/>校园
				<input type="checkbox" name="bookLabel" value="2"/>青春
				<input type="checkbox" name="bookLabel" value="3"/>政治
				<input type="checkbox" name="bookLabel" value="4"/>经济
			</td>
		</tr>
		<tr>
			<td>书籍描述</td>
			<td>
				<input name="bookDesc" id="bookDesc">
			</td>
		</tr>
		<tr>
			<td>作者所在省</td>
			<td>
				<select id="authorProId" name="authorProId">
					<option value="-1">--请选择--</option>
				</select>
			</td>
		</tr>
		<tr>
			<td>作者所在市</td>
			<td>
				<select id="authorCityId" name="authorCityId">
					<option value="-1">--请选择--</option>
				</select>
			</td>
		</tr>
		<tr>
			<td colspan="2">
				<input type="button" value="提交" id="add_book">
			</td>
		</tr>
	</table>
</form>
<script type="text/javascript" src="${base}/plugins/jquery.min.js"></script>
<script src="${base}/plugins/layui/layui.all.js"></script>
</body>
</html>

2、为日期、简介、图片上传设置相应的layui组件

<script>
	
	//初始化layui相关组件
	layui.use(['form', 'upload', 'layedit', 'laydate'], function(){
            var form = layui.form;
            var upload = layui.upload;
            var edit = layui.layedit;
            var laydate = layui.laydate;
            
            //初始化编辑器
            bookEditor = edit.build("bookDesc"); //其中写富文本简介的id,不加“#”
            
            data_sync = function() {
            	edit.sync(bookEditor);
            }
            
            //初始化日期控件
            laydate.render({
            	elem:"#add_book_date"    //写需要添加日期插件的input的“id”,这里需要加“#”
            });
            
            var ssdd1;
            //普通图片上传--封面
            var uploadInst = upload.render({
            	//绑定上传组件到具体的标签上
                elem: '#uploadPic'
                //文件上传的后台方法
                ,url: '${base}/book/uploadBookCover'
                //文件上传到后台的对象的属性名,如:此处Book中图片的属性为bookCover,控制层接收的参数要与此对应
                ,field:"bookCover"
                //是否开启多文件上传
                ,multiple:true
                //文件上传之前调用,弹出模态窗口
                ,before: function(obj){
                    ssdd1 = layer.open({
                        type: 1
                        ,title: false //不显示标题栏
                        ,closeBtn: false
                        ,shade: 0.4
                        ,moveType: 1 //拖拽模式,0或者1
                        ,content: '<i class="layui-icon layui-anim layui-anim-rotate layui-anim-loop">&#xe63d;</i>'
                    });
                    //预读本地文件示例,不支持ie8
                    obj.preview(function(index, file, result){
                        $('#demo1').html('<img height="80px" src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img">')
                    });
                }
                ,done: function(data){
                	//当一次上传结束之后回调函数
                    $("#add_book_cover").val(data.filepath);
                    layer.close(ssdd1);
                }
                ,error: function(){
                    //演示失败状态,并实现重传
                    var demoText = $('#demoText');
                    demoText.html('<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-mini demo-reload">重试</a>');
                    demoText.find('.demo-reload').on('click', function(){
                        uploadInst.upload();
                    });
                }
            });
    });
</script>

        此处的引入中,需要注意的是富文本编辑器的在引入的时候不需要为相应的<input>表单的“id”属性加“#”;
        但是在日期插件的<input>的“id”属性需要加“#”;
        并且还需要设置文件上传的访问路径,以及绑定触发的控件“id”,然后设置好与实体类对应的参数名称“field”
   绑定要预览的位置,因为此处打开了多文件上传,所以如果需要多图片预览的时候,需要修改“$('#demo1').html()”为“$('#demo1').append()”即可。

3、设置相应的类型,和出版社

$(function(){
		//类型
		$.ajax({
			url:"${base}/booktype/listAll",
			type:"post",
			dataType:"json",
			data:"{}",
			success:function(data){
				for(var x = 0; x < data.length ; x ++){
					add_select_Row("bookTypeId",data[x].typeId,data[x].typeName);
				}
			} 
		});
		//出版社
		$.ajax({
			url:"${base}/bookpress/listAll",
			type:"post",
			dataType:"json",
			data:"{}",
			success:function(data){
				for(var x = 0; x < data.length ; x ++){
					add_select_Row("bookPressId",data[x].pressId,data[x].pressName);
				}
			}
		});
		//省
		$.ajax({
			url:"${base}/location/list",
			type:"post",
			dataType:"json",
			data:"{}",
			success:function(data){
				for(var x = 0; x < data.length ; x ++){
					//console.log(data[x].locationID +","+ data[x].locationName);
					add_select_Row("authorProId",data[x].locationID,data[x].locationName);
				}
			}
		});
	});
	
	$("#authorProId").on("change",function(){
		//市
		var parentId = $(this).val();
		$.ajax({
			url:"${base}/location/list",
			type:"post",
			dataType:"json",
			data:{locationID:parentId},
			success:function(data){
				$("#authorCityId option:gt(0)").remove();
				for(var x = 0; x < data.length ; x ++){
					//console.log(data[x].locationID +","+ data[x].locationName);
					add_select_Row("authorCityId",data[x].locationID,data[x].locationName);
				}
			}
		});
	});
	
	function add_select_Row(eleId,contentId,contentTitle){
		$("#"+eleId).append(
				"<option value='"+ contentId +"'>"+ contentTitle +"</option>"
		);
	}

        类型,和出版社,以及省的设置都需要在页面加载的时候进行设置好,而市区的设置却需要在省进行变化时在动态的进行访问添加,也就是二级联动,而此处需要注意的是,因为我使用的是append()方法,所以每次在添加市区的时候,需要先删除之前的内容“$("#authorCityId option:gt(0)").remove();”

4、最后进行表单的提交处理

//提交表单
	$("#add_book").click(function() {
		//进行数据同步
		data_sync();
		$.ajax({
			url:"${base}/book/add",
			data:$("#add_book_form").serialize(),
			type:"post",
			dataType:"json",
			success:function(data) {
				alert("新增成功")
				location.href = "${base}/book/list";
			}
		});
	});

        此处需要将富文本编辑其中设置的内容同步到该内容中。

至此,所以的添加任务完成。

其中,在控制层进行的上传图片所调用的方法封装为UpDownPicture.java:

package cn.mldn.szq.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile;

public class UpDownPicture {
	/**
	 * <pre>uploadPhoto(这里用一句话描述这个方法的作用)
	 * @param request : HttpServletRequest的对象
	 * @param Photo :所要上传的图片文件
	 * @return 将保存好的文件名称以Map形式返回</pre>
	 */
	public static Map<String,Object> uploadPhoto(HttpServletRequest request,MultipartFile Photo){
		Map<String,Object> map = new HashMap<String,Object>();
		if(Photo.getSize() > 0){
			String realpath = request.getServletContext().getRealPath("/") + "/upload/";
			File file = new File(realpath);
			if(!file.exists()){
				file.mkdirs();
			}
			
			String originalFilename = Photo.getOriginalFilename();
			String newFileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
			
			try {
				Photo.transferTo(new File(realpath + newFileName));
				map.put("filepath", "/upload/" + newFileName);
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return map;
	}
	
	/**
	 * <pre>downLoadFile(这里用一句话描述这个方法的作用)   
	 * 用于图片下载操作
	 * @param response :HttpServletResponse对象
	 * @param request:HttpServletRequest对象
	 * @param photoTitle:要下载的图片名称</pre>
	 */
	public static void downLoadFile(HttpServletResponse response, HttpServletRequest request, String photoTitle) {
		String realPath = request.getServletContext().getRealPath("/") + photoTitle;
		File file = new File(realPath);
		if (file.exists()) {
			response.setCharacterEncoding("utf-8");
	        response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
	        response.setHeader("Content-Type", "application/octet-stream");
	        FileInputStream inputStream = null;
	        ServletOutputStream outputStream = null;
	        try {
	        	inputStream = new FileInputStream(file);
				outputStream = response.getOutputStream();
				byte[] b = new byte[1024];
				int read = inputStream.read(b);
				while (-1 != read) {
					outputStream.write(b);
					outputStream.flush();
					//读取下一次
					read = inputStream.read(b);
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				if (null != outputStream) {
					try {
						outputStream.close();
						outputStream = null;
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if (null != inputStream) {
					try {
						inputStream.close();
						inputStream = null;	//方便GC更快回收
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/xiaoxiaoqiang666/article/details/81101178