微服务Feign相关杂记

1 各个微服务有自己的token,如何调用免除微服务之前的token,但不能影响每个服务自身的token校验机制呢?

解决方案两个步骤

   步骤之一:在feignclient中增加自定义标识头

headers = {"ContentType=application/x-www-form-urlencoded","OutToken=true"}
@PostMapping(value = "/hardware/getbuildNuListByAreaId",headers = {"ContentType=application/x-www-form-urlencoded","OutToken=true"})
    public Result<IPage<BuildNumListVo>> getbuildNuListByAreaId(
            @RequestParam(name = "houseAreaId", required = true) String houseAreaId,
            @RequestParam(name = "pageSize", required = false, defaultValue = "10") Integer pageSize,
            @RequestParam(name = "pageNo", required = false, defaultValue = "1") Integer pageNo);

步骤二在切面中过滤拦截限制

//如果是FeignClient调用那么直接过滤掉token,OutToken为外部调用是否放行,true放行,false不放行
String OutToken = request.getHeader("OutToken");
if(StringUtils.equals(OutToken,"true")){//放行
   return  point.proceed();
}
package org.jeecg.common.aspect;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.aspect.annotation.DeviceAuthToken;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.YyResultCodeVsMsgConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.SpringContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Enumeration;


/**
 * @version 1.0
 * @Author zhaozhiqiang
 * @Date 2021/11/26 10:05
 * @Param
 * @Description //TODO 设备端token拦截切面
 * @return
 */
@Aspect
@Component
@Slf4j
public class DeviceAuthTokenAspect {

	@Autowired
	private RedisUtil redisUtil;
	/**
	 * 切点
	 */
	@Pointcut("@annotation(org.jeecg.common.aspect.annotation.DeviceAuthToken)")
	public void pointCut() {

	}

	@Around("pointCut()")
	public Object arround(ProceedingJoinPoint point) throws  Throwable{
		HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
		//如果是FeignClient调用那么直接过滤掉token,OutToken为外部调用是否放行,true放行,false不放行
		String OutToken = request.getHeader("OutToken");
		if(StringUtils.equals(OutToken,"true")){//放行
			return  point.proceed();
		}
		MethodSignature signature = (MethodSignature) point.getSignature();
		Method method = signature.getMethod();
		DeviceAuthToken pd = method.getAnnotation(DeviceAuthToken.class);
		boolean value = pd.value();
		if(!value){
			return  point.proceed();
		}
		// 将token信息放入header中
		String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);//设备名+登录密码
		if(token==null || "".equals(token)){
			token = request.getParameter("unique");
		}
		if(token==null || "".equals(token)){
			throw  new JeecgBootException(YyResultCodeVsMsgConstant.DEVICE_TOKEN_IS_NULL_CODE+ ":" + YyResultCodeVsMsgConstant.DEVICE_TOKEN_IS_NULL_MSG);
		}
		if (!StringUtils.isNotBlank(JwtUtil.getDeviceName(token))) {//有效
			throw  new JeecgBootException(YyResultCodeVsMsgConstant.DEVICE_SERVICE_TOKEN_ILLEGAL_CODE+ ":" + YyResultCodeVsMsgConstant.DEVICE_SERVICE_TOKEN_ILLEGAL_MSG);
		}
		//判断缓存中token是否失效
		Object redisToken = redisUtil.get(CommonConstant.PREFIX_DEVICE_TOKEN + token);
		if((redisToken==null || "".equals(redisToken))){
			throw  new JeecgBootException(YyResultCodeVsMsgConstant.DEVICE_SERVICE_TOKEN_IS_NULL_CODE+ ":" + YyResultCodeVsMsgConstant.DEVICE_SERVICE_TOKEN_IS_NULL_MSG);
		}else{
			if(null!=redisToken){//用户名登陆
				//查看token与服务端是否匹配
				if(!StringUtils.equals(token,redisToken.toString())){
					throw  new JeecgBootException(YyResultCodeVsMsgConstant.DEVICE_SERVICE_TOKEN_AND_INNPU_CODE+ ":" + YyResultCodeVsMsgConstant.DEVICE_SERVICE_TOKEN_AND_INNPU_MSG);
				}
			}
		}
		return  point.proceed();
	}

}

2 微服务表单对象传递,数据丢失

解决方案增加@SpringQueryMap

 @PostMapping(value = "/hardware/switchLight",headers = {"ContentType=application/x-www-form-urlencoded","OutToken=true"})
    public Result switchLight(@SpringQueryMap SwitchLightDto dto);

3 微服务multipart/form-data混合表单传参解析不了

解决步骤:

    步骤一:在FeignClient中增加如下

consumes = MediaType.MULTIPART_FORM_DATA_VALUE
/**
 * 文件上传
 * @return
 * @throws Exception
 */
@PostMapping(value = "/property/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result<?> upload(@RequestParam(value = "biz",required = false ,defaultValue = "temp")String biz,
                        @RequestPart(value = "file",required = true)MultipartFile file) throws Exception ;

  步骤二:具体的接口也增加

     

@PostMapping(value = "property/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Result<?> upload(@RequestParam(value = "biz",required = false ,defaultValue = "temp")String biz,
                        @RequestPart(value = "file",required = true)MultipartFile file) throws Exception {

}

4 微服务分页问题 

调用方不能用interface类

public class Page<T> implements IPage<T> {

微服务方

@PostMapping(value = "/hardware/getHouseAreaListByPca",headers = {"ContentType=application/x-www-form-urlencoded","OutToken=true"})
public Result<IPage<HouseAreaListVo>> getHouseAreaListByPca(
        @RequestParam(name = "pca", required = true) String pca,
        @RequestParam(name = "pageSize", required = false, defaultValue = "10") Integer pageSize,
        @RequestParam(name = "pageNo", required = false, defaultValue = "1") Integer pageNo);

调用方

@ApiOperation(value = "根据省市区获取当前小区信息", notes = "根据省市区获取当前小区根据省市区获取当前小区信息")
@PostMapping(value = "/getHouseAreaListByPca")
@ApiImplicitParams({
        @ApiImplicitParam(paramType = "query", dataType = "String", name = "pcaId", value = "省市区编号", required = true),
        @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "pageSize", defaultValue = "10", value = "每页条数", required = false),
        @ApiImplicitParam(paramType = "query", dataType = "Integer", name = "pageNo", defaultValue = "1", value = "当前页", required = false),
})
public Result<Page<HouseAreaListVo>> getHouseAreaListByPca(
        @RequestParam(name = "pcaId", required = true) String pcaId,
        @RequestParam(name = "pageSize", required = false, defaultValue = "10") Integer pageSize,
        @RequestParam(name = "pageNo", required = false, defaultValue = "1") Integer pageNo) {
    Result<Page<org.jeecg.common.system.mj.vo.HouseAreaListVo>> houseAreaListByPca = sysBaseAPI.getHouseAreaListByPca(pcaId, pageSize, pageNo);
    return houseAreaListByPca;
}

 5 多类目分类

@Data
public class RepairTypeVo implements Serializable {
    @ApiModelProperty(value = "维修类型(1住宅报修,2公共报修)")
    private Integer maintainType;
    @ApiModelProperty(value = "id")
    private String id;
    @ApiModelProperty(value = "维修设施")
    private String name;

    public RepairTypeVo(Integer maintainType, String id, String name) {
        this.maintainType = maintainType;
        this.id = id;
        this.name = name;
    }
}
public static void main(String args[]) {
    List<RepairTypeVo> list2=new ArrayList<RepairTypeVo>();
    list2.add(new RepairTypeVo(1,"1","name"));
    list2.add(new RepairTypeVo(2,"5","name5"));
    list2.add(new RepairTypeVo(3,"4","name2"));
    list2.add(new RepairTypeVo(1,"1","name7"));
    Map<Integer, List<RepairTypeVo>> collect =
            list2.stream().collect(Collectors.groupingBy(RepairTypeVo::getMaintainType));
    System.out.println(new Gson().toJson(collect));

}

