先说一下感想:啊,我终于把1.0版本的做完了,这个项目时17年的视频,比较老了,做过的人也挺多的,在网上搜索某个模块都是可以搜到的。但在编写的过程中还是出现了很多问题,特别是js方面的。刚开始接触这个项目的时候是先编写了一堆的配置,这些前期工作都进行了差不多两天,也不知道自己写的对不对,也听不太懂这些配置,就觉得很没意思不想继续了,但是还是坚持下来了,直到今天,把1.0版本的写完了,当然里面有的章节我跳过了(阿里云部署和微信平台的开发),因为时间太紧了,来不及了/(ㄒoㄒ)/~~

下面先说一下项目大致流程
1、创建实体类和数据库表
2、搭建spring的环境
3、Logback日志配置
4、Thumbnailator对图片的处理
5、各功能模块的开发(店铺,商品,前端展示系统)

1、 实体类分析设计

注意:在设计实体类时,设计为引用类型。因为基础类型的会有默认赋值,而引用类型不会自动赋值。

项目总体上分为店家管理系统的开发和前端展示系统的开发

2、店家管理系统

店家管理系统分为店铺和商品两个模块。
店铺:
主要功能:店铺列表的展示,店铺信息的修改,增加店铺


商品
主要功能:商品列表的展示,商品信息的修改,商品类别的增删改,商品详情的展示

3、前端展示系统

前端展示系统用的主要是SUI Mobile 里面的模板,根据自己的需要来选择
前端展示系统需要注意的是:因为我把头条信息存在了redis里面,所以要先开启redis,才能获取数据,显示页面,不然页面一片空白,下面会说到。

4、里面用到的大大小小的技术

4.1、Logback日志配置

因为我上个项目用的是SSM里面的AOP日志,它是利用spring的AOP来进行日志操作,即记录下你对系统的操作存到数据库。而这个使用的logback
1、导入jar包

 <!-- 1.日志 --><!-- 实现slf4j接口并整合 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version><scope>test</scope></dependency><dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.2</version></dependency>

2、编写配置文件logback.xml

<?xml version="1.0" encoding="utf-8"?><!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 --><configuration scan="true" scanPeriod="60 seconds" debug="false"><!-- 定义参数常量 --><property name="log.level" value="debug" /><property name="log.maxHistory" value="30" /><!--<property name="log.filePath" value="C:/logs/log" />--><property name="log.filePath" value="${catalina.base}/logs/webapps"/><property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}[%thread]%-5level %logger{50} - %msg%n" /><!-- 输出到控制台 --><appender  name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${log.pattern}</pattern></encoder></appender><!--输出到文件--><!-- debug级别 --><appender name="debugAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.filePath}/debug.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 文件名称 --><fileNamePattern>${log.filePath}/debug/debug.%d{yyyy-MM-dd}.log.gz</fileNamePattern><!-- 文件最大保存的数量 --><maxHistory>${log.maxHistory}</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>DEBUG</level><onMatch>ACCEPT</onMatch><onMisMatch>DENY</onMisMatch></filter></appender><!-- ERROR级别 --><appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.filePath}/error.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 文件名称 --><fileNamePattern>${log.filePath}/error/error.%d{yyyy-MM-dd}.log.gz</fileNamePattern><!-- 文件最大保存的数量 --><maxHistory>${log.maxHistory}</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>ACCEPT</onMatch><onMisMatch>DENY</onMisMatch></filter></appender><!-- info级别 --><appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.filePath}/info.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 文件名称 --><fileNamePattern>${log.filePath}/info/info.%d{yyyy-MM-dd}.log.gz</fileNamePattern><!-- 文件最大保存的数量 --><maxHistory>${log.maxHistory}</maxHistory></rollingPolicy><encoder><pattern>${log.pattern}</pattern></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>INFO</level><onMatch>ACCEPT</onMatch><onMisMatch>DENY</onMisMatch></filter></appender><root level="info"><appender-ref  ref="consoleAppender"/></root><logger name="com.mooc.o2o" level="${log.level}" additivity="true"><appender-ref ref="debugAppender"/><appender-ref ref="infoAppender"/><appender-ref ref="errorAppender"/></logger>
</configuration>

(当初写配置写到差点崩溃)

3、验证配置

package com.mooc.web.superadmin;import com.mooc.entity.Area;
import com.mooc.service.AreaService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 java.util.HashMap;
import java.util.List;
import java.util.Map;@Controller
@RequestMapping("/superadmin")
public class AreaController {Logger logger= LoggerFactory.getLogger(AreaController.class);@Autowiredprivate AreaService areaService;@RequestMapping(value = "/listArea")@ResponseBody  //将结果转为json对象public Map<String,Object> listArea() throws Exception {logger.info("=====start===");long startTime=System.currentTimeMillis();Map<String,Object> modelMap=new HashMap<String, Object>();List<Area> Areas = areaService.getListArea();modelMap.put("rows",Areas);modelMap.put("total",Areas.size());long endTime=System.currentTimeMillis();logger.debug("costTime:[{}ms]",endTime-startTime);logger.info("=====end===");return modelMap;}
}

4.2、Thumbnailator图片处理

Thumbnailator 是一个优秀的图片处理的Google开源Java类库。处理效果远比Java API的好。从API提供现有的图像文件和图像对象的类中简化了处理过程,两三行代码就能够从现有图片生成处理后的图片,且允许微调图片的生成方式,同时保持了需要写入的最低限度的代码量。还支持对一个目录的所有图片进行批量处理操作。

支持的处理操作:图片缩放,区域裁剪,水印,旋转,保持比例。

1、使用Thumbnailator给店铺添加水印,并输出缩略图,保存到webapp外部的指定路径,为什么不将图片保存到webapp目录下:

(1)tomcat目录下的webapps 文件夹是部署目录,当项目重新部署(Tomcat重启、代码改变时的自动部署),上传的文件不在部署文件的范畴内,即此时开发工具中没有上传的文件,所以上传的文件会被自动删除。

清理缓存也会使上传到webapps目录下的文件文件消失。

(2)如果能保存的话,随着用户上传图片,webapp项目体积就会增大,影响部署。并且图片和webapp耦合在一起,如果webapp删除了,那么图片也就会丢失。

摘自Thumbnailator

1、导入jar包

 <!--图片相关--><!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator --><dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.8</version></dependency>

主要涉及类

ImageUtil:保存图片到指定路径下

package com.mooc.util;import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;public class ImageUtil {//String basePath=Thread.currentThread().getContextClassLoader().getResource("").getPath();private static String basePath="C:\\Users\\大 大\\Desktop\\About learn\\java学习\\代码\\IdeaProgrames\\SSM\\o2o-1\\src\\main\\resources\\watermark.jpg";private static final SimpleDateFormat sDateFormat=new SimpleDateFormat("yyyyMMddHHmmss");private static final Random r=new Random();private static Logger logger = LoggerFactory.getLogger(ImageUtil.class);//用来处理缩略图(参数用户传递过来的文件,和要存储的路径)   门面图//用户传来的参数可能会重名,我们用自己的public static String generateThumbnail(ImageHolder thumbnail, String targetAddr){String realFileName=getRandomFileName();String extension = getFileExtension(thumbnail.getImageName());makeDirPath(targetAddr);String relativeAddr = targetAddr + realFileName + extension;File dest=new File(PathUtil.getImgBasePath()+relativeAddr);try {Thumbnails.of(thumbnail.getImage()).size(200,200).watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(basePath)),0.5f)//添加水印.outputQuality(0.7f).toFile(dest);//压缩图片} catch (IOException e) {throw new RuntimeException("创建缩略图失败:" + e.toString());}return relativeAddr;}//获取输入文件流的扩展名public static String getFileExtension(String fileName) {return fileName.substring(fileName.lastIndexOf("."));//获得最后.}//创建目标路径所设计到的目录,即/home/work/xiangze/xxx.jpg,// 那么home   work  xiangze 这三个文件夹都要自动创建private static void makeDirPath(String targetAddr) {String realFileParentPath=PathUtil.getImgBasePath()+targetAddr;File dirPath=new File(realFileParentPath);if (!dirPath.exists()){dirPath.mkdirs();}}//生成随机文件名,当前年月日消失分钟秒钟+随机五位数public static String getRandomFileName() {//获得随即五位数int rannum=r.nextInt(89999)+10000;String nowTimeStr=sDateFormat.format(new Date());return nowTimeStr + rannum;}/*跟新图片,删除原文件* storePath是文件的路径,则删除文件。如果是目录路径,则删除该目录下的所有文件*/public static void deleteFileOrPath(String storePath){//获得全路径File fileOrPath=new File(PathUtil.getImgBasePath()+storePath);if (fileOrPath.exists()){//删除目录下的所有文件if(fileOrPath.isDirectory()){File files[]=fileOrPath.listFiles();for (int i = 0; i <files.length ; i++) {files[i].delete();}}fileOrPath.delete();}}/*根据输入流,生成详情图片,并返回新生成图片的相对地址
* */public static String generateNormalImg(ImageHolder thumbnail,String targetAddr) {//获取文件的随机名称String realFileName=getRandomFileName();//获取用户上传的文件扩展名称(文件后缀)String extension=getFileExtension(thumbnail.getImageName());//创建图片的存储目录(这个目录包括根目录加上相对目录)makeDirPath(targetAddr);//图片的相对目录(带文件名)String relativeAddr = targetAddr +realFileName + extension;logger.debug("图片的相对路径:"+relativeAddr);//图片的绝对目录File dest = new File(PathUtil.getImgBasePath() + relativeAddr);logger.debug("图片完整路径:"+dest.getAbsolutePath());//调用 Thumbnails生成带有水印的图片try {//可以传入文件,也可以传入图片流Thumbnails.of(thumbnail.getImage()).size(337, 640).watermark(Positions.BOTTOM_RIGHT,ImageIO.read(new File(basePath)),0.25f).outputQuality(0.9f).toFile(dest);}catch (IOException e) {logger.error(e.toString());e.printStackTrace();}return relativeAddr;}public static void main(String[] args) throws IOException {//获得当前线程的路径//String basePath=Thread.currentThread().getContextClassLoader().getResource("").getPath();// String basePath="C:\\Users\\大 大\\Desktop\\About learn\\java学习\\代码\\IdeaProgrames\\SSM\\o2o-1\\src\\main\\resources\\hh.png";//System.out.println(basePath);Thumbnails.of(new File("C:\\Users\\大 大\\Desktop\\About learn\\ps图片\\11.jpg")).size(200,200).watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(basePath)),0.5f)//添加水印.outputQuality(0.7f).toFile("C:\\Users\\大 大\\Desktop\\About learn\\ps图片\\oo.jpg");//压缩图片}}

PathUtil:被ImageUtil和其他类所调用,主要用于产生图片保存的根路径、指定商铺ID的目录路径等。

package com.mooc.util;public class PathUtil {//获得系统的分隔符private static String separator=System.getProperty("file.separator");//返回项目的根路径public static String getImgBasePath(){//获得系统名称String os=System.getProperty("os.name");String basePath="";if (os.toLowerCase().startsWith("win")){basePath="C:/XiaoYuanShangPu/image";}else {basePath="/home/XiaoYuanShangPu/image";}basePath=basePath.replace("/",separator);return basePath;}//根据项目返回图片的子路径public static String getShopImagePath(Long shopId){String imagePath="/upload/item/shop/"+shopId +"/";return imagePath.replace("/",separator);}
}

此处要注意水印图片的存放位置:存两处:
1、resources下

2、test下面的resources下

不然会报javax.imageio.IIOException: Can’t read input file!

3、CommonsMultipartFile service测试相关

因为CommonsMultipartFile是由前台传递过来并且由SpringMVC封装得来的,我们如果使用CommonsMultipartFile进行JUnit测试,很难构造出CommonsMultipartFile这个对象,所以我们在上传图片的方法上将参数设置为File或者InputStream类型,这样能够构造File对象并对service层店铺注册逻辑进行测试。

但是后面到了controller层又把参数改为了图片包装类,因为之间的转换问题。

基于Apache Commons FileUpload的文件上传,CommonsMultipartFile用来处理图片,获取前端传过来的文件流,转换为shopImg

图片包装类

package com.mooc.util;import java.io.InputStream;
/*封装图片缩略图
* */
public class ImageHolder {private String imageName;private InputStream image;public ImageHolder(String imageName, InputStream image) {this.imageName = imageName;this.image = image;}public String getImageName() {return imageName;}public void setImageName(String imageName) {this.imageName = imageName;}public InputStream getImage() {return image;}public void setImage(InputStream image) {this.image = image;}
}

文件上传也是需要jar包的

  <!--文件上传的jar--><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.2</version></dependency>

4.3、kaptcha验证码

读作:卡普查

SSM校园商铺项目1.0总结相关推荐

  1. 校园商铺平台1.0学习

    做完校园商铺平台O2O小项目1.0,项目来源慕课网,记录一下平时遇到的问题?: 项目简介: 项目1.0中使用SSM技术快速迭代出版校园商铺1.0:同时包含MySQL主从同步实现读写分离,利用SUI M ...

  2. java项目-第122期ssm校园快递物流管理系统-计算机毕业设计项目

    java项目-第122期ssm校园快递物流管理系统-计算机毕业设计项目 [源码请到资源专栏下载] Hi,大家好,今天分享的源码是<ssm校园快递物流管理系统>. 这款系统分为三个角色:管理 ...

  3. SpringBoot+Vue项目校园商铺系统

    文末获取源码 开发语言:Java 框架:springboot+vue Node:node.js JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7/8.0 数据库工具:Nav ...

  4. 校园商铺o2o实战(SSM版)

    校园商铺O2O

  5. 计算机毕业设计ssm校园招聘管理系统968b0系统+程序+源码+lw+远程部署

    计算机毕业设计ssm校园招聘管理系统968b0系统+程序+源码+lw+远程部署 本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 开发软件:idea eclipse 前端技术:Layui. ...

  6. (附源码)Springboot校园商铺系统 毕业设计 052145

    Springboot校园商铺系统的设计与实现 摘 要 科技进步的飞速发展引起人们日常生活的巨变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用.信息时代的到来已成为不可阻挡 ...

  7. 计算机毕业设计JAVA校园商铺mybatis+源码+调试部署+系统+数据库+lw

    计算机毕业设计JAVA校园商铺mybatis+源码+调试部署+系统+数据库+lw 计算机毕业设计JAVA校园商铺mybatis+源码+调试部署+系统+数据库+lw 本源码技术栈: 项目架构:B/S架构 ...

  8. Springboot校园商铺系统的设计与实现052145毕业设计源码

    Springboot校园商铺系统的设计与实现 摘要 科技进步的飞速发展引起人们日常生活的巨大变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用.信息时代的到来已成为不可阻挡 ...

  9. java毕业设计校园商铺mybatis+源码+调试部署+系统+数据库+lw

    java毕业设计校园商铺mybatis+源码+调试部署+系统+数据库+lw java毕业设计校园商铺mybatis+源码+调试部署+系统+数据库+lw 本源码技术栈: 项目架构:B/S架构 开发语言: ...

最新文章

  1. HMM——维特比算法(Viterbi algorithm)
  2. There is no isNullOrEmpty for collections in Guawa
  3. 4.5 搭建深层神经网络块-深度学习-Stanford吴恩达教授
  4. pytorch 笔记:tensorboardX
  5. 在SAP中进行黏贴时必须要把之前的数据删掉后才能黏贴,不能直接使用黏贴来覆盖之前的数据,这个怎麼解?
  6. mac 安装cmake
  7. 你在「动森」里遇到的那些「丑动物」,后来怎么样了?
  8. ubuntu 18.04 install gitlab-ce
  9. sh: 0: getcwd() failed: No such file or directory解决
  10. Windows7 Credential Manage
  11. [sol]250OJ 1~10
  12. C++中的模板template typename T
  13. Android系统架构与系统源码目录
  14. SpringBoot文件上传文件大小限制The field file exceeds its maximum permitted size of 1048576 bytes.
  15. 郑州大学计算机上机模拟题库,郑州大学VB考试模拟试题
  16. 阵列信号处理笔记-波达方向DOA-子空间方法
  17. 白话讲解Dubbo服务
  18. 怎么知道跟交换机互联的交换机_电话交换机日常怎么维护和保养?
  19. 阻容感基础05:电容器原理(1)-电容器模型
  20. 『实践』VirtualBox 5.1.18+Centos 6.8+hadoop 2.7.3搭建hadoop完全分布式集群及基于HDFS的网盘实现...

热门文章

  1. Python-006-灰色关联分析法
  2. 高速电路回流路径分析
  3. 厦门大学考研真题笔记:公共卫生硕士
  4. gradle的build.gradle详解
  5. 运维:CMDB好用和用好,差别还是挺大的!
  6. echart图表中,给数据添加单位符号
  7. 【java】jdb调试java代码
  8. mosh--sql教程个人笔记-高级-索引
  9. 超顺磁氧化铁纳米颗粒/CoFe2O4@MnFe2O4/磁性材料CoFe2O4(443 W/g)/氧化铁纳米环
  10. java互联网招聘系统