京淘开发1.0

JT开发文档
1.0京淘项目搭建
1.01创建jt 父级项目
1.02选择jar包类型
在这里插入图片描述
1.10添加pom.xml文件

  <!--定义了父级的依赖项 定义了springBoot内部的全部关联配置 -->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.2.2.RELEASE</version>
	<relativePath /> <!-- lookup parent from repository -->
</parent>

<!--springboot2.0版本中 与IDE整合有问题 -->
<properties>
	<java.version>1.8</java.version>
	<!--默认条件下执行的maven解析版本问题 -->
	<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>

<dependencies>

	<!--开箱即用 spring-boot-starter springBoot的启动器 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
		<exclusions>
			<exclusion>
				<groupId>org.junit.vintage</groupId>
				<artifactId>junit-vintage-engine</artifactId>
			</exclusion>
		</exclusions>
	</dependency>

	<!--添加属性注入依赖 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-configuration-processor</artifactId>
		<optional>true</optional>
	</dependency>

	<!--支持热部署 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
	</dependency>

	<!--引入插件lombok 自动的set/get/构造方法插件 -->
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
	</dependency>

	<!--引入数据库驱动 -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<scope>runtime</scope>
		<version>5.1.32</version>
	</dependency>

	<!--springBoot数据库连接 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-jdbc</artifactId>
	</dependency>

	<!--spring整合mybatis-plus -->
	<dependency>
		<groupId>com.baomidou</groupId>
		<artifactId>mybatis-plus-boot-starter</artifactId>
		<version>3.2.0</version>
	</dependency>

	<!--springBoot整合JSP添加依赖 -->
	<!--servlet依赖 -->
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>javax.servlet-api</artifactId>
	</dependency>

	<!--jstl依赖 -->
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>jstl</artifactId>
	</dependency>

	<!--使jsp页面生效 -->
	<dependency>
		<groupId>org.apache.tomcat.embed</groupId>
		<artifactId>tomcat-embed-jasper</artifactId>
	</dependency>

	<!-- 引入aop支持 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-aop</artifactId>
	</dependency>

	<!--spring整合redis -->
	<dependency>
		<groupId>redis.clients</groupId>
		<artifactId>jedis</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.data</groupId>
		<artifactId>spring-data-redis</artifactId>
	</dependency>

	<!--添加httpClient jar包 -->
	<dependency>
		<groupId>org.apache.httpcomponents</groupId>
		<artifactId>httpclient</artifactId>
	</dependency>

	<!--引入dubbo配置 -->
	<!--<dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> 
		<version>0.2.0</version> </dependency> -->

	<!--添加Quartz的支持 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-quartz</artifactId>
	</dependency>
</dependencies>

<!--只添加parent和依赖即可,不需要添加插件 -->

1.2.1构建jt-common
1.2.2选择maven-module方式创建项目
在这里插入图片描述
1.2.3选择jar包类型
在这里插入图片描述
3.格式如下
在这里插入图片描述
1.3.1构建jt-manage项目
1.3.1.1创建项目
在这里插入图片描述
1.3.2选择打包类型
在这里插入图片描述

1.3.3添加继承/依赖/插件
在这里插入图片描述

<dependencies>
	<dependency>
		<groupId>com.jt</groupId>
		<artifactId>jt-common</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</dependency>
</dependencies>

<build>
	<plugins>
		<!--跳过测试类打包 -->
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-surefire-plugin</artifactId>
			<configuration>
				<skip>true</skip>
			</configuration>
		</plugin>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	</plugins>
</build>

1.3.4导入静态资源文件
在这里插入图片描述
1.3.5编辑jt-manage
在这里插入图片描述

 	package com.jt.controller;
 import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;  
@Controller
 public class IndexController {
@RequestMapping("/page/{moduleName}")
public String module(@PathVariable String moduleName) {
	
	return moduleName;
}
}



   package com.jt.controller;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
  import com.jt.service.ItemService;
  @Controller
  public class ItemController {
@Autowired
private ItemService itemService;
}


package com.jt.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.Item;

public interface ItemMapper extends BaseMapper<Item>{

}


package com.jt.service;

public interface ItemService {

}


package com.jt.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.jt.mapper.ItemMapper;

@Service
public class ItemServiceImpl implements ItemService {

@Autowired
private ItemMapper itemMapper;
}


package com.jt;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.jt.mapper")
public class SpringBootRun {

public static void main(String[] args) {
	
	SpringApplication.run(SpringBootRun.class, args);
}

}

1.3.6编辑com.jt.pojo的类

 package com.jt.pojo;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import lombok.experimental.Accessors;
//pojo基类,完成2个任务,2个日期,实现序列化
@Data
@Accessors(chain=true)
public class BasePojo implements Serializable{
private Date created;
private Date updated;

}


package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import lombok.Data;
import lombok.experimental.Accessors;

@JsonIgnoreProperties(ignoreUnknown=true) //表示JSON转化时忽略未知属性
@TableName("tb_item")
@Data
@Accessors(chain=true)
public class Item extends BasePojo{
@TableId(type=IdType.AUTO)
private Long id;				//商品id
private String title;			//商品标题
private String sellPoint;		//商品卖点信息
private Long   price;			//商品价格 Long > dubbo
private Integer num;			//商品数量
private String barcode;			//条形码
private String image;			//商品图片信息   1.jpg,2.jpg,3.jpg
private Long   cid;				//表示商品的分类id
private Integer status;			//1正常,2下架

//为了满足页面调用需求,添加get方法
public String[] getImages(){
	
	return image.split(",");
}
}

2.3.6.1启动效果
在这里插入图片描述
1.4.1编辑manage 里的vo对象

package com.jt.vo;
import java.io.Serializable;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class EasyUITable implements Serializable{

/**
 * 实行不能随意定义,必须满足js数据要求
 */
private Integer total;
private List<?> rows;
}

1.5商品列表展现
1.5.1 商品表设计

create table tb_item
(
id                   bigint(10) not null auto_increment    comment '商品ID,也是商品编号',
title                varchar(100),
sell_point           varchar(150),
 price                bigint(20) comment '单位为:分',
num                  int(10),
barcode              varchar(30),
image                varchar(500) comment '最多5张图片',
cid                  bigint(10),
status               int(1) default 1 comment '默认值为1,可 选值:1正常,2下架,3删除',
created              datetime,
updated              datetime comment '列表排序时按修改 时间排序,所以在新增时需要设置此值。',
primary key (id)
);

1.5.2编辑jt-common pojo

package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.experimental.Accessors;
@JsonIgnoreProperties(ignoreUnknown=true) //表示JSON转化时忽略未知属性
@TableName("tb_item")
@Data
@Accessors(chain=true)
public class Item extends BasePojo{
@TableId(type=IdType.AUTO)		
private Long id;				//商品id
private String title;			//商品标题
private String sellPoint;		//商品卖点信息
private Long   price;			//商品价格 扩大100倍保存
private Integer num;			//商品数量
private String barcode;			//条形码
private String image;			//商品图片信息   1.jpg,2.jpg,3.jpg
private Long   cid;				//表示商品的分类id
private Integer status;			//1正常,2下架


//为了满足页面调用需求,添加get方法
public String[] getImages(){
	
	return image.split(",");
}
}

1.5.5编辑jt-manage ItemController

@RestController  //保证返回值数据都是JSON时使用\
@RequestMapping("/item")
public class ItemController {

@Autowired
private ItemService itemService;

/**
 *    根据条件查询数据信息.
 *  url:http://localhost:8091/item/query?page=1&rows=20
 */
@RequestMapping("/query")
public EasyUITable findItemByPage
					(Integer page,Integer rows) {
	
	return itemService.findItemByPage(page,rows);
}

}

1.5.6编辑 jt-manage ItemService 和ItemServiceImpl

package com.jt.service;
public interface ItemService {

EasyUITable findItemByPage(Integer page, Integer rows); 
}

 package com.jt.service;
 @Service
public class ItemServiceImpl implements ItemService {

@Autowired
private ItemMapper itemMapper;

/*
 * 1.查询商品总记录数
 * 2.进行分页查询
 *   
 *   分页sql:  每页20条
 *   第1页                                                    起始位置,展现条数
 * 	 select * from tb_item limit 0,20 	 [0,19]
 *   第2页
 *   select * from tb_item limit 20,20 	 [20,39]
 *   第3页
 *   select * from tb_item limit 40,20 	 [40,59]
 *    第N页
 *   select * from tb_item order by updated limit (page-1)*rows,rows
 */
@Override
public EasyUITable findItemByPage(Integer page, Integer rows) {
	
	int total = itemMapper.selectCount(null);
	int start = (page - 1) * rows;
	List<Item> userList = 
			itemMapper.findItemByPage(start,rows);
	return new EasyUITable(total, userList);
}
}

1.5.7编辑Mapper接口

package com.jt.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.pojo.Item;

