心得体会

最近通过慕课网学习了《基于springboot企业微信点餐系统项目》,干货满满,既有springboot知识的学习,又有业务逻辑的处理体会。更多的是接触了企业级开发过程中各种编程心得和技巧,能够很大程度的帮助我们规范开发的流程,使得我们的代码更加优雅和实现可维护性。

git地址:https://gitee.com/jiayuan1234/sell

关于springcloud的可以看参考这篇文章:https://blog.csdn.net/zhang_jiayuan/article/details/83994948

基于springboot

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置,也就是人们常说的“约定大于配置”。

使用体会

基于springboot进行开发,最直观的感受就是,它使得我们能在很短的时间内快速搭建一个项目环境,并且能够方便的集成各种优秀组件,通过application.yml文件进行统一配置和管理。同时它也是基于maven构建,以传统的ssm框架为基础,帮助我们更好的开发spring应用程序,很好的解决了先前“配置地狱”的苦恼,使得我们能够更加专注于业务逻辑的开发,提高效率。

项目准备

jdk:1.8.0_65

mysql:5.7.1

maven:3.3.9

redis: 3.0.6

springboot-version: 1.5.4.RELEASE

IDE:  Intellij IDEA 2017.2,navicat 12

本次学习是跟随慕课网上《基于springboot企业微信点餐系统》进行的,以Spring Boot和微信特性为核心技术栈,实现一个从下单到接单流程完整,包含买家端和卖家端前后台功能的微信点餐系统,一步步设计并开发一个中小型企业级Java应用。

项目结构

通过IDEA创建springboot项目,Spring Initializr帮我们初始化了项目目录,主要包括main(java,resources),test。如下是到com.imooc这一层级,再以下均为自定义

maven依赖

spring-boot-starter-*起步依赖是SpringBoot核心之处,它提供了Spring和相关技术提供一站式服务,让开发者不再关心Spring相关配置,简化了传统的依赖注入操作。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.imooc</groupId><artifactId>sell</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>sell</name><description>Demo project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.4.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><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></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId></dependency><dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>3.1.0</version></dependency><dependency><groupId>cn.springboot</groupId><artifactId>best-pay-sdk</artifactId><version>1.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.2.0</version></dependency></dependencies><build><finalName>sell</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

application.yml配置

替代传统的application.properties,配置和使用更为简洁

注意yml文件空格递进表示的层级配置,key-value格式,注意value值要在key值冒号后面空格一位,在IDE中可通过颜色高亮看出配置文件是否有误

spring:datasource:driver-class-name: com.mysql.jdbc.Driverusername: rootpassword: 123456url: jdbc:mysql://localhost:3306/sell?characterEncoding=utf-8&useSSL=falsejackson:default-property-inclusion: non_nullredis:host: ***.**.**.***port: 6379
server:context-path: /sell
wechat:#公众平台idmpAppId: wx777f4f5e7f1ccef7#公众平台密钥mpAppSecret: ebb4f15df7e750a88777b8b9dd88f86c#开放平台idopenAppId: x6ad144e54af67d87#开放平台密钥openAppSecret: 91a2dd6s38a2bbccfb7e9#商户号mchId: 1409146202#商户密钥mchKey: c976503d34ca432c601361f969fd8d85#商户证书路径keyPath: /var/weixin_cert/h5.p12#微信支付异步通知地址notifyUrl: http://sell.natapcc/sell/pay/notify#微信模版idtemplateId:orderStatus: e-Cqq67QxD6YNI41iRqawEYdFavW_7pc7LyEMb-yeQ
projectUrl:wechatMpAuthorize: http://sell.natapp4.ccwechatOpenAuthorize: http://sell.natapp4.ccsell: http://localhost:8080logging:level:com.imooc.dataobject.mapper: trace
mybatis:mapper-locations: classpath:mapper/*.xml

SpringbootApplication一键部署和启动

在 SpringbootApplication 文件中右键 Run as -> Java Application。当看到 “Tomcat started on port(s): 8080 (http)” 字样说明启动成功。

基础注解为@SpringBootApplication,用于将该类标识和注解为启动类

当使用注解式sql语句编写时,需要在此加入注解扫描来指定mapper文件,也可以直接在application.yml文件中配置mybatis.mapper-locations:classpath:mapper/*.xml.

@EnableCaching增加对缓存的支持

package com.imooc;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;@SpringBootApplication
@MapperScan(basePackages = "com.imooc.dataobject.mapper")
@EnableCaching
public class SellApplication {public static void main(String[] args) {SpringApplication.run(SellApplication.class, args);}
}

使用logback日志

在resources文件夹下创建logback-spring.xml文件,并在application.yml文件中加入配置(如日志打印级别)

日志级别包括:TRACE<DEBUG<INFO<WARN<ERROR,其中常用的是DEBUG、INFO和ERROR。如果logger没有被分配级别,name它将从有被分配级别的最近的父类那里继承级别,root logger默认级别是DEBUG。级别在高于或等于其logger的有效级别时为启用,否则为禁用。只有在请求级别大于有效级别时,该请求才会被执行,并打印或输出日志

<?xml version="1.0" encoding="UTF-8" ?><configuration><appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender"><layout class="ch.qos.logback.classic.PatternLayout"><pattern>%d - %msg%n</pattern></layout></appender><appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>DENY</onMatch><onMismatch>ACCEPT</onMismatch></filter><encoder><pattern>%msg%n</pattern></encoder><!--滚动策略--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--路径 /var/log/tomcat/sell/info.%d.log--><fileNamePattern>/D://MyData//workspace//IDEA//sell-log//info.%d.log</fileNamePattern></rollingPolicy></appender><appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender"><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>ERROR</level></filter><encoder><pattern>%msg%n</pattern></encoder><!--滚动策略--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--路径  /var/log/tomcat/sell/error.%d.log --><fileNamePattern>/D://MyData//workspace//IDEA//sell-log//error.%d.log</fileNamePattern></rollingPolicy></appender><root level="info"><appender-ref ref="consoleLog" /><appender-ref ref="fileInfoLog" /><appender-ref ref="fileErrorLog" /></root></configuration>

使用lombok简化bean开发

在项目中使用Lombok可以减少很多重复代码的书写。比如说getter/setter/toString等方法的编写。

打开IDEA的Setting –> 选择Plugins选项 –> 选择Browse repositories –> 搜索lombok –> 点击安装 –> 安装完成重启IDEA –> 安装成功。该插件还可以解决IntelliJ 注解@Slf4j后找不到log问题

在pom.xml文件中添加Lombok依赖

常用注解有 @Getter,@Setter,@Data

@Data
@Entity
public class SellerInfo {@Idprivate String sellerId;private String username;private String password;private String openid;
}

使用JavaBean读取配置文件

通过@Data注解可以获得该bean中的属性值

通过@ConfigurationProperties(prefix="xxx")可以指定application.yml文件中以xxx开头的配置项,并将其配置值注入到相应的变量中,实现对配置文件的读取

通过@Component 将普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>

@Data
@ConfigurationProperties(prefix = "projectUrl")
@Component
public class ProjectUrlConfig {/*** 微信公众平台授权url*/public String wechatMpAuthorize;/*** 微信开放平台授权url*/public String wechatOpenAuthorize;/*** 点餐系统*/public String sell;
}

自定义异常

通过继承RuntimeException 定义一个异常类,提供构造方法完成code和message的初始化

加入@Getter注解,对外提供异常信息的获取

@Getter
public class SellException extends RuntimeException {private Integer code;public SellException(ResultEnum resultEnum){super(resultEnum.getMessage());this.code = resultEnum.getCode();}public SellException(Integer code,String message){super(message);this.code = code;}
}

全局异常处理

在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping中。该注解很多时候是应用在全局异常处理中,类似本案例这种处理方式。

通过 @ExceptionHandler(value= xxxException.class)实现对异常的捕获,并获取异常的详细信息和错误码,处理后返回

通过@ResponseStatus(HttpStatus.FORBIDDEN)  设置响应状态码,具体状态码参考HttpStatus枚举类

@ControllerAdvice
public class SellExceptionHandler {@Autowiredprivate ProjectUrlConfig projectUrlConfig;@ExceptionHandler(value= SellerAuthorizeException.class)@ResponseStatus(HttpStatus.FORBIDDEN)  //设置响应状态码public ModelAndView handlerAuthorizeException(){return new ModelAndView("redirect:".concat(projectUrlConfig.getWechatOpenAuthorize()).concat("/sell/wechat/qrAuthorize").concat("?returnUrl=").concat(projectUrlConfig.getSell()).concat("/sell/seller/login"));}@ExceptionHandler(value= SellException.class)@ResponseBodypublic ResultVO handerSellerException(SellException e){return ResultVOUtil.error(e.getCode(),e.getMessage());}
}

设定系统常量

在开发中,我们会需要使用到一些常量并且共享,为了保持常量值统一不变和避免魔幻数字的使用,需要将此常量值进行统一维护。在这里采用接口类进行常量的定义和初始化。

接口中的常量默认用public static final修饰,符合我们的需求。

public interface CookieConstant {String TOKEN = "token";Integer EXPIRE = 7200;
}

枚举的使用

通过定义枚举类可以帮助我们对项目中一些状态值或是错误码进行统一管理,并且可以通过Getter方法获取枚举值的详细信息。

@Getter
public enum ResultEnum {SUCCESS(0, "成功"),PARAM_ERROR(1, "参数不正确"),PRODUCT_NOT_EXIST(10, "商品不存在"),PRODUCT_STOCK_ERROR(11, "商品库存不正确"),ORDER_NOT_EXIST(12, "订单不存在"),ORDERDETAIL_NOT_EXIST(13, "订单详情不存在"),ORDER_STATUS_ERROR(14, "订单状态不正确"),ORDER_UPDATE_FAIL(15, "订单更新失败"),ORDER_DETAIL_EMPTY(16, "订单详情为空"),ORDER_PAY_STATUS_ERROR(17, "订单支付状态不正确"),CART_EMPTY(18, "购物车为空"),ORDER_OWNER_ERROR(19, "该订单不属于当前用户"),WECHAT_MP_ERROR(20, "微信公众账号方面错误"),WXPAY_NOTIFY_MONEY_VERIFY_ERROR(21, "微信支付异步通知金额校验不通过"),ORDER_CANCEL_SUCCESS(22, "订单取消成功"),ORDER_FINISH_SUCCESS(23, "订单完结成功"),PRODUCT_STATUS_ERROR(24, "商品状态不正确"),LOGIN_FAIL(25, "登录失败, 登录信息不正确"),LOGOUT_SUCCESS(26, "登出成功"),;private Integer code;private String message;ResultEnum(Integer code, String message) {this.code = code;this.message = message;}
}

Aspect切面

AOP是spring框架中的一个重要内容。AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待。

使用@Aspect声明一个切面类。

使用注解完成切点表达式、环绕通知、前置通知、后置通知的声明。

通过切点表达式,实现对访问请求的拦截,并进行切面中逻辑的处理,这里进行的是登录校验

@Aspect
@Component
@Slf4j
public class SellerAuthorizeAspect {@Autowiredprivate StringRedisTemplate redisTemplate;@Pointcut("execution(public * com.imooc.controller.Seller*.*(..))" +"&& !execution(public * com.imooc.controller.SellerUserController.*(..))")public void verify() {}@Before("verify()")public void doVerify() {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();//查询cookieCookie cookie = CookieUtil.get(request, CookieConstant.TOKEN);if (cookie == null) {log.warn("【登录校验】Cookie中查不到token");throw new SellerAuthorizeException();}//去redis里查询String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue()));if (StringUtils.isEmpty(tokenValue)) {log.warn("【登录校验】Redis中查不到token");throw new SellerAuthorizeException();}}
}

实体的定义

@Entity声明该类为实体类,对应数据库的表,反映数据库表和Java实体间的映射关系

@DynamicUpdate 表示update对象的时候,生成动态的update语句。如果字段有更新,Hibernate才会对该字段进行更新,比如下面的updateTime字段。参考 https://blog.csdn.net/itguangit/article/details/78696767

@JsonIgnore  作用是在将ResponseBody中的Javabean返回前端过程中,被springmvc自带的jackson转化成json字符串时,忽略这个属性。对序列化也有影响。

@Entity
@Data
@DynamicUpdate
public class ProductInfo implements Serializable{private static final long serialVersionUID = 6399186181668983148L;@Idprivate String productId;/** 名字. */private String productName;/** 单价. */private BigDecimal productPrice;/** 库存. */private Integer productStock;/** 描述. */private String productDescription;/** 小图. */private String productIcon;/** 状态, 0正常1下架. */private Integer productStatus = ProductStatusEnum.UP.getCode();/** 类目编号. */private Integer categoryType;private Date createTime;private Date updateTime;@JsonIgnorepublic ProductStatusEnum getProductStatusEnum() {return EnumUtil.getByCode(productStatus, ProductStatusEnum.class);}
}

dao层

这里通过继承JpaRepository实现对数据库的curd操作

public interface SellerInfoRepository extends JpaRepository<SellerInfo, String> {SellerInfo findByOpenid(String openid);
}

Service层

Service业务处理层接口定义

public interface SellerService {/*** 通过openid查询卖家端信息* @param openid* @return*/SellerInfo findByOpenid(String openid);
}

Service业务处理层接口实现,注意加入@Service注解

@Service
public class SellerServiceImpl implements SellerService{@Autowiredprivate SellerInfoRepository repository;@Overridepublic SellerInfo findByOpenid(String openid) {return repository.findByOpenid(openid);}
}

Controller层

@RestController注解相当于@ResponseBody + @Controller合在一起的作用。

@RequestMapping("/path") 表示访问的请求映射路径

@Valid 用于对表单的校验,如果校验不通过,BindingResult对象不为空,并可通过bindingResult.getFieldError().getDefaultMessage()方法获取错误信息

@RestController
@RequestMapping("/buyer/order")
@Slf4j
public class BuyerOrderController {@Autowiredprivate OrderService orderService;@Autowiredprivate BuyerService buyerService;//创建订单@PostMapping("/create")public ResultVO<Map<String,String>> create(@Valid OrderForm orderForm,BindingResult bindingResult){if(bindingResult.hasErrors()){log.error("【创建订单】参数不正确,orderForm={}",orderForm);throw new SellException(ResultEnum.PARAM_ERROR.getCode(),bindingResult.getFieldError().getDefaultMessage());}OrderDTO orderDTO = OrderForm2OrderDTOConverter.convert(orderForm);if(CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){log.error("【创建订单】购物车不能为空");throw new SellException(ResultEnum.CART_EMPTY);}OrderDTO createResult = orderService.create(orderDTO);Map<String,String> map = new HashMap<String,String>();map.put("orderId",createResult.getOrderId());return ResultVOUtil.success(map);}
}

表单校验

通过注解完成对表单填写信息的约束,并在不符合约束时将message信息返回

@Data
public class OrderForm {/*** 买家姓名*/@NotEmpty(message = "姓名必填")private String name;/*** 买家手机号*/@NotEmpty(message = "手机号必填")private String phone;/*** 买家地址*/@NotEmpty(message = "地址必填")private String address;/*** 买家微信openid*/@NotEmpty(message = "openId必填")private String openid;/*** 购物车*/@NotEmpty(message = "购物车不能为空")private String items;
}

dto,util,converter的使用后续补充~

基于Spring Boot企业微信点餐系统项目总结相关推荐

  1. Spring Boot企业微信点餐系统

    Spring Boot企业微信点餐系统 网盘地址:https://pan.baidu.com/s/1kcsDXp5C7QiJpTnpdd41Ng 密码: qhxb 备用地址(腾讯微云):https:/ ...

  2. 一个强大的开源的基于Spring Boot开发的Web支付系统项目,支持聚合码支付

    一个强大的开源的基于Spring Boot开发的Web支付系统项目,支持聚合码支付.

  3. Spring Boot 实现微信点餐系统

    来源:www.jianshu.com/p/ae14101989f2_ 架构 前后端分离: 部署架构: 补充: setting.xml 文件的作用:**settings.xml 是 maven 的全局配 ...

