BladeX初探


一、BladeX是什么?

BladeX 是由一个商业级项目升级优化而来的SpringCloud微服务架构,采用Java8 API重构了业务代码,完全遵循阿里巴巴编码规范。采用Spring Boot 2 、Spring Cloud Honxton 、Mybatis 等核心技术,同时提供基于React和Vue的两个前端框架用于快速搭建企业级的SaaS微服务系统平台。

二、API鉴权使用

鉴权,获得Token,接口请求时,请求头需携带Token进行认证;不管是客户端(PC或移动端)的请求,还是服务内部调用,请求都会经过Zuul网关,然后再由网关来实现鉴权等操作

1.下载配置文件并解压

具体调用方式请看:https://sns.bladex.vip/article-14982.html

2.打开后点击左上角的Import

导入json配置文件到postman

3.设置环境变量,修改请求数据,添加脚本代码

设置test、dev、pro的环境变量
修改账号、密码,在Tests里使用脚本将token赋值给环境变量

//获取返回值
var response =JSON.parse(responseBody);
//判断返回值是否有access_token参数
if (response.access_token) {
  //如果有则此次验证通过
  tests["first has access_token"] = true;
  //获取需要的参数
  var token = response.access_token;
  //打印获取的参数
  console.log("response.access_token-->" + token); 
  //将值写入当前选中的环境中 变成环境变量 
  pm.environment.set("token", "bearer "+token);
}
else {
  //如果无则此次验证不通过
  tests["first has access_token"] = false;
}

三、Redis缓存

提示:使用 Redis可视化工具Redis Desktop Manager来实时查看redis的使用情况

1.读取缓存

调用接口并查看控制台,发现打印本条信息没有从缓存获取

	@GetMapping("/infod")
	@Cacheable(cacheNames = "test-infod", key = "#name")
	public R<String> infod(String name) {
		log.info("本条信息没有从缓存获取");
		return R.data("Hello: " + name);
	}

查看Redis Desktop Manager,发现多了一个键值,正是我们设置的
再次调用接口,发现控制台再无日志输出,说明第二次以后的请求,缓存都从Redis取了

2.移除缓存

调用接口,并查看返回结果为删除缓存成功

	@GetMapping("remove-info")
	@CacheEvict(cacheNames = "demo-info", key = "#name")
	public R<String> removeInfo(String name) {
		return R.success("删除缓存成功");
	}

查看Redis Desktop Manager,发现缓存被移除
再次调用infod接口,发现又如一开始,控制台打印了日志,并且Redis增加了键值

四、mybatis-plus配置

BlogMapper继承BaseMapper类,继承BaseMapper接口,它帮我们做了CRUD操作,我们不用在自己写sql语句了

package org.springbalde.demo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.demo.entity.Blog;

public interface BlogMapper extends BaseMapper<Blog> {

}

BlogService继承IService类

package org.springbalde.demo.service;


import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.demo.entity.Blog;

public interface BlogService extends IService<Blog> {

}

BlogServiceImpl继承ServiceImpl类,实现BlogService类

package org.springbalde.demo.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springbalde.demo.mapper.BlogMapper;
import org.springbalde.demo.service.BlogService;
import org.springblade.demo.entity.Blog;
import org.springframework.stereotype.Service;

@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements BlogService{

}

在application.yml文件中,进行mybatis-plus配置,mybatis-plus扫描bean-alias的配置

#mybatis-plus配置
mybatis-plus:
  mapper-locations: classpath:com/springbalde/**/mapper/*Mapper.xml
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.springbalde.**.entity

新建一个MybatisPlusConfiguration类,使用@MapperScan注解,配置包扫描的路径

package org.springblade.test.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springblade.test.props.TestProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableFeignClients({"org.springblade", "org.springblade"})
@MapperScan({"org.springblade.**.mapper.**", "org.springblade.**.mapper.**"})
@EnableConfigurationProperties(TestProperties.class)
public class MybatisPlusConfiguration {
	
}

五、结合mybatis-plus实现CRUD

1.新增

新增API

	/**
	 * 新增
	 */
	@PostMapping("/save")
	public R save(@RequestBody Blog blog) {
		return R.status(service.save(blog));
	}

2.修改

通过id修改

	/**
	 * 通过id修改
	 */
	@PostMapping("/update")
	public R update(@RequestBody Blog blog) {
		return R.status(service.updateById(blog));
	}

3.删除