public interface ItemMapper extends BaseMapper<Item>{

@Select("select * from tb_item order by updated desc limit #{start},#{rows}")
List<Item> findItemByPage(@Param("start")Integer start,@Param("rows")Integer rows);

 }

1.6Mybatis-plus方式实现分页

1.6.1编辑业务层ItemServiceImpl

* mybatis-plus分页说明
 * 1.new Page<>(current, size);
 * 	 current:当前页数
 * 	 size:   每页条数
 */
@Override
public EasyUITable findItemByPage(Integer page, Integer rows) {
	
	Page<Item> tempPage = new Page<>(page, rows);
	QueryWrapper<Item> queryWrapper = new QueryWrapper<Item>();
	queryWrapper.orderByDesc("updated");
	//当前查询的分页结果对象
	IPage<Item> IPage = 
			itemMapper.selectPage(tempPage, queryWrapper);
	//获取总记录数
	int total = (int) IPage.getTotal();
	//获取分页的结果
	List<Item> userList = IPage.getRecords();
	return new EasyUITable(total, userList);
}

1.6.2编辑配置类
说明:定义MybatisConfis的配置类,在com.jr.config中

package com.jt.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
@Configuration //配置类
public class MybatisConfig {
 /* <bean id="paginationInterceptor" class=""/> */

//添加分页拦截器,否则分页有问题!!!!
@Bean //将对象交给Spring容器管理
public PaginationInterceptor paginationInterceptor() {
	
	return new PaginationInterceptor();
}
}

1.7 实现商品分类目录回显
1.71格式化价格

return now.format("yyyy-MM-dd  hh:mm:ss");data-o<th ptions="field:'price',width:70,align:'right',formatter:KindEditorUtil.formatPrice">价格</th>

2.common.js

// 格式化价格  value是数据库数据  
   ormatPrice : function(val,row){
	
	return (val/100).toFixed(2);
},

1.7.2格式化时间
1.item-list页面

<th data-options="field:'created',width:130,align:'center',formatter:KindEditorUtil.formatDateTime">创建日期</th>

2.common.js

// 格式化时间
formatDateTime : function(val,row){
	var now = new Date(val);

},

1.8格式化叶子类目
1.8.1页面分析

<th data-options="field:'cid',width:100,align:'center',formatter:KindEditorUtil.findItemCatName">叶子类目</th>

1.8.2编辑common.js

//格式化名称
findItemCatName : function(val,row){
	var name;
	$.ajax({
		type:"get",
		url:"/item/cat/queryItemName",
		data:{itemCatId:val},
		cache:true,    //缓存
		async:false,    //表示同步   默认的是异步的true
		dataType:"text",//表示返回值参数类型
		success:function(data){
    		name = data;
    	}
	});
	return name;
},

1.8.4编辑 jt-common ItemCat pojo对象

package com.jt.pojo;
 import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
@TableName("tb_item_cat")
@Data
@Accessors(chain = true)
public class ItemCat extends BasePojo{
@TableId(type = IdType.AUTO)
private Long id;
private Long parentId;
private String name;
private Integer status;
private Integer sortOrder;	//排序号
private Boolean isParent;   //是否为父级
}

1.8.4编辑jt-manage ItemCatController

@RestController
@RequestMapping("/item/cat")
public class ItemCatController {

@Autowired
private ItemCatService itemCatService;

/**
 * 根据itemCatId查询商品分类名称
 * http://localhost:8091/item/cat/queryItemName?itemCatId=560
 */
@RequestMapping("/queryItemName")
public String findItemCatNameById(Long itemCatId) {
	
	//1.先根据id查询对象
	ItemCat itemCat = 
			itemCatService.findItemCatById(itemCatId);
	//2.将对象中的name名称获取
	return itemCat.getName();
}
}

1.8.5编辑 jt-manage ItemCatService 和ItemCat ServiceImpl

package com.jt.service;
public interface ItemCatService {
ItemCat findItemCatById(Long itemCatId);
}

package com.jt.service;
@Service
public class ItemCatServiceImpl implements    ItemCatService {

@Autowired
private ItemCatMapper itemCatMapper;

@Override
public ItemCat findItemCatById(Long itemCatId) {
	
	return itemCatMapper.selectById(itemCatId);
}
}

1.8.6ajax嵌套问题
说明:当ajax进行嵌套时,一般将内部的ajax的请求方式设置为同步.
在这里插入图片描述
1.8.7页面效果展现

在这里插入图片描述
1京淘项目后台维护
1.1编辑jt-manage vo对象

 package com.jt.vo;
 import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
//[{id:"编号",text:"文本信  息",state:"open/closed"}]
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class EasyUITree {
private Long id;		//节点ID
private String text;	//文本信息
private String state;	//open/closed
}

1.2…1商品分类页面TreeAjax请求
在这里插入图片描述
1.2.2编辑 jt- manage ItemCatController

/**
  *      获取商品分类列表信息
 *  url:/item/cat/list
  *      返回值: EasyUITree
  *  
  *  @RequestParam 获取参数实现数据的转化
 */
@RequestMapping("/list")
public List<EasyUITree> findItemCatByParentId
(@RequestParam(value = "id",defaultValue = "0") 
	Long parentId){
	
	return itemCatService.findItemCatByParentId(parentId);
}

1.2.3编辑 jt-manage ItemCatService

/**
 * 1.根据parentId查询数据库记录
 * 2.循环遍历数据,之后封装EasyUITree的list集合
 */
@Override
public List<EasyUITree> findItemCatByParentId(Long parentId) {
	//1.查询数据
	List<ItemCat> itemCatList = 
				  findItemCatListByParentId(parentId);
	//2.实现数据封装
	List<EasyUITree> treeList = 
			new ArrayList<EasyUITree>(itemCatList.size());
	
	for (ItemCat itemCat : itemCatList) {
		Long id = itemCat.getId();
		String text = itemCat.getName();
		//如果是父级 closed,否则 表示3级标题 open
		String state = itemCat.getIsParent()?"closed":"open";
		EasyUITree tree = new EasyUITree(id, text, state);
		treeList.add(tree);
	}
	
	return treeList;
}

private List<ItemCat> findItemCatListByParentId(Long parentId) {
	QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
	queryWrapper.eq("parent_id", parentId);
	List<ItemCat> itemCatList = 
			itemCatMapper.selectList(queryWrapper);
	return itemCatList;
}

1.2.3页面效果
在这里插入图片描述
1.3商品新增
1.3.1 编辑 jt-common封装SysResult vo 对象

package com.jt.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
*  该类是系统级VO对象.
* @author Administrator
*
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class SysResult {
private Integer status;	//状态码 200成功  201失败
private String  msg;	//提示信息
private Object  data;   //返回数据


/**
 * 1.只是告知用户 执行成功
 * @return
 */
public static SysResult success() {
	
	return new SysResult(200, null, null);
}

/**
 * 2.成功之后返回数据data   String=name
 */
public static SysResult success(Object data) {
	
	return new SysResult(200, null, data);
}

/**
 * 3.成功之后返回msg
 */
public static SysResult success(String msg,Object data) {
	
	return new SysResult(200, msg, data);
}

//失败之后调用
public static SysResult fail(){
	
	return new SysResult(201,"业务执行失败", null);
}
}

1.3.2编辑 jt-manage ItemController

/**
 *  实现商品新增
 */
@RequestMapping("/save")
public SysResult saveItem(Item item) {
	try {
		itemService.saveItem(item);
		return SysResult.success();
	} catch (Exception e) {
		return SysResult.fail();
	}
}

1.3.3编辑 jt-manage ItemService

@Override
public void saveItem(Item item) {
	
	item.setStatus(1)	//表示正常状态
		.setCreated(new Date())
		.setUpdated(item.getCreated());
	itemMapper.insert(item);
}

1.3.4全局异常处理机制

说明:在jt-common中添加SysExecution类.实现全局异常处理.

//返回数据为JSON
@RestControllerAdvice  //异常通知 对Controller层生效
@Slf4j				   //记录日志
public class SysExecution {

//当系统中出现运行时异常时生效
@ExceptionHandler(RuntimeException.class)
public SysResult error(Exception exception) {
	exception.printStackTrace();
	log.error(exception.getMessage());
	return SysResult.fail();
}
}
  2.重构ItemController
 /**
 *  实现商品新增
 */
@RequestMapping("/save")
public SysResult saveItem(Item item) {
	
	itemService.saveItem(item);
	return SysResult.success();
}

1.4商品更新
1.4.1页面跳转过程

text:'编辑',
    iconCls:'icon-edit',
    handler:function(){
    	//获取用户选中的数据
    	var ids = getSelectionsIds();
    	if(ids.length == 0){
    		$.messager.alert('提示','必须选择一个商品才能编辑!');
    		return ;
    	}
    	if(ids.indexOf(',') > 0){
    		$.messager.alert('提示','只能选择一个商品!');
    		return ;
    	}

1.5.1编辑 jt-manage ItemController

/**
 * 实现商品更新
 */
@RequestMapping("/update")
public SysResult updateItem(Item item) {
	
	itemService.updateItem(item);
	return SysResult.success();
}

1.5.2编辑jt-manage ItemService 和ItemServiceImpl

 @Override
public void updateItem(Item item) {
	item.setUpdated(new Date());
	itemMapper.updateById(item);
	//所有数据都更新.
}

1.6.1编辑ItemController

/**
 *   商品下架
 * url:/item/instock
 * type:post
 * params:{ids:111,222}
 */
@RequestMapping("instock")
public SysResult instockItem(Long[] ids) {
	
	int status = 2;	//表示下架
	itemService.updateStatus(ids,status);
	return SysResult.success();
}

1.6.2编辑ItemService

/**
 * 任务:将ids中所有的数据的状态status改为2
 */
@Override
public void updateStatus(Long[] ids, Integer status) {

	//1.小白级别
	/*
	 * for (Long id : ids) { 
	 * Item item = new Item(); 
	 * item.setId(id)
	 * .setStatus(status) .setUpdated(new Date()); 
	 * itemMapper.updateById(item); 
	 * }
	 */
	
	//2.菜鸟级别  sql
	Item item = new Item();
	item.setStatus(status).setUpdated(new Date());
	UpdateWrapper<Item> updateWrapper = new UpdateWrapper<Item>();
	List idList = Arrays.asList(ids);
	updateWrapper.in("id", idList);
	itemMapper.update(item, updateWrapper);
}

1商品后台管理
1.1商品删除
1.1.1页面分析
在这里插入图片描述
1.1.2编辑ItemController

@RequestMapping("delete")
public SysResult deleteItem(Long[] ids) {
	
	itemService.deleteItem(ids);
	return SysResult.success();
}

1.1.3编辑ItemController

@Override
public void deleteItem(Long[] ids) {
	List idList = Arrays.asList(ids);
	itemMapper.deleteBatchIds(idList);
}

1.2.1编辑 jt-common pojo

package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
@TableName("tb_item_desc")
public class ItemDesc extends BasePojo{

@TableId	//只标识主键
private Long itemId;  //必须与item id相同
private String itemDesc;

}

1.2.4编辑ItemController

/**
 *  实现商品新增
 */
@RequestMapping("/save")
public SysResult saveItem(Item item,ItemDesc itemDesc) {
	
	itemService.saveItem(item,itemDesc);
	return SysResult.success();
}

1.2.5编辑ItemService

/**
 * 实现2张表同时入库
 * 
 */
@Override
@Transactional	//事务控制
public void saveItem(Item item,ItemDesc itemDesc) {
	
	item.setStatus(1)	//表示正常状态
		.setCreated(new Date())
		.setUpdated(item.getCreated());
	itemMapper.insert(item);
	//利用Mybatis-plus入库之后,会自动的将主键ID进行回显
	itemDesc.setItemId(item.getId())
			.setCreated(item.getCreated())
			.setUpdated(item.getCreated());
	itemDescMapper.insert(itemDesc);
}

1.3商品详情数据回显
1.3.1页面分析
1.url分析
在这里插入图片描述
2.页面js分析

// 加载商品描述
    			//_data = SysResult.ok(itemDesc)
    			$.getJSON('/item/query/item/desc/'+data.id,function(_data){
    				if(_data.status == 200){
    					//UM.getEditor('itemeEditDescEditor').setContent(_data.data.itemDesc, false);
    					itemEditEditor.html(_data.data.itemDesc);
    				}
    			});

1.3.2编辑ItemController

说明:根据ItemId查询商品详情信息.
/**
 * 根据Id查询商品详情信息
 */
@RequestMapping("/query/item/desc/{itemId}")
public SysResult findItemDescById
				(@PathVariable Long itemId) {
	
	ItemDesc desc = itemService.findItemDescById(itemId);
	
	return SysResult.success(desc);
	//{status:200,msg:'',data:{itemId:"1123123",itemDesc:"html代码"}}
}

1.3.3编辑Item Service

@Override
public ItemDesc findItemDescById(Long itemId) {
	
	return itemDescMapper.selectById(itemId);
}

1.3.4 页面效果
在这里插入图片描述
1.4商品详情更新
1.4.1页面url
在这里插入图片描述
1.4.2编辑ItemController

/**
 * 实现商品更新
 */
@RequestMapping("/update")
public SysResult updateItem(Item item,ItemDesc itemDesc) {
	
	itemService.updateItem(item,itemDesc);
	return SysResult.success();
}

1.4.3编辑ItemService

@Override
@Transactional	//控制事物
public void updateItem(Item item,ItemDesc itemDesc) {
	
	item.setUpdated(new Date());
	itemMapper.updateById(item);
	//所有数据都更新.
	itemDesc.setItemId(item.getId())
			.setUpdated(item.getUpdated());
	itemDescMapper.updateById(itemDesc);
}

1.5 商品删除
1.5.1页面分析
在这里插入图片描述

$.messager.confirm('确认','确定删除ID为 '+ids+' 的商品吗?',function(r){
    	    if (r){
        	    //100,101,102,103
    	    	var params = {"ids":ids};
            	$.post("/item/delete",params, function(data){
        			if(data.status == 200){
        				$.messager.alert('提示','删除商品成功!',undefined,function(){
        					$("#itemList").datagrid("reload");
        				});
        			}else{
        				$.messager.alert("提示",data.msg);
        			}
        		});
    	    }
    	});

1.5.2编辑ItemController

/**
 * url: /item/delete
 *   参数:  {"ids":ids}  100,101,102
 *   返回值: SysResult
 * @return
 */
@RequestMapping("/delete")
public SysResult deleteItems(Long[] ids) {
	
	itemService.deleteItems(ids);
	return SysResult.success();
}

1.5.3编辑ItemService

@Override
@Transactional
public void deleteItems(Long[] ids) {
	
	List<Long> idList = Arrays.asList(ids);
	itemMapper.deleteBatchIds(idList);
	itemDescMapper.deleteBatchIds(idList);
}

京淘后台管理
1.1图片上传
1.1.1入门案例

 <body>
<h1>实现文件长传</h1>
<!--enctype="开启多媒体标签"  -->
<form action="http://localhost:8091/file" method="post" 
enctype="multipart/form-data">
	<input name="fileImage" type="file" />
	<input type="submit" value="提交"/>
</form>
</body>

1.1.2编辑FileController

@RestController
public class FileController {

/**
 * 要求: 实现图片上传,返回上传成功信息
 * 规范: 参数名称必须与页面name属性一致
 * 步骤: 
 * 		1.确定文件上传的路径.
 * 		2.校验文件路径是否正确.
 * 		3.实现文件上传
 * @throws IOException 
 * @throws IllegalStateException 
 */
@RequestMapping("/file")
public String file(MultipartFile fileImage) throws IllegalStateException, IOException {
	String fileDir = "D:/1_JT/images";
	File file = new File(fileDir);
	if(!file.exists()) {
		//如果文件不存在,则新建文件
		file.mkdirs();
	}
	
	String name = fileImage.getName();
	System.out.println("name:"+name);
	String fileName = fileImage.getOriginalFilename();
	
	//D:images/a.jpg
	String realPath = "D:/1_JT/images/"+fileName;
	//实现文件上传
	fileImage.transferTo(new File(realPath));
	
	return "文件上传成功!!!!";
}
}

1.2复文本编辑器实现文件上传
1.2.1图片上传回显数据要求

{"error":0,"url":"图片的保存路径","width":图片的宽度,"height":图片的高度}

参数说明: 0代表是一张图片,如果是0,前台才可以解析并显示。1代表不是图片,
不显示如果不设置宽度和高度,则默认用图片原来的大小,所以不用设置

1.2.2封装Vo对象

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ImageVO {

private Integer error;	//0正常  1失败
private String url;		//图片虚拟路径
private Integer width;	//宽度
private Integer height;	//高度

public static ImageVO fail() {
	
	return new ImageVO(1, null, null, null);
}

public static ImageVO success(String url,Integer width,Integer height) {
	
	return new ImageVO(0, url, width, height);
}
}

1.2.3文件上传页面分析
1.url
在这里插入图片描述
页面js:

//编辑器参数
 kingEditorParams : {
    filePostName : "uploadfile",
    uploadJson : '/pic/up;oad',
    dir : "image"
 },

1.2.4正则表达式
正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen。
1.2.5正则语法

元字符	描述
\	将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\\n”匹配\n。“\n”匹配换行符。序列“\\”匹配“\”而“\(”则匹配“(”。即相当于多种编		程语言中都有的“转义字符”的概念。
^	匹配输入字行首。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$	匹配输入行尾。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
*	匹配前面的子表达式任意次。例如,zo*能匹配“z”,也能匹配“zo”以及“zoo”。*等价于{0,}。
+	匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
?	匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}。
{n}	n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,}	n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m}	m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
?	当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},	{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 ['o', 'o', 'o', 'o']
.点	匹配除“\n”和"\r"之外的任何单个字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式。
(pattern)	匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”或“\)”。
(?:pattern)	非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)	非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)	非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
(?<=pattern)	非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
*python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等
(?<!patte_n)	非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
*python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等
x|y	匹配x或y。例如,“z|food”能匹配“z”或“food”(此处请谨慎)。“[z|f]ood”则匹配“zood”或“food”。
[xyz]	字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz]	负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”任一字符。
[a-z]	字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.
[^a-z]	负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b	匹配一个单词的边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”;“\b1_”可以匹配“1_23”中的“1_”,但不能匹配“21_3”中的“1_”。
\B	匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx	匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d	匹配一个数字字符。等价于[0-9]。grep 要加上-P,perl正则支持
\D	匹配一个非数字字符。等价于[^0-9]。grep要加上-P,perl正则支持
\f	匹配一个换页符。等价于\x0c和\cL。
\n	匹配一个换行符。等价于\x0a和\cJ。
\r	匹配一个回车符。等价于\x0d和\cM。
\s	匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S	匹配任何可见字符。等价于[^ \f\n\r\t\v]。
\t	匹配一个制表符。等价于\x09和\cI。
\v	匹配一个垂直制表符。等价于\x0b和\cK。
\w	匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。
\W	匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
\xn	匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。
\num	匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。
\n	标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
\nm	标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。
\nml	如果n为八进制数字(0-7),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
\un	匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(&copy;)。
\p{P}	小写 p 是 property 的意思,表示 Unicode 属性,用于 Unicode 正表达式的前缀。中括号内的“P”表示Unicode 字符集七个字符属性之一:标点字符。
其他六个属性:
L:字母;
M:标记符号(一般不会单独出现);
Z:分隔符(比如空格、换行等);
S:符号(比如数学符号、货币符号等);
N:数字(比如阿拉伯数字、罗马数字等);
C:其他字符。
*注:此语法部分语言不支持,例:javascript。
\<
\>	匹配词(word)的开始(\<)和结束(\>)。例如正则表达式\<the\>能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。
( )	将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。
|	将两个匹配条件进行逻辑“或”(or)运算。例如正则表达式(him|her) 匹配"it belongs to him"和"it belongs to her",但是不能匹配"it belongs to them."。注意:这个元字符不是所有的软件都支持的。

1.2.6编辑FileController

@Autowired
private FileService fileService;

@RequestMapping("/pic/upload")
public ImageVO uploadFile(MultipartFile uploadFile) {
	
	return fileService.uploadFile(uploadFile);
}

1.2.7编辑FileService

@Service
public class FileServiceImpl implements FileService {

private String localDirPath = "D:/1_JT/images/";
/**
 * 步骤:
 * 	 1.准备文件上传根目录  D:\1_JT\images
 * 	 2.校验文件类型. jpg|png|gif......
 * 	 3.为了检索快速,需要分目录存储   1.按照类型 2.按照商品类目 3.按照时间
 * 	 4.文件名称不能重复  UUID
 */
@Override
public ImageVO uploadFile(MultipartFile uploadFile) {
	
	ImageVO imageVO = null; 
	//1.现获取文件名称  abc.jpg ABC.JPG
	String fileName = uploadFile.getOriginalFilename();
	//2.校验是否为图片类型   字符串的匹配规则 正则表达式
	fileName = fileName.toLowerCase(); //将字符转化为小写
	if(!fileName.matches("^.+\\.(jpg|png|gif)$")) {
		//说明不是图片
		return ImageVO.fail();
	}
	
	//3.校验程序是否为恶意程序. 检查图片是否有宽 高
	try {
		BufferedImage bufferedImage = 
				ImageIO.read(uploadFile.getInputStream());
		int height = bufferedImage.getHeight();
		int width = bufferedImage.getWidth();
		if(height==0 || width == 0) {
			
			return ImageVO.fail();
		}
		
		//4.实现分目录保存. date转为字符串 yyyy/MM/dd
		String datePath = new SimpleDateFormat("yyyy/MM/dd/")
						  .format(new Date());
		
		String fileLocalPath = localDirPath + datePath;
		File fileDir = new File(fileLocalPath);
		if(!fileDir.exists()) {
			
			fileDir.mkdirs();
		}
		
		//5.准备文件名称 uuid.type
		String uuid = UUID.randomUUID().toString();
		int index = fileName.lastIndexOf(".");
		String type = fileName.substring(index); //.jpg
		String uuidName = uuid + type;
		
		//6.实现文件上传.   D:\1_JT\images\2020\01\03\  uuid.jpg
		String realFilePath = fileLocalPath + uuidName;
		uploadFile.transferTo(new File(realFilePath));
		
		String url = "https://img14.360buyimg.com/n0/jfs/t1/56892/29/14466/153329/5db7d937Ef56a8fd2/c6d77f97bbd7e155.jpg";
		imageVO = ImageVO.success(url, width, height);
				
	} catch (IOException e) {
		
		e.printStackTrace();
		return ImageVO.fail();
	}
	return imageVO;
}
}