  4. 基于Spring Boot的农家乐点餐系统

    随着传统的购物方式正在向网络化发展,出现了"网购,这种越来越受欢迎的新型消费方式.为了提高餐饮业务水平和效率,实现比电话订购更有效的送餐业务,网上订餐系统因运而生.通过对订餐流程和业务进行全 ...

  5. 基于spring boot的婚纱摄影约拍系统

    基于spring boot的婚纱摄影约拍系统主要实现以下几种功能 后台 1.摄影师管理: ① 新增摄影师,填写摄影师个人信息和上传照片 ② 修改摄影师信息 ③ 摄影师作品管理,上传摄影师拍摄作品 ④ ...

  6. springboot 打卡功能_基于spring boot框架的公司考勤系统的研究与设计

    基于 spring boot 框架的公司考勤系统的研究与设计 李宏坤 ; 郑光勇 ; 谢舞 ; 彭承辉 [期刊名称] <电脑知识与技术> [年 ( 卷 ), 期] 2019(015)018 ...

  7. 基于Spring Boot技术栈博客系统企业级前后端实战之课程导论(零)

    零.说明(必读) 一.课程概述 1.1 名称 1.2 功能 1.3 技术点 1.4 目标 二.核心功能 2.1 用户管理 2.2 安全设置 2.3 博客管理 2.4 评论管理 2.5 点赞管理 2.6 ...

  8. 自荐Mall4j项目一个基于spring boot的Java开源商城系统

    前言 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样 ...

  9. 基于Spring Boot的个人博客系统(源码+数据库)

    目录 一.系统功能框架图 二.开发技术 三.开发环境 四.页面展示 1.登录页面 2.首页 3.文章详情页面 4.文章评论页面 ​5.后台页面 6.后台文件编辑页面 ​7.后台文章管理列表页面 五.文 ...

  10. springboot 微信太阳码_WxJava基于Spring Boot开发微信公众号手机注册码

    WxJava基于Spring Boot开发微信公众号手机注册码 Szx • 2019 年 05 月 18 日 第一步先下载官方Demo https://github.com/binarywang/we ...

最新文章

  1. Facebook曝至今最严重安全漏洞,超过5000万用户受影响
  2. Xamarin XAML语言教程将XAML设计的UI显示到界面
  3. python语言视频-Python语言之Python3 实现简易局域网视频聊天工具
  4. 成功解决ValueError: Shape of passed values is (33, 1), indices imply (33, 2)
  5. Android 切换系统语言源码分析
  6. 知识总结: Activity的四种启动模式
  7. your port 80 is actually used by server IIS解决办法
  8. java第三方包学习之jsoup
  9. 系统搜索资源就停止服务器,SQL Server (MSSQLSERVER) 服务启动不了,系统日志显示由于下列服务特定错误而终止: 找不到映像文件中指定的资源名。...
  10. 设计模式PHP篇(三)————适配器模式
  11. TCP Timestamp选项
  12. c语言网吧计费管理小项目,c语言网吧计费系统小项目.doc
  13. java 获取本机ip地址吗_java 获取本机ip地址
  14. SRE稳定性指标:MTBF、MTTR
  15. 电子凸轮基本概念学习
  16. Python制作黑客工具,发现了同学U盘里见不得人的秘密
  17. php验证是否为整数(0、正整数、负整数)
  18. facenet 人脸识别原理理解(三)
  19. grad-cam一直无法画比较合适的图的原因
  20. [Camera]摄像头模组硬件

热门文章

  1. Android Ibeacon 算法,iBeacon定位算法
  2. elementUI表格合并行
  3. python dataframe重新索引_Concat DataFrame重新索引仅对唯一值索引对象有效
  4. 遥感小目标检测论文梳理
  5. 解决底部横杠遮挡问题(兼容苹果手机底部)
  6. Learning to Reweight Examples for Robust Deep Learning
  7. 微信小程序解决 加载图片出现渲染层网络层错误
  8. PS如何快速简单的给人像美白
  9. php获取数组元素keys,关于array_keys函数的详细介绍 - key
  10. @PreAuthorize、@Secured、 @RolesAllowed优先级