微服务
在没使用到springcloud之前我们都是通过使用“RestTemplate”去进行微服务之间的调用,即:在SpringBoot启动类添加一个bean实例
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
下面来展示使用“RestTemplate”调用微服务
两个工程一个ms-user、ms-class 都是SpringBoot+Jpa
首先是ms-user工程(服务提供者)
目录结构
实体类
@Table(name = "user")
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String username;
@Column
private String password;
@Column
private BigDecimal money;
@Column
private String role;
@Column
private Date regTime;
}
Repository
@Repository
public interface UserRepository extends CrudRepository<User,Integer>{
}
Repository—>即:dao层、mapper层(如果不了解Jpa建议百度去了解)
Service
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User findById(Integer id) {//这里使用了java8新特性
return this.userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("用户不存在"));
}
}
Controller
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users/{id}")
public User findById(@PathVariable Integer id){
return this.userService.findById(id);
}
}
SpringBoot启动类
@SpringBootApplication
public class MsUserApplication {
public static void main(String[] args) {
SpringApplication.run(MsUserApplication.class, args);
}
}
yml配置
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/ms_user?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
hikari:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
#让hibernate不去操作表结构
ddl-auto: none
show-sql: true
ms-class工程(服务消费者)
工程目录
实体类
@Table(name = "lesson")
@Entity
public class Lesson {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String title;
@Column
private String cover;
@Column
private BigDecimal price;
@Column
private String description;
@Column
private Date createTime;
@Column
private String videoUrl;
}
@Table(name = "lesson_user")
@Entity
public class LessonUser {
@Id
@Column
private Integer lessonId;
@Column
private Integer userId;
}
Repository
@Repository
public interface LessonRepository extends CrudRepository<Lesson,Integer>{
}
@Repository
public interface LessonUserRepository extends CrudRepository<LessonUser,Integer>{
LessonUser findByLessonId(Integer id);
}
Service
@Service
public class LessonService {
@Autowired
private LessonRepository lessonRepository;
@Autowired
private LessonUserRepository lessonUserRepository;
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
public Lesson buyById(Integer id) {
//1.根据id查询lesson
Lesson lesson = this.lessonRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("该课程不存在!"));
//2.根据lesson.id查询user_lesson,那么直接返回lesson如果没有
LessonUser lessonUser = this.lessonUserRepository.findByLessonId(id);
if (lessonUser != null) {
return lesson;
}
//3.根据user_lesson == null && 用户的余额 > lesson.price,就去购买
// TODO 登录实现后需重构
Integer userId = 1;
List<ServiceInstance> instances = this.discoveryClient.getInstances("/ms-user");
List<ServiceInstance> userInstancesInNJJIFANG = instances.stream()
.filter(instance -> {
// 用户微服务的元数据
Map<String, String> metadata = instance.getMetadata();
String jifang = metadata.get("JIFANG");
if ("NJ".equals(jifang)) {
return true;
}
return false;
}).collect(Collectors.toList());
// TODO 需要改进
URI uri = userInstancesInNJJIFANG.get(0)
.getUri();
UserDTO userDTO = restTemplate.getForObject(
uri + "/users/{userId}",
UserDTO.class,
userId
);
//lesson.getPrice() - 此BigDecimal要减去的值
BigDecimal money = userDTO.getMoney().subtract(lesson.getPrice());
if (money.doubleValue() < 0) {
throw new IllegalArgumentException("余额不足!");
}
//TODO 购买逻辑。。。1. 调用用户微服务的扣减金额接口;2. 向lesson_user表插入数据
return lesson;
}
}
Controller
@RestController
@RequestMapping("/lessons")
public class LessonController {
@Autowired
private LessonService lessonService;
/**
* 购买指定id的课程
* @param id
*/
@GetMapping("/buy/{id}")
public Lesson findById(@PathVariable Integer id){
return this.lessonService.buyById(id);
}
}
SpringBoot启动类
@SpringBootApplication
public class MsClassApplication {
public static void main(String[] args) {
SpringApplication.run(MsClassApplication.class, args);
}
/**
* spring web提供的轻量级http client
* <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
yml
server:
port: 8010
spring:
datasource:
url: jdbc:mysql://localhost:3306/ms_class?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
hikari:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
#让hibernate不去操作表结构
ddl-auto: none
show-sql: true
application:
name: ms-class
主要体现在Service层