通过id逻辑删除,需在实体类上加上@TableLogic注解

	@PostMapping("/remove")
	public R remove(@RequestParam String id) {
		return R.status(service.removeByIds(Func.toLongList(id)));
	}
	/**
	 * 是否已删除
	 */
	@TableField("isDeleted")
	@TableLogic(value = "0", delval = "1")
	private Integer isDeleted;

4.查询

通过id查询详情

	/**
	 * 通过id查询详情
	 */
	@GetMapping("/detail")
	public R<Blog> detail(String id) {
		Blog detail = service.getById(id);
		return R.data(detail);
	}

查询多条

	/**
	 * 查询多条
	 */
	@GetMapping("/list")
	public R<List<Blog>> list() {
		List<Blog> list = service.list();
		return R.data(list);
	}

使用条件构造器Wrappers查询多条

	/**
	 * 查询多条
	 */
	@GetMapping("/list2")
	public R<List<Blog>> list2(Blog blog) {
		List<Blog> list = service.list(Wrappers.query(blog));
		return R.data(list);
	}

查询多条

	/**
	 * 查询多条
	 */
	@GetMapping("/list4")
	public R<List<Blog>> list4(@RequestParam Map<String, Object> blog) {
		List<Blog> list = service.list(Condition.getQueryWrapper(blog, Blog.class).lambda().orderByDesc(Blog::getBlogDate));
		return R.data(list);
	}

分页

	/**
	 * 分页
	 */
	@GetMapping("/page")
	public R<IPage<Blog>> page(@ApiIgnore @RequestParam Map<String, Object> blog, Query query) {
		IPage<Blog> pages = service.page(Condition.getPage(query), Condition.getQueryWrapper(blog, Blog.class));
		return R.data(pages);
	}

六、微服务远程调用

1.声明式服务调用 Feign

在package,feign下创建一个接口类,命名为BlogClient

package org.springblade.demo.feign;

import org.springblade.common.constant.CommonConstant;
import org.springblade.core.tool.api.R;
import org.springblade.demo.entity.Blog;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(
   //定义Feign指向的service-id
   value = CommonConstant.APPLICATION_DEMO_NAME 
)
public interface BlogClient{

   /**
    * 接口前缀
    */
   String API_PREFIX = "/api/blog";

   /**
    * 获取详情
    *
    * @param id 主键
    * @return
    */
   @GetMapping(API_PREFIX + "/detail")
   R<Blog> detail(@RequestParam("id") Integer id);

}

增加feign的实现类BlogClientImpl

package org.springblade.demo.feign;

import lombok.AllArgsConstructor;
import org.springblade.core.tool.api.R;
import org.springblade.demo.entity.Blog;
import org.springblade.demo.service.BlogService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@AllArgsConstructor
public class BlogClientImpl implements BlogClient {

   private BlogService service;

   @Override
   @GetMapping(API_PREFIX + "/detail")
   public R<Blog> detail(Integer id) {
      return R.data(service.getById(id));
   }

}

在另一个服务Controller类中添加方法接口,进行服务调用

private BlogClient client;

@GetMapping("/blog-detail")
public R<Blog> blogDetail(Integer id) {
   R<Blog> result = client.detail(id);
   return result;
}

2.熔断机制 Hystrix

2.1Hystrix简单使用

新建Hystrix类,命名为BlogClientFallback,实现BlogClient接口

package org.springblade.demo.feign;

import org.springblade.core.tool.api.R;
import org.springblade.demo.entity.Blog;

import java.time.LocalDateTime;

public class BlogClientFallback implements BlogClient {

   @Override
   public R<Blog> detail(Integer id) {
      Blog blog = new Blog();
      blog.setBlogTitle("Hystrix");
      blog.setBlogContent("FallBack Success");
      blog.setBlogDate(LocalDateTime.now());
      blog.setIsDeleted(0);
      return R.data(blog);
   }

}

修改BlogClient,增加Hystrix配置

@FeignClient(
   //定义Feign指向的service-id
   value = CommonConstant.APPLICATION_DEMO_NAME,
   //定义hystrix配置类
   fallback = BlogClientFallback.class
)
public interface BlogClient {

   /**
    * 接口前缀
    */
   String API_PREFIX = "/api/blog";

   /**
    * 获取详情
    *
    * @param id 主键
    * @return
    */
   @GetMapping(API_PREFIX + "/detail")
   R<Blog> detail(@RequestParam("id") Integer id);

}

