您好,登录后才能下订单哦!
一、概念
基于springboot基础上用于快速构建分布式系统的通用模式的工具集。
二、特点
1、约定优于配置;
2、隐藏组件复杂性;
3、轻量级组件;
4、组件丰富,功能齐全,例如:服务发现、断路器、微服务网关等;
5、选型中立、丰富;
6、灵活。
三、服务消费者与服务提供者
在微服务架构中有两种角色:服务消费者与服务提供者,二者关系如下:
服务提供者:服务的被调用者
服务消费者:服务的调用者
例如,在电影系统中,用户购买电影票票之前,电影服务需要调用用户服务的接口获取用户信息,此时的电影服务就是调用方,即服务消费者,用户服务为被调用方,即服务提供者。
四、微服务实践
1、服务提供者:用户服务
项目结构如下:

这个demo主要是为了演示服务与服务之间的通信,因此不再配置数据源。
User.java
package com.my.user.entity;
import lombok.Data;
/**
 * @author 垃圾美少女
 */
@Data
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String username;
    private Integer balance;
}IUserService.java
package com.my.user.service;
import com.my.user.entity.User;
/**
 * @author 垃圾美少女
 */
public interface IUserService {
    User getByUserId(Integer userId);
}UserServiceImpl.java
package com.my.user.service.impl;
import com.my.user.entity.User;
import com.my.user.service.IUserService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * @author 垃圾美少女
 */
@Service
public class UserServiceImpl implements IUserService {
    @Override
    public User getByUserId(Integer userId) {
        List<User> userList = getUserList();
        userList = userList.stream()
                .filter(user -> Objects.equals(user.getId(), userId))
                .collect(Collectors.toList());
        if (userList != null && userList.size() > 0) {
            return userList.get(0);
        }
        return null;
    }
    /**
     * 由于没有配置数据源,在此设置虚拟数据
     *
     * @return list
    */
    private List<User> getUserList() {
        List<User> list = new ArrayList<>(5);
        for (int i = 0; i < 5; i++) {
            User user = new User();
            user.setAge(12 + 1);
            user.setId(1 + i);
            user.setName("用户" + i);
            user.setUsername("用户名" + i);
            user.setBalance(123 + i);
            list.add(user);
        }
        return list;
    }
}UserController.java
package com.my.user.controller;
import com.my.user.Util.ReturnUtil;
import com.my.user.entity.User;
import com.my.user.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
 * @author 垃圾美少女
 */
@RestController
@Slf4j
public class UserController {
    @Autowired
    private IUserService userService;
    /**
     * 根据id获取用户信息
     *
     * @param userId 用户id
     * @return map
     */
    @RequestMapping(value = "/user/getUserInfo", method = RequestMethod.GET)
    public Map getUserInfo(Integer userId) {
        try {
            log.info("/user/getUserInfo被访问,参数:userId=" + userId);
            User user = userService.getByUserId(userId);
            return ReturnUtil.succe***esult(user, "获取成功");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ReturnUtil.errorResult(null, "获取失败");
        }
    }
}ReturnUtil.java
package com.my.user.Util;
import java.util.HashMap;
import java.util.Map;
/**
 * @author 垃圾美少女
 */
public class ReturnUtil {
    public static Map succe***esult(Object data, String msg) {
        Map<String, Object> map = new HashMap<>(3);
        map.put("code", 1);
        map.put("msg", msg);
        map.put("data", data);
        return map;
    }
    public static Map errorResult(Object data, String msg) {
        Map<String, Object> map = new HashMap<>(3);
        map.put("code", -1);
        map.put("msg", msg);
        map.put("data", data);
        return map;
    }
}application.yml
server: port: 8010 #指定端口为 8010
启动项目后访问:http://localhost:8010/user/getUserInfo?userId=1
得到相应:
{
    "msg": "获取成功",
    "data": {
        "id": 1,
        "name": "用户0",
        "age": 13,
        "username": "用户名0",
        "balance": 123
    },
    "code": 1
}表示接口已通。
2、服务消费者:电影服务
项目架构如下:

User.java和ReturnUtil.java与上例相同在此不再展示。
MovieApplicaiton.java
package com.my.movie;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class MovieApplication {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(MovieApplication.class, args);
    }
}MovieController.java
package com.my.movie.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
/**
 * @author 垃圾美少女
 */
@RestController
@Slf4j
public class MovieController {
    @Autowired
    private RestTemplate restTemplate;
    @RequestMapping(value = "/movie/findById", method = RequestMethod.GET)
    public Map findById(Integer userId) {
        log.info("/movie/findById被访问,参数:userId=" + userId);
        ResponseEntity<HashMap> forEntity =
                this.restTemplate.getForEntity("http://localhost:8010/user/getUserInfo?userId=" + userId, HashMap.class);
        return forEntity.getBody();
    }
}application.yml
server: port: 8020
此时启动项目,访问:http://localhost:8020/movie/findById?userId=1
得到响应:
{
    "msg": "获取成功",
    "code": 1,
    "data": {
        "id": 1,
        "name": "用户0",
        "age": 13,
        "username": "用户名0",
        "balance": 123
    }
}至此,一个简单的电影微服务就完成了。
五、上述例子中存在的问题
1、在代码中写死访问路径
在电影服务中,可以将user服务的访问路径写到yml配置文件中,使代码更清爽:
yml:
server: port: 8020 userService: domain: http://localhost:8010/user/ getUserByIdUrl: http://localhost:8010/user/getUserInfo?userId=
MovieController.java
package com.my.movie.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
/**
 * @author 垃圾美少女
 */
@RestController
@Slf4j
public class MovieController {
    @Autowired
    private RestTemplate restTemplate;
    @Value("${userService.domain}")
    private String userServiceDomain;
    @Value("${userService.getUserByIdUrl}")
    private String findByUserIdUrl;
    @RequestMapping(value = "/movie/findById", method = RequestMethod.GET)
    public Map findById(Integer userId) {
        log.info("/movie/findById被访问,参数:userId=" + userId);
        ResponseEntity<HashMap> forEntity =
                this.restTemplate.getForEntity(findByUserIdUrl + userId, HashMap.class);
        return forEntity.getBody();
    }
}2、适用场景有限:当用户服务的地址或端口号发生改变时,需要修改电影服务的配置文件并且重新部署,这显然是不可取的。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。