{

  • "1":[
    1. {
      • "maintainType":1,
      • "id":"1",
      • "name":"name"
      },
    2. {
      • "maintainType":1,
      • "id":"1",
      • "name":"name7"
      }
    ],
  • "2":[
    1. {
      • "maintainType":2,
      • "id":"5",
      • "name":"name5"
      }
    ],
  • "3":[
    1. {
      • "maintainType":3,
      • "id":"4",
      • "name":"name2"
      }
    ]

 前端页面边界去重

/**
     * 从diff中找出main中没有的元素
     * @param main
     * @param diff
     * @return
     */
    private List<String> getDiff(String main,String diff){
        if(oConvertUtils.isEmpty(diff)) {
            return null;
        }
        if(oConvertUtils.isEmpty(main)) {
            return Arrays.asList(diff.split(","));
        }

        String[] mainArr = main.split(",");
        String[] diffArr = diff.split(",");
        Map<String, Integer> map = new HashMap<>();
        for (String string : mainArr) {
            map.put(string, 1);
        }
        List<String> res = new ArrayList<String>();
        for (String key : diffArr) {
            if(oConvertUtils.isNotEmpty(key) && !map.containsKey(key)) {
                res.add(key);
            }
        }
        return res;
    }

linux启动脚本

#版本 注意,需要跟随版本号进行调整
version=3.4.4
#运行目录
run_path=/usr/local/services/jar/
ps -ef |grep java |grep jeecg-cloud-nacos  |grep -v 'grep'|awk '{print $2}'  | xargs kill -9
ps -ef |grep java |grep jeecg-cloud-gateway  |grep -v 'grep'|awk '{print $2}'  | xargs kill -9
ps -ef |grep java |grep jeecg-system-cloud-start  |grep -v 'grep'|awk '{print $2}'  | xargs kill -9
ps -ef |grep java |grep jeecg-module-hardware-start  |grep -v 'grep'|awk '{print $2}'  | xargs kill -9
ps -ef |grep java |grep jeecg-module-operate-start  |grep -v 'grep'|awk '{print $2}'  | xargs kill -9
ps -ef |grep java |grep jeecg-module-property-start  |grep -v 'grep'|awk '{print $2}'  | xargs kill -9
ps -ef |grep java |grep jeecg-module-community-start  |grep -v 'grep'|awk '{print $2}'  | xargs kill -9

cd ${run_path}
#先启动nacos
nohup java -Xmx512m -Xms512m -Xss256k  -jar jeecg-cloud-nacos-$version.jar> logs/nacos.out  &
sleep 6s

nohup java -Xmx512m -Xms512m -Xss256k  -jar jeecg-module-community-start.jar> logs/community.out  
nohup java -Xmx512m -Xms512m -Xss256k  -jar jeecg-system-cloud-start-$version.jar> logs/system.out  &
nohup java -Xmx512m -Xms512m -Xss256k  -jar jeecg-module-hardware-start.jar> logs/hardware.out  &
nohup java -Xmx512m -Xms512m -Xss256k  -jar jeecg-module-operate-start.jar> logs/operate.out  &
nohup java -Xmx512m -Xms512m -Xss256k  -jar jeecg-module-property-start.jar> logs/property.out  &
nohup java -Xmx512m -Xms512m -Xss256k  -jar jeecg-cloud-gateway-$version.jar> logs/gateway.out  &
 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
微服务之间的调用,也可以使用Feign来进行,同样需要在Feign的配置中启用HTTPS支持。具体步骤如下: 1. 引入Feign的依赖 ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> ``` 2. 配置Feign的HTTPS支持 ``` @Configuration public class FeignConfig { @Autowired private ObjectFactory<HttpMessageConverters> messageConverters; @Bean public Client feignClient() { return new Client.Default(getSSLSocketFactory(), null); } private SSLSocketFactory getSSLSocketFactory() { try { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[] { new X509TrustManager() { public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {} public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {} public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }, new SecureRandom()); return sslContext.getSocketFactory(); } catch (Exception e) { throw new RuntimeException(e); } } @Bean public Decoder feignDecoder() { return new ResponseEntityDecoder(new SpringDecoder(messageConverters)); } } ``` 其中,`getSSLSocketFactory`方法返回一个`SSLSocketFactory`对象,用于创建HTTPS连接。这里采用了忽略证书的方式,实际生产环境中应该使用可信的证书。 3. 在Feign的接口中使用`https`协议 ``` @FeignClient(name = "example", url = "https://example.com") public interface ExampleClient { @GetMapping("/api") String get(); } ``` 其中,`url`参数指定了HTTPS协议的地址。 4. 在微服务中使用Feign进行调用 ``` @RestController public class ExampleController { @Autowired private ExampleClient exampleClient; @GetMapping("/example") public String get() { return exampleClient.get(); } } ``` 这样就可以在微服务中使用Feign调用HTTPS接口了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

BACKWASH2038

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

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

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

打赏作者

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

抵扣说明:

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

余额充值