在BlogClientFallback类上加@Component注解

@Component
public class BlogClientFallbackConfiguration {

	@Bean(name = {"configure1"})
	public BlogClientFallbackConfiguration blogClientFallback(){
		return new BlogClientFallbackConfiguration();
	}
}

在BlogClientImpl模拟异常

@RestController
@AllArgsConstructor
public class BlogClientImpl implements BlogClient {

   private BlogService service;

   @Override
   @GetMapping(API_PREFIX + "/detail")
   public R<Blog> detail(Integer id) {
      int cnt = 100 / 0;
      return R.data(service.getById(id));
   }

}

最后,使用Postman调用API查看,发现Hystrix配置生效

2.2Hystrix服务降级and服务全局降级

需添加注解

@EnableCircuitBreaker
//服务全局降级
@DefaultProperties(defaultFallback = "GlobalError")

模拟Hystrix服务降级and服务全局降级

/**
	 * @Description: 模拟超时过程  Hystrix测试
	 * @Param:
	 * @Author: 
	 * @Date: 2021-11-09 10:48
	 */
	@GetMapping("/timeOut")
	public String timeOut() throws InterruptedException {
		TimeUnit.SECONDS.sleep(3);
		return "模拟超时过程";
	}

	/**
	 * 模拟服务降级
	 */
	@GetMapping("/timeOuts")
	//配置熔断器,fallbackMethod为降级调用方法,commandProperties为触发服务降级配置
	@HystrixCommand(fallbackMethod = "errors", commandProperties = {
		//条件设置为2s后未返回结果则发生降级
		@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
	})
	public String timeOuts() {
		//模拟程序出错
		int cnt = 100 / 0;
		return "服务降级";
	}

	/**
	 * 模拟服务全局降级
	 */
	@GetMapping("/timeOutsqj")
	@HystrixCommand
	public String timeOutsqj() {
		//模拟程序出错
		int cnt = 100 / 0;
		return "服务全局降级";
	}

	public String errors() {
		return "这是服务出错/超时发生的降级处理方法";
	}

	public String GlobalError() {
		return "这是全局指定服务出错/超时发生的降级处理方法";
	}

七、Excel工具包使用

BladeX提供的Excel工具基于阿里出品的EasyExcel封装而来

1.前提准备

基于官方文档,我们编写一个EasyExcel格式的bean

@Data
@ColumnWidth(25)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class BlogExcel {

	/**
	 * 主键
	 */
//	@ExcelIgnore
	@ColumnWidth(10)
	@ExcelProperty("id")
	private Long id;
	/**
	 * 标题
	 */
	@ColumnWidth(20)
	@ExcelProperty("标题")
	private String blogTitle;
	/**
	 * 内容
	 */
	@ColumnWidth(20)
	@ExcelProperty("内容")
	private String blogContent;
	/**
	 * 时间
	 */
	@ColumnWidth(10)
	@ExcelProperty("时间")
	private Date blogDate;
	/**
	 * 是否已删除
	 */
//	@ExcelIgnore
	@ColumnWidth(10)
	@ExcelProperty("删除标记")
	private Integer isDeleted;
}

2.Excel导出

excel导出测试,有标题无数据

@GetMapping("export-notice")
public void exportNotice(HttpServletResponse response) {
   List<NoticeExcel> list = new ArrayList<>();
   ExcelUtil.export(response, "导出数据", "数据表", list, NoticeExcel.class);
}

excel导出数据测试,进行数据填充

	@GetMapping("/export-blog2")
	public void exportNotice2(HttpServletResponse response) {
		List<BlogExcel> list = new ArrayList<>();

		BlogExcel ne1 = new BlogExcel();
		ne1.setBlogTitle("标题1");
		ne1.setBlogContent("发布通知");
		ne1.setBlogDate(DateUtil.now());

		BlogExcel ne2 = new BlogExcel();
		ne2.setBlogTitle("标题2");
		ne2.setBlogContent("批转通知");
		ne2.setBlogDate(DateUtil.now());

		list.add(ne1);
		list.add(ne2);

		ExcelUtil.export(response, "test导出数据", "test数据表", list, BlogExcel.class);
	}

3.Excel读取测试

读取excel文件并返回list数据

	@PostMapping("read-blog")
	public R<List<BlogExcel>> readNotice(MultipartFile file) {
		List<BlogExcel> list = ExcelUtil.read(file, BlogExcel.class);
		return R.data(list);
	}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-.- !

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值