JeecgBoot使用總結-Feign的使用總結


當系統為微服務時,需要模塊之間的調用,但是不太方便直接將模塊整個引入,所以就需要使用Feign進行調用,使用步驟進行總結,比如A模塊准備調用B模塊的C方法,按照這個進行整理。

第一步:

因為要調用B模塊,所以需要在B模塊創建一個對外的服務接口,並將業務進行實現,代碼如下:

package org.jeecg.modules.api.controller;
/**
 * 服務化 system模塊 對外接口請求類
 */
@Api(tags="對外接口請求類")
@RestController
@RequestMapping("/sys/api")
@Slf4j
public class SystemAPIController extends BaseController {

    @Resource
    private SysUserMapper userMapper;

    ....../**
     * 37根據多個用戶id(逗號分隔),查詢返回多個用戶信息
     * @param ids
     * @return
     */
    //todo feign 第三步在該模塊聲明接口
    @RequestMapping("/queryUsersById")
    LoginUser queryUsersById(@RequestParam("ids") String ids){
        log.info("fegin遠程調用:第三步");
        //return this.sysBaseAPI.queryUsersById(ids);
        log.info("fegin遠程調用:直接隔斷");
        SysUser user = userMapper.selectById(ids);
        LoginUser loginUser = new LoginUser();
        if (user!=null){
            loginUser.setId(user.getId());
            loginUser.setAvatar(user.getAvatar());
            loginUser.setRealname(user.getRealname());
        }
        return loginUser;
    }
  ......
}

以上代碼中的對外接口就是”/sys/api/queryUsersById“。

第二步:

因為A模塊調用B模塊,也會存在其他模塊之間的調用,為了提供公共的對外接口,就需要一個額外的公共api模塊,於是有了如下路徑

jeecg-boot-base\jeecg-boot-base-api\jeecg-system-cloud-api\src\main\java\org\jeecg\common\system\api\ISysBaseAPI.java

為了區分是單體還是微服務,使用jeecg-system-cloud-api以及jeecg-system-local-api,也就是cloud和local進行區分。因為咱們使用的是微服務,所以重點說一下cloud模塊。

在cloud模塊中還有一下分類,system.api、online.api、bpm.api,見明知義,主要是按照你調用模塊的簡稱進行區分,調用jeecg-system模塊的api全都寫在system這個api中。

每個模塊中的文件夾都是固定的,接下來簡單說一下每個文件夾中文件的作用

 如圖片所示,先簡單說一下2和3,其實他們就是一個東西,熔斷器,主要增加一層保險,當接口查詢不到數據,默認返回一些假數據,從而達到防止系統查詢不到數據導致崩潰的作用。2和3中有對方法的一些重寫,其實就是一模一樣的接口再重新寫一遍,但是返回的值

正常的話會進行處理,具體的使用看下邊代碼中標紅的fallbackFactory參數

接下來就是重點說1的作用了,1其實就是對位的api接口,底層通過http請求來找到對應模塊中的接口。代碼如下:

package org.jeecg.common.system.api;
@Component
@FeignClient(contextId = "sysBaseRemoteApi", value = ServiceNameConstants.SYSTEM_SERVICE, fallbackFactory = SysBaseAPIFallbackFactory.class)
public interface ISysBaseAPI extends CommonAPI {

    ......//todo feign 第一步聲明接口
    @RequestMapping("/sys/api/queryUsersById")
    LoginUser queryUsersById(@RequestParam("ids") String ids);

    ......

}
  //在接口上加 @FeignClient 注解來聲明 一個Feign Client,其中 value 為 遠程調用其他服務的服務名
  //FeignConfig.class 為 Feign Client 的配置類,注入Retryer類的實例,這樣在遠程調用失敗后,feign會進行重試
  //使用 Spring MVC 的注解來綁定具體該服務提供的 REST 接口
  //fallback 配置回調處理類,該處理類是作為 Feign 熔斷器的邏輯處理類,實現FeignHystrixInter 接口
  //fallbackFactory(類似於斷容器)與fallback方法。

看到標紅的地方沒,有沒有很熟悉,其實就是第一步中所謂的對外接口,這下基本上就已經對應上了。

需要重點注意@FeignClient后邊的三個參數。

  • contextId:api接口的id
  • value:對應模塊的名稱
  • fallbackFactory:熔斷器的文件地址

第三步:

前兩步將准備工作已經做好,接下來就只需要引用然后調用即可。

