今天在做项目时,发现个很有意思的知识点(自我认为),在这里总结下来。
我在做项目时,需要做一个新的需求,该项目是以前说过的多个服务通过远程调用(remote命名,@RequestMapping(value = “/wms-service/in/wmsinreceipt/listSKInfo”)远程服务匹配的机制)。来看接口。
WmsInReceiptRemote.java
@FeignClient(name = "gateway-server", fallbackFactory = WmsInReceiptRemoteFallBackFactory.class)
public interface WmsInReceiptRemote {
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listScmMat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
R listScmMat(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listSKInfo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R listSKInfo(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listPOMat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R listPOMat(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listOutMat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R listOutMat(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listPOCFMat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R listPOCFMat(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/list303Mat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R list303Mat(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/list303AMat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R list303AMat(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listPOAMat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R listPOAMat(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listOutAMat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R listOutAMat(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/boundIn", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R boundIn(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/getMatInfo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R getMatInfo(@RequestParam Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/getCostMatInfo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public R getCostMatInfo(@RequestParam Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/info/{qty}")
public R info(@PathVariable("qty") Long qty);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listCloudMat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
R listCloudMat(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listCloudMatSyn", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
R listCloudMatSyn(@RequestBody Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/getSAPMatDetail", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
R getSAPMatDetail(@RequestParam(value = "params") Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/exportExcel", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
R exportExcel(@RequestParam(value = "params") Map params);
@RequestMapping(value = "/wms-service/in/wmsinreceipt/listStoMat", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
R listStoMat(@RequestBody Map params);
}
// @RequestMapping(value = "/test") 松开测试新加方法
// R newAddMethod(@RequestBody Map params);
该接口里的所有方法不用管,就是一些业务。而此时我新做了个业务,需要在这里面加一个方法,此时有趣的问题就来了。因为采用的是热部署,不过一会儿(其实就是因为java代码更改重新build的过程)错误信息就出来了。
我就很好奇这个问题,于是就访问相关文件。
WmsInReceiptRemoteFallBackFactory.java
import feign.hystrix.FallbackFactory; @Component public class WmsInReceiptRemoteFallBackFactory implements FallbackFactory{ @Override public WmsInReceiptRemote create(Throwable cause) { return new WmsInReceiptRemote() { @Override public R listScmMat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R listSKInfo(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R listPOMat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R listOutMat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R listPOCFMat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R list303Mat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R list303AMat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R listPOAMat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R listOutAMat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R boundIn(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R getMatInfo(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R getCostMatInfo(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R info(Long qty) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R listCloudMat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R listCloudMatSyn(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R getSAPMatDetail(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R exportExcel(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } @Override public R listStoMat(Map params) { // return R.error(500, "WMS-BUSINESS-SERVICE服务异常!"); return R.error(500,LocaleLanguageFactory.getValue("J_WMS_BUSINESS_SERVICEFWYC")); } }; } }
报错的原因原来是这里使用了匿名内部类new接口,因为不是abstract的,所以需要完成接口的所有方法。
问题很容易解决,再将没实现的方法实现一下就行了。
不过,吸引我的是为什么会有WmsInReceiptRemoteFallBackFactory这个类?它是干什么的?
看回WmsInReceiptRemoteFallBackFactory的java源码文件,发现其就是再做一件事抛异常,这个类就是只专注做一件事抛异常,于是我就有了大胆的猜测。
1.1、猜测小结以前学习接口的时候,会发现接口可以带抛出异常,但是我们知道接口是抽象的,而接口的实现类是定性的,同一接口的不同实现类处理方法实现业务可能有自己不同的异常,不同实现类可以自己万紫千红地自己表达自己的异常,如何把这些异常统一起来表达,这就是FallbackFactory在做的。
接口可能有不同的实现类,不同实现类做的同一业务(或者说执行的同一方法)可能有自己不同的异常信息,为了保护这些异常信息不对外,或者为了将这些异常信息总结为同一个信息。 也就是说任意实现类执行这个方法出错了(也就是只要这个接口方法执行出错),你在所有实现类写的任意错误信息都不会表达出来,而会同一表达成定义在FallbackFactory的错误信息。这也就是接口的统一异常。
随后,我在网上搜索了FallbackFactory的相关知识。得到了这个结论。Hystrix的功能,当网络不通时返回默认的配置数据。在FeignClient中,可以通过制定fallback,实现在服务不可用时自动调用fallback指定定的处理方法。
关于如何使用(绑定)。
-
xx接口类,绑定xxFallbackFactory类。也就是加注解@FeignClient(name = “…”, fallbackFactory = xxxFallBackFactory.class)。
-
xxFallbackFactory类更新create代码。
FallbackFactory的作用理解了,底层怎么实现的不知道,需要后续学习。
上述类R也不用在意,其就是模仿浏览器的状态码,看R源码。
R.java
public class R extends HashMap{ private static final long serialVersionUID = 1L; public R() { put("code", 0); put("msg", "success"); } public static R error() { // return error(500, "未知异常,请联系管理员"); return error(500, LocaleLanguageFactory.getValue("J_UK_EXCEP_CONT_ADMIN")); } public static R error(String msg) { return error(500, msg); } public static R error(int code, String msg) { R r = new R(); r.put("code", code); r.put("msg", msg); return r; } public static R ok(String msg) { R r = new R(); r.put("msg", msg); return r; } public static R ok(Map map) { R r = new R(); r.putAll(map); return r; } public static R ok() { return new R(); } @Override public R put(String key, Object value) { super.put(key, value); return this; } public Boolean isOk(){ return (Integer)this.get("code") == 0; } }



