1. day01 项目搭建

2. 前后端分离

01. day01 项目搭建 - 图1

3. 技术架构

01. day01 项目搭建 - 图2

4. 系统架构

01. day01 项目搭建 - 图3

5. 项目分层

01. day01 项目搭建 - 图4

changgou_gateway

  1. 网关模块,根据网站的规模和需要,可以将综合逻辑相关的服务用网关路由组合到一起。在这里还可以做鉴权和限流相关操作。

changgou_service

  1. 微服务模块,该模块用于存放所有独立的微服务工程。

changgou_service_api

  1. 对应工程的JavaBeanFeign、以及Hystrix配置,该工程主要对外提供依赖。

changgou_transaction_fescar

  1. 分布式事务模块,将分布式事务抽取到该工程中,任何工程如需要使用分布式事务,只需依赖该工程即可。

changgou_web

  1. web服务工程,对应功能模块如需要调用多个微服务,可以将他们写入到该模块中,例如网站后台、网站前台等

6. 项目搭建

6.1. 一级父工程搭建

创建父工程 changgou_parent 修改pom文件 并删除src目录

此项目工程为父工程 无需编写编码

  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>2.1.4.RELEASE</version>
  5. </parent>
  6. <properties>
  7. <skipTests>true</skipTests>
  8. </properties>
  9. <!--依赖包-->
  10. <dependencies>
  11. <!--测试包-->
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-test</artifactId>
  15. <scope>test</scope>
  16. </dependency>
  17. </dependencies>
  18. <dependencyManagement>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.cloud</groupId>
  22. <artifactId>spring-cloud-dependencies</artifactId>
  23. <version>Greenwich.SR1</version>
  24. <type>pom</type>
  25. <scope>import</scope>
  26. </dependency>
  27. </dependencies>
  28. </dependencyManagement>

6.2. 创建二级父工程项目

依次创建各个二级父工程 并删除项目中的src目录

  • changgou_gateway
  • changgou_service
  • changgou_service_api
  • changgou_transaction_fescar
  • changgou_web

6.3. Eureka微服务搭建

创建二级父工程 changgou_eureka 并编辑pom

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
  5. </dependency>
  6. </dependencies>
  • 创建启动类并注解开启eurekasever
  1. package com.changgou.eureka;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
  5. @SpringBootApplication
  6. @EnableEurekaServer //声明为eureka注册中心 服务端
  7. public class EurekaApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(EurekaApplication.class, args);
  10. }
  11. }
  • application 配置文件
  1. server:
  2. port: 6868
  3. eureka:
  4. client:
  5. register-with-eureka: false #是否将自己注册到eureka中
  6. fetch-registry: false #是否从eureka中获取信息
  7. service-url:
  8. defaultZone: http://127.0.0.1:${server.port}/eureka/

测试启动 运行启动类

访问http://localhost:6868/

6.4. 全局公共模块

创建子模块changgou_common pom引入模块

  1. <dependencies>
  2. <!--web起步依赖-->
  3. <dependency>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-starter-web</artifactId>
  6. </dependency>
  7. <!-- redis 使用-->
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-data-redis</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>com.alibaba</groupId>
  14. <artifactId>fastjson</artifactId>
  15. <version>1.2.51</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.springframework.cloud</groupId>
  23. <artifactId>spring-cloud-starter-openfeign</artifactId>
  24. </dependency>
  25. </dependencies>

创建常用对象 分页pojo 页面返回对象 返回结果对象 状态码

在com.changgou.common.pojo下创建

page

  1. package com.changgou.common.pojo;
  2. import java.io.Serializable;
  3. import java.util.List;
  4. /**
  5. * 分页对象
  6. * @param <T>
  7. */
  8. public class Page <T> implements Serializable{
  9. //当前默认为第一页
  10. public static final Integer pageNum = 1;
  11. //默认每页显示条件
  12. public static final Integer pageSize = 20;
  13. //判断当前页是否为空或是小于1
  14. public static Integer cpn(Integer pageNum){
  15. if(null == pageNum || pageNum < 1){
  16. pageNum = 1;
  17. }
  18. return pageNum;
  19. }
  20. // 页数(第几页)
  21. private long currentpage;
  22. // 查询数据库里面对应的数据有多少条
  23. private long total;// 从数据库查处的总记录数
  24. // 每页查5条
  25. private int size;
  26. // 下页
  27. private int next;
  28. private List<T> list;
  29. // 最后一页
  30. private int last;
  31. private int lpage;
  32. private int rpage;
  33. //从哪条开始查
  34. private long start;
  35. //全局偏移量
  36. public int offsize = 2;
  37. public Page() {
  38. super();
  39. }
  40. /****
  41. *
  42. * @param currentpage
  43. * @param total
  44. * @param pagesize
  45. */
  46. public void setCurrentpage(long currentpage,long total,long pagesize) {
  47. //可以整除的情况下
  48. long pagecount = total/pagesize;
  49. //如果整除表示正好分N页,如果不能整除在N页的基础上+1页
  50. int totalPages = (int) (total%pagesize==0? total/pagesize : (total/pagesize)+1);
  51. //总页数
  52. this.last = totalPages;
  53. //判断当前页是否越界,如果越界,我们就查最后一页
  54. if(currentpage>totalPages){
  55. this.currentpage = totalPages;
  56. }else{
  57. this.currentpage=currentpage;
  58. }
  59. //计算start
  60. this.start = (this.currentpage-1)*pagesize;
  61. }
  62. //上一页
  63. public long getUpper() {
  64. return currentpage>1? currentpage-1: currentpage;
  65. }
  66. //总共有多少页,即末页
  67. public void setLast(int last) {
  68. this.last = (int) (total%size==0? total/size : (total/size)+1);
  69. }
  70. /****
  71. * 带有偏移量设置的分页
  72. * @param total
  73. * @param currentpage
  74. * @param pagesize
  75. * @param offsize
  76. */
  77. public Page(long total,int currentpage,int pagesize,int offsize) {
  78. this.offsize = offsize;
  79. initPage(total, currentpage, pagesize);
  80. }
  81. /****
  82. *
  83. * @param total 总记录数
  84. * @param currentpage 当前页
  85. * @param pagesize 每页显示多少条
  86. */
  87. public Page(long total,int currentpage,int pagesize) {
  88. initPage(total,currentpage,pagesize);
  89. }
  90. /****
  91. * 初始化分页
  92. * @param total
  93. * @param currentpage
  94. * @param pagesize
  95. */
  96. public void initPage(long total,int currentpage,int pagesize){
  97. //总记录数
  98. this.total = total;
  99. //每页显示多少条
  100. this.size=pagesize;
  101. //计算当前页和数据库查询起始值以及总页数
  102. setCurrentpage(currentpage, total, pagesize);
  103. //分页计算
  104. int leftcount =this.offsize, //需要向上一页执行多少次
  105. rightcount =this.offsize;
  106. //起点页
  107. this.lpage =currentpage;
  108. //结束页
  109. this.rpage =currentpage;
  110. //2点判断
  111. this.lpage = currentpage-leftcount; //正常情况下的起点
  112. this.rpage = currentpage+rightcount; //正常情况下的终点
  113. //页差=总页数和结束页的差
  114. int topdiv = this.last-rpage; //判断是否大于最大页数
  115. /***
  116. * 起点页
  117. * 1、页差<0 起点页=起点页+页差值
  118. * 2、页差>=0 起点和终点判断
  119. */
  120. this.lpage=topdiv<0? this.lpage+topdiv:this.lpage;
  121. /***
  122. * 结束页
  123. * 1、起点页<=0 结束页=|起点页|+1
  124. * 2、起点页>0 结束页
  125. */
  126. this.rpage=this.lpage<=0? this.rpage+(this.lpage*-1)+1: this.rpage;
  127. /***
  128. * 当起点页<=0 让起点页为第一页
  129. * 否则不管
  130. */
  131. this.lpage=this.lpage<=0? 1:this.lpage;
  132. /***
  133. * 如果结束页>总页数 结束页=总页数
  134. * 否则不管
  135. */
  136. this.rpage=this.rpage>last? this.last:this.rpage;
  137. }
  138. public long getNext() {
  139. return currentpage<last? currentpage+1: last;
  140. }
  141. public void setNext(int next) {
  142. this.next = next;
  143. }
  144. public long getCurrentpage() {
  145. return currentpage;
  146. }
  147. public long getTotal() {
  148. return total;
  149. }
  150. public void setTotal(long total) {
  151. this.total = total;
  152. }
  153. public long getSize() {
  154. return size;
  155. }
  156. public void setSize(int size) {
  157. this.size = size;
  158. }
  159. public long getLast() {
  160. return last;
  161. }
  162. public long getLpage() {
  163. return lpage;
  164. }
  165. public void setLpage(int lpage) {
  166. this.lpage = lpage;
  167. }
  168. public long getRpage() {
  169. return rpage;
  170. }
  171. public void setRpage(int rpage) {
  172. this.rpage = rpage;
  173. }
  174. public long getStart() {
  175. return start;
  176. }
  177. public void setStart(long start) {
  178. this.start = start;
  179. }
  180. public void setCurrentpage(long currentpage) {
  181. this.currentpage = currentpage;
  182. }
  183. /**
  184. * @return the list
  185. */
  186. public List<T> getList() {
  187. return list;
  188. }
  189. /**
  190. * @param list the list to set
  191. */
  192. public void setList(List<T> list) {
  193. this.list = list;
  194. }
  195. public static void main(String[] args) {
  196. //总记录数
  197. //当前页
  198. //每页显示多少条
  199. int cpage =17;
  200. Page page = new Page(1001,cpage,50,7);
  201. System.out.println("开始页:"+page.getLpage()+"__当前页:"+page.getCurrentpage()+"__结束页"+page.getRpage()+"____总页数:"+page.getLast());
  202. }
  203. }

PageResult

  1. package com.changgou.common.pojo;
  2. import java.util.List;
  3. public class PageResult<T> {
  4. private Long total;//总记录数
  5. private List<T> rows;//记录
  6. public PageResult(Long total, List<T> rows) {
  7. this.total = total;
  8. this.rows = rows;
  9. }
  10. public PageResult() {
  11. }
  12. public Long getTotal() {
  13. return total;
  14. }
  15. public void setTotal(Long total) {
  16. this.total = total;
  17. }
  18. public List<T> getRows() {
  19. return rows;
  20. }
  21. public void setRows(List<T> rows) {
  22. this.rows = rows;
  23. }
  24. }

Result

  1. package com.changgou.common.pojo;
  2. /**
  3. * 返回结果实体类
  4. */
  5. public class Result<T> {
  6. private boolean flag;//是否成功
  7. private Integer code;//返回码
  8. private String message;//返回消息
  9. private T data;//返回数据
  10. public Result(boolean flag, Integer code, String message, Object data) {
  11. this.flag = flag;
  12. this.code = code;
  13. this.message = message;
  14. this.data = (T)data;
  15. }
  16. public Result(boolean flag, Integer code, String message) {
  17. this.flag = flag;
  18. this.code = code;
  19. this.message = message;
  20. }
  21. public Result() {
  22. this.flag = true;
  23. this.code = StatusCode.OK;
  24. this.message = "执行成功";
  25. }
  26. public boolean isFlag() {
  27. return flag;
  28. }
  29. public void setFlag(boolean flag) {
  30. this.flag = flag;
  31. }
  32. public Integer getCode() {
  33. return code;
  34. }
  35. public void setCode(Integer code) {
  36. this.code = code;
  37. }
  38. public String getMessage() {
  39. return message;
  40. }
  41. public void setMessage(String message) {
  42. this.message = message;
  43. }
  44. public T getData() {
  45. return data;
  46. }
  47. public void setData(T data) {
  48. this.data = data;
  49. }
  50. }

StatusCode

  1. package com.changgou.common.pojo;
  2. /**
  3. * 返回码
  4. */
  5. public class StatusCode {
  6. public static final int OK=20000;//成功
  7. public static final int ERROR =20001;//失败
  8. public static final int LOGINERROR =20002;//用户名或密码错误
  9. public static final int ACCESSERROR =20003;//权限不足
  10. public static final int REMOTEERROR =20004;//远程调用失败
  11. public static final int REPERROR =20005;//重复操作
  12. }

6.5. 数据访问公共模块搭建

这个公共模块是连接mysql数据库的公共微服务模块,所以需要连接mysql的微服务都继承自此工程。

创建公共模块changgou_common_db,pom文件引入依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>com.changgou</groupId>
  4. <artifactId>changgou_common</artifactId>
  5. <version>1.0-SNAPSHOT</version>
  6. </dependency>
  7. <!--通用mapper起步依赖-->
  8. <dependency>
  9. <groupId>tk.mybatis</groupId>
  10. <artifactId>mapper-spring-boot-starter</artifactId>
  11. <version>2.0.4</version>
  12. </dependency>
  13. <!--MySQL数据库驱动-->
  14. <dependency>
  15. <groupId>mysql</groupId>
  16. <artifactId>mysql-connector-java</artifactId>
  17. </dependency>
  18. <!--mybatis分页插件-->
  19. <dependency>
  20. <groupId>com.github.pagehelper</groupId>
  21. <artifactId>pagehelper-spring-boot-starter</artifactId>
  22. <version>1.2.3</version>
  23. </dependency>
  24. </dependencies>

6.6. 商品微服务API工程搭建

创建 changgou_service_api 模块

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-openfeign</artifactId>
  5. <scope>provided</scope>
  6. </dependency>
  7. <dependency>
  8. <groupId>javax.persistence</groupId>
  9. <artifactId>persistence-api</artifactId>
  10. <version>1.0</version>
  11. <scope>compile</scope>
  12. </dependency>
  13. </dependencies>

6.6.1. 在api工程下创建goods_api子模块

changgou_service_api 下创建changgou_service_goods_api子模块并添加common依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>com.changgou</groupId>
  4. <artifactId>changgou_common</artifactId>
  5. <version>1.0-SNAPSHOT</version>
  6. </dependency>
  7. </dependencies>

6.7. 微服务工程搭建

changgou_service下创建changgou_service_goods子模块

  1. <dependencies>
  2. <dependency>
  3. <groupId>com.changgou</groupId>
  4. <artifactId>changgou_common_db</artifactId>
  5. <version>1.0-SNAPSHOT</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.changgou</groupId>
  9. <artifactId>changgou_service_goods_api</artifactId>
  10. <version>1.0-SNAPSHOT</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.cloud</groupId>
  14. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  15. </dependency>
  16. </dependencies>

application.yml

  1. server:
  2. port: 9011
  3. spring:
  4. application:
  5. name: goods
  6. datasource:
  7. driver-class-name: com.mysql.cj.jdbc.Driver
  8. url: jdbc:mysql://192.168.130.128:3306/changgou_goods?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
  9. username: root
  10. password: root
  11. eureka:
  12. client:
  13. service-url:
  14. defaultZone: http://127.0.0.1:6868/eureka
  15. instance:
  16. prefer-ip-address: true
  17. feign:
  18. hystrix:
  19. enabled: true
  20. #hystrix 配置
  21. hystrix:
  22. command:
  23. default:
  24. execution:
  25. timeout:
  26. #如果enabled设置为false,则请求超时交给ribbon控制
  27. enabled: true
  28. isolation:
  29. strategy: SEMAPHORE

创建启动类 并声明为eureka客户端 并开启mapper扫描

  1. package com.changgou.service.goods;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  5. import tk.mybatis.spring.annotation.MapperScan;
  6. @SpringBootApplication
  7. @EnableEurekaClient //声明为eureka客户端
  8. @MapperScan(basePackages = {"com.changgou.service.goods.dao"}) //扫描指定路径下的dao层接口
  9. public class GoodsApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(GoodsApplication.class, args);
  12. }
  13. }

7. 增删改查

  • 在changou_service_api中的changou_service_goods_api 用于放置 pojo

创建品牌的映射类

  1. package com.changgou.goods.pojo;
  2. import javax.persistence.Id;
  3. import javax.persistence.Table;
  4. import java.io.Serializable;
  5. @Table(name = "tb_brand")
  6. public class Brand implements Serializable {
  7. @Id
  8. private Integer id;//品牌id
  9. private String name;//品牌名称
  10. private String image;//品牌图片地址
  11. private String letter;//品牌的首字母
  12. private Integer seq;//排序
  13. public Integer getId() {
  14. return id;
  15. }
  16. public void setId(Integer id) {
  17. this.id = id;
  18. }
  19. public String getName() {
  20. return name;
  21. }
  22. public void setName(String name) {
  23. this.name = name;
  24. }
  25. public String getImage() {
  26. return image;
  27. }
  28. public void setImage(String image) {
  29. this.image = image;
  30. }
  31. public String getLetter() {
  32. return letter;
  33. }
  34. public void setLetter(String letter) {
  35. this.letter = letter;
  36. }
  37. public Integer getSeq() {
  38. return seq;
  39. }
  40. public void setSeq(Integer seq) {
  41. this.seq = seq;
  42. }
  43. }
  • 在changogu_service中的changogu_service_goods 创建 dao层并继承Mapper序列化 泛型为映射类
  1. package com.changgou.service.goods.dao;
  2. import com.changgou.goods.pojo.Brand;
  3. import tk.mybatis.mapper.common.Mapper;
  4. public interface BrandMapper extends Mapper<Brand> {
  5. }
  • 创建service 层 接口 调用dao层
  1. package com.changgou.service.goods.service;
  2. import com.changgou.goods.pojo.Brand;
  3. import com.github.pagehelper.Page;
  4. import java.util.List;
  5. import java.util.Map;
  6. public interface BrandService {
  7. //品牌列表查询
  8. List<Brand> findList();
  9. //根据id查询
  10. Brand findById(Integer id);
  11. //品牌新增
  12. void add(Brand brand);
  13. //品牌修改
  14. void update(Brand brand);
  15. //品牌删除
  16. void delById(Integer id);
  17. //品牌列表条件查询
  18. List<Brand> list(Map<String,Object> searchMap);
  19. //品牌列表分页查询
  20. Page<Brand> findPage(int page,int size);
  21. //品牌列表分页+条件查询
  22. Page<Brand> findPage(Map<String,Object> searchMap,int page,int size);
  23. }
  • 创建service 层的实现类 impl
  1. package com.changgou.service.goods.service.impl;
  2. import com.changgou.goods.pojo.Brand;
  3. import com.changgou.service.goods.dao.BrandMapper;
  4. import com.changgou.service.goods.service.BrandService;
  5. import com.github.pagehelper.Page;
  6. import com.github.pagehelper.PageHelper;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.stereotype.Service;
  9. import org.springframework.transaction.annotation.Transactional;
  10. import tk.mybatis.mapper.entity.Example;
  11. import java.util.List;
  12. import java.util.Map;
  13. @Service
  14. public class BrandServiceImpl implements BrandService {
  15. @Autowired
  16. private BrandMapper brandMapper;
  17. //品牌列表查询
  18. @Override
  19. public List<Brand> findList() {
  20. List<Brand> brandList = brandMapper.selectAll();
  21. return brandList;
  22. }
  23. //根据id查询
  24. @Override
  25. public Brand findById(Integer id) {
  26. Brand brand = brandMapper.selectByPrimaryKey(id);
  27. return brand;
  28. }
  29. //添加品牌
  30. @Override
  31. public void add(Brand brand) {
  32. brandMapper.insert(brand);
  33. }
  34. //更新品牌
  35. @Override
  36. public void update(Brand brand) {
  37. brandMapper.updateByPrimaryKey(brand);
  38. }
  39. //根据ids删除
  40. @Override
  41. @Transactional
  42. public void delById(Integer id) {
  43. brandMapper.deleteByPrimaryKey(id);
  44. }
  45. //品牌列表条件查询
  46. @Override
  47. public List<Brand> list(Map<String, Object> searchMap) {
  48. Example example = new Example(Brand.class);
  49. //封装查询条件
  50. Example.Criteria criteria = example.createCriteria();
  51. if (searchMap != null) {
  52. //品牌名称 like模糊查询
  53. if (searchMap.get("name") != null && !"".equals(searchMap.get("name"))) {
  54. //andLike like品牌 property属性名 value为查询条件
  55. criteria.andLike("name", "%" + searchMap.get("name") + "%");
  56. }
  57. //按品牌首字母进行查询 精确查询
  58. if (searchMap.get("letter") != null && !"".equals(searchMap.get("letter"))) {
  59. criteria.andEqualTo("letter", searchMap.get("letter"));
  60. }
  61. }
  62. List<Brand> brandList = brandMapper.selectByExample(example);
  63. return brandList;
  64. }
  65. @Override
  66. public Page<Brand> findPage(int page, int size) {
  67. PageHelper.startPage(page, size);
  68. Page<Brand> page1 = (Page<Brand>) brandMapper.selectAll();
  69. return page1;
  70. }
  71. @Override
  72. public Page<Brand> findPage(Map<String, Object> searchMap, int page, int size) {
  73. //分页
  74. PageHelper.startPage(page, size);
  75. //设置查询条件
  76. Example example = new Example(Brand.class);
  77. Example.Criteria criteria = example.createCriteria();
  78. if (searchMap != null) {
  79. //设置品牌模糊查询
  80. if (searchMap.get("name") != null && !"".equals(searchMap.get("name"))) {
  81. //模糊查询
  82. criteria.andLike("name", "%" + searchMap.get("name") + "%");
  83. }
  84. //设置品牌首字母的精确查询
  85. if (searchMap.get("letter") != null && !"".equals(searchMap.get("letter"))) {
  86. criteria.andEqualTo("letter", searchMap.get("letter"));
  87. }
  88. }
  89. Page<Brand> pageInfo = (Page<Brand>) brandMapper.selectByExample(example);
  90. return pageInfo;
  91. }
  92. }
  • controller层
  1. package com.changgou.service.goods.controller;
  2. import com.changgou.common.pojo.PageResult;
  3. import com.changgou.common.pojo.Result;
  4. import com.changgou.common.pojo.StatusCode;
  5. import com.changgou.goods.pojo.Brand;
  6. import com.changgou.service.goods.service.BrandService;
  7. import com.github.pagehelper.Page;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.web.bind.annotation.*;
  10. import java.util.List;
  11. import java.util.Map;
  12. @RequestMapping("/brand")
  13. @RestController
  14. public class BrandController {
  15. @Autowired
  16. private BrandService brandService;
  17. @GetMapping
  18. public Result<List<Brand>> findList() {
  19. List<Brand> brandList = brandService.findList();
  20. return new Result<>(true, StatusCode.OK, "查询成功", brandList);
  21. }
  22. @GetMapping("/{id}")
  23. public Result<Brand> findById(@PathVariable("id") Integer id) {
  24. Brand brand = brandService.findById(id);
  25. return new Result<>(true, StatusCode.OK, "查询成功", brand);
  26. }
  27. @PostMapping
  28. private Result add(@RequestBody Brand brand) {
  29. brandService.add(brand);
  30. return new Result(true, StatusCode.OK, "添加成功");
  31. }
  32. @PutMapping("/{id}")
  33. public Result update(@PathVariable("id") Integer id, @RequestBody Brand brand) {
  34. brand.setId(id);
  35. brandService.update(brand);
  36. return new Result(true, StatusCode.OK, "更新成功");
  37. }
  38. @DeleteMapping("/{id}")
  39. public Result delById(@PathVariable("id") Integer id) {
  40. brandService.delById(id);
  41. return new Result(true, StatusCode.OK, "删除成功");
  42. }
  43. @GetMapping("/search")
  44. public Result<List<Brand>> search(@RequestParam Map searchMap) {
  45. List<Brand> list = brandService.list(searchMap);
  46. return new Result<>(true, StatusCode.OK, "查询成功", list);
  47. }
  48. @GetMapping("/search/{page}/{size}")
  49. public Result findPage(
  50. @PathVariable("page") int page,
  51. @PathVariable("size") int size
  52. ) {
  53. Page<Brand> pageInfo = brandService.findPage(page, size);
  54. PageResult pageResult = new PageResult(pageInfo.getTotal(), pageInfo.getResult());
  55. return new Result(true, StatusCode.OK, "查询成功", pageResult);
  56. }
  57. @GetMapping("/searchPage/{page}/{size}")
  58. public Result findPage(@RequestParam Map searchMap, @PathVariable("page") int page,
  59. @PathVariable("size") int size) {
  60. Page pageInfo = brandService.findPage(searchMap, page, size);
  61. PageResult pageResult = new PageResult(pageInfo.getTotal(), pageInfo.getResult());
  62. return new Result(true, StatusCode.OK, "查询成功", pageResult);
  63. }
  64. }

8. 公共异常处理

上面的接口我们都是直接返回结果给前端 如果后端出现异常会直接返回java中异常错误结果

为了使我们代码更加容易维护 我们创建一个公共异常处理类 来进行处理

通过@ControllerAdvice 声明类为增强类

通过@ExceptionHandler(value = Exception.class) 捕抓指定的异常

  1. package com.changgou.service.goods.handler;
  2. import com.changgou.common.pojo.Result;
  3. import com.changgou.common.pojo.StatusCode;
  4. import org.springframework.web.bind.annotation.ControllerAdvice;
  5. import org.springframework.web.bind.annotation.ExceptionHandler;
  6. import org.springframework.web.bind.annotation.ResponseBody;
  7. //统一异常处理类
  8. @ControllerAdvice //声明该类是一个增强类
  9. public class BaseExceptionHandler {
  10. @ExceptionHandler(value = Exception.class) //声明为异常处理的handler
  11. @ResponseBody
  12. public Result error(Exception e) {
  13. e.printStackTrace();
  14. return new Result(false, StatusCode.ERROR, "当前系统繁忙,请您稍后重试");
  15. }
  16. }

9. 跨域解决

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

如果跨域调用,会出现如下错误:

No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:9100‘ is therefore not allowed access. The response had HTTP status code 400.

由于我们采用的是前后端分离的编程方式,前端和后端必定存在跨域问题。解决跨域问题可以采用CORS

9.1. CORS

CORS 是一个 W3C 标准,全称是”跨域资源共享”(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制。整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。

01. day01 项目搭建 - 图5

01. day01 项目搭建 - 图6

springMVC的版本在4.2或以上版本,可以使用注解实现跨域。 我们只需要在Controller类上添加注解@CrossOrigin 就可以了。

  1. @RequestMapping("/brand")
  2. @RestController
  3. @CrossOrigin //开启跨域请求操作
  4. public class BrandController {
  5. }