1.2.8页面效果
在这里插入图片描述
1.3 文件上传优化
1.3.1利用properties 实现数据动态注入
1.3.1.1编辑properties文件

#配置图片路径信息
image.localDirPath=D:/1_JT/images/

1.3.1.2动态注入数据
在这里插入图片描述
1.3.2实现图片真实回显
url网络虚拟路径:
http://mange.jt.com/2020/01/03/a.jpg
本地磁盘路径:
D:\1_JT\images/2020/01/03/a.jpg

说明:应该准备一个网络的虚拟路径为用户提供访问的链接.但是要求网络链接地址能够找到真实图片信息.

1.3.2.1编辑properties文件

#配置图片路径信息
image.localDirPath=D:/1_JT/images/
image.urlPath=http://image.jt.com/

1.3.2.2编辑FileServiceImpl
说明:实现图片虚拟地址注入,并且拼接URL地址,形成真实的本地地址.

@Service
@PropertySource("classpath:/properties/image.properties")
public class FileServiceImpl implements FileService {

@Value("${image.localDirPath}")
private String localDirPath;  // = "D:/1_JT/images/";
@Value("${image.urlPath}")	//
private String urlPath;			

/**
 * 步骤:
 * 	 1.准备文件上传根目录  D:\1_JT\images
 * 	 2.校验文件类型. jpg|png|gif......
 * 	 3.为了检索快速,需要分目录存储   1.按照类型 2.按照商品类目 3.按照时间
 * 	 4.文件名称不能重复  UUID
 */
@Override
public ImageVO uploadFile(MultipartFile uploadFile) {
	
	ImageVO imageVO = null; 
	//1.现获取文件名称  abc.jpg ABC.JPG
	String fileName = uploadFile.getOriginalFilename();
	//2.校验是否为图片类型   字符串的匹配规则 正则表达式
	fileName = fileName.toLowerCase(); //将字符转化为小写
	if(!fileName.matches("^.+\\.(jpg|png|gif)$")) {
		//说明不是图片
		return ImageVO.fail();
	}
	
	//3.校验程序是否为恶意程序. 检查图片是否有宽 高
	try {
		BufferedImage bufferedImage = 
				ImageIO.read(uploadFile.getInputStream());
		int height = bufferedImage.getHeight();
		int width = bufferedImage.getWidth();
		if(height==0 || width == 0) {
			
			return ImageVO.fail();
		}
		
		//4.实现分目录保存. date转为字符串 yyyy/MM/dd
		String datePath = new SimpleDateFormat("yyyy/MM/dd/")
						  .format(new Date());
		
		String fileLocalPath = localDirPath + datePath;
		File fileDir = new File(fileLocalPath);
		if(!fileDir.exists()) {
			
			fileDir.mkdirs();
		}
		
		//5.准备文件名称 uuid.type
		String uuid = UUID.randomUUID().toString();
		int index = fileName.lastIndexOf(".");
		String type = fileName.substring(index); //.jpg
		String uuidName = uuid + type;
		
		//6.实现文件上传.   D:\1_JT\images\2020\01\03\  uuid.jpg
		String realFilePath = fileLocalPath + uuidName;
		uploadFile.transferTo(new File(realFilePath));
		
		//http://image.jt.com/yyyy/MM/dd/
		String url = urlPath + datePath + uuidName;
		imageVO = ImageVO.success(url, width, height);
				
	} catch (IOException e) {
		
		e.printStackTrace();
		return ImageVO.fail();
	}
	return imageVO;
}
}
发布了7 篇原创文章 · 获赞 0 · 访问量 59

猜你喜欢

转载自blog.csdn.net/weixin_45404244/article/details/105177873