在B模塊啟動類中,先啟用Feign,代碼如下:

package org.jeecg;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.Environment;
import java.net.InetAddress;
import java.net.UnknownHostException;
@Slf4j
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients public class JeecgknowledgeCloudApplication extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(JeecgknowledgeCloudApplication.class);
    }
    public static void main(String[] args) throws UnknownHostException {
        long startTime = System.currentTimeMillis();    //獲取開始時間
        ConfigurableApplicationContext application = SpringApplication.run(JeecgknowledgeCloudApplication.class, args);
        Environment env = application.getEnvironment();
        String ip = InetAddress.getLocalHost().getHostAddress();
        String port = env.getProperty("server.port");
        String path = oConvertUtils.getString(env.getProperty("server.servlet.context-path"));
        log.info("\n----------------------------------------------------------\n\t" +
                "Application Jeecg-Boot is running! Access URLs:\n\t" +
                "Local: \t\thttp://localhost:" + port + path + "/doc.html\n" +
                "External: \thttp://" + ip + ":" + port + path + "/doc.html\n" +
                "Swagger文檔: \thttp://" + ip + ":" + port + path + "/doc.html\n" +
                "----------------------------------------------------------");
        System.out.println("=====知識庫-啟動成功=====");
        long endTime = System.currentTimeMillis();    //獲取結束時間
        System.out.println("程序運行時間:" + (endTime - startTime)/1000 + "");    //輸出程序運行時間
    }
}

標紅的位置是在啟動類啟動fegin的服務應用,然后引入api的模塊,接着在你需要的類中引用“ISysBaseAPI”這個類,從而去引用你想要引用的方法

package org.jeecg.modules.wiki.service.impl;/**
 * @Description: 頁面信息
 * @Author: jeecg-boot
 * @Date:   2021-11-12
 * @Version: V1.0
 */
@Service
@DS("knowledge")
public class ContentServiceImpl extends ServiceImpl<ContentMapper, Content> implements IContentService {

    @Autowired
    private  ContentMapper contentMapper;

    @Autowired
    private BodycontentMapper bodycontentMapper;

    @Autowired
    private IBodycontentService iBodycontentService;

    @Autowired private ISysBaseAPI iSysBaseAPI;

    ......

    @Override
    public List<ContentVO> getAlllatelyWork(Content content) {
        List<ContentVO> list =new ArrayList<>();
        LoginUser user01 = iSysBaseAPI.queryUsersById("e9ca23d68d884d4ebb19d07889727dae"); // 系統用戶信息
        log.debug("數據查詢:"+user01.getUsername());
        List<ContentVO> contentVOList = contentMapper.getUserWork(DateUtil.getDate(),DateUtil.getupperDate(),content.getUsername());
        if (contentVOList.size()>0&&contentVOList!=null){
            for (ContentVO contentVO : contentVOList) {
                if (!StringUtils.isEmpty(contentVO.getUsername())){
                    LoginUser user =  iSysBaseAPI.queryUsersById(contentVO.getUsername()); // 系統用戶信息
                    if (user!=null){
                        contentVO.setLastName(user.getRealname());
                        contentVO.setActive(user.getAvatar());
                    }
                }
                list.add(contentVO);
            }

        }
        return list;
    }

}

以上過程就完成了模塊之間的調用了。

對於feign參數的使用也進行過總結,鏈接:Feign使用總結-參數傳遞

大致的流程圖如下:

 

 注意:

有些模塊已經引用了ISysBaseAPI這個類,但是調用的是local模塊,通過以上的流程圖進行調用的,當需要一個新的Feign接口時,一定要注意按照已經存在的形式進行使用,不能直接引用以下代碼,不然本該走local的直接走cloud,就會導致啟動異常。

     <dependency>
            <groupId>org.jeecgframework.boot</groupId>
            <artifactId>jeecg-system-cloud-api</artifactId>
        </dependency>

eg:jeecg-boot-module-system模塊中JimuReportTokenService類中引用代碼(部分)

/**
 * 自定義積木報表鑒權(如果不進行自定義,則所有請求不做權限控制)
 *  * 1.自定義獲取登錄token
 *  * 2.自定義獲取登錄用戶
 */
@Component
public class JimuReportTokenService implements JmReportTokenServiceI {
    @Autowired
    private ISysBaseAPI sysBaseAPI;

在沒有引cloud之前走的是local,在引用后走的是cloud。就會導致出現問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM