• [技术干货] 利用Java SDK开发OBS, 创建桶失败:IllegalLocationConstraintExceptio
    Response Code: 400Error Message: The  location constraint is incompatible for the region specific endpoint this request was sent to.Error Code:       IllegalLocationConstraintExceptionRequest ID:      00000171D44061F59011D81F3F8FC8AFHost ID:           gVNXYhZIxXzQmJYAuEry2vbWxP2mbdVkv5B4mJHidhajjxwhLnnvY73GmrbiYlq7
  • [问题求助] 服务器与物联网管理云平台对接的问题
    使用postman调试问题:是否需要证书,以及证书应该如何配置是不是在服务器端和云平台都要配(仅用于测试阶段)?在第一步获取accetoken 时,appId和secret信息从哪里获取,我在云平台上只找了APPId,以及是否需要内网穿透?我从华为下的文件JavaSDK中的一个文件中找到了appid和secret信息输入到postman上,并且试过用内网穿透和不使用内网穿透,安装上了华为给的postman的证书,但是postman依然收不到回复关于应用测java sdk的使用,是否需要使用其他工具(如maven),从华为下的JAVA SDK文件夹中里面的,应该使用哪些jar包?我直接使用myeclipse建了一个建了一个java工程,导入 JAVA SDK 中JAR包,然后使用指导书上步骤,获取accetoken,源代码没有错,但是编译出错?请问java sdk到底该如何使用,本人专业学的本来就是偏硬件,毕设给分到了这些偏软件的题,对java懂的也不多,有哪位大佬有时间可以给我指点一下吗? 有偿。 
  • [技术干货] JVM监控java.lang.management简介
        java.lang.management是JDK自带的一套工具库。通过工厂类ManagementFactory对外提供一套管理接口,提供JVM和JVM所运行操作系统的各种信息,例如:内存使用情况、GC情况和操作系统版本等。基于以上信息,可以辅助我们对定位问题或者性能调优提供数据支撑。Management同时允许从本地和远程(JMX)对正在运行的JVM进行监视和管理。MXBean简介      根据ManagementFactory的javadoc,可以看出它提供了大量的工厂方法,使得我们可以通过调用这些方法来获取JVM各组件相关的JavaBean,通过这些JavaBean就可以获取到对应组件的运行状态数据。而这些JavaBean是各个服务启动时自动注册好的,运行数据也是提前计算好的,所以我们并不会因为获取相关数据,而导致额外消耗资源进行计算。       这些JavaBean被称之为MBean或者MXBean。MBean和MXBean两者的区别在于:MXBean是一个特殊的MBean,它的数据类型被限制为开放类型,基本上是原始类型、字符串及其组合。由于这些限制,MXBean可以在不加载类的情况下使用,这使得它们甚至可以与非Java客户机进行互操作。这个特性对于我们进行通用封装是十分重要的。使用案例1:      JVM频繁的FullGC或者Java服务发生了OOM,但是JVM进程并没有自动退出。这种场景下,仅仅在操作系统层面对JVM进程进行监控是不能及时发现相关问题的。可以使用MemoryMXBean和GarbageCollectorMXBean来获取相关信息;并结合其他监控或者定时执行机制,实现告警等功能。实现代码:public class MemoryMXBeanTest {    private static volatile MemoryMXBean memoryMBean;    private static volatile List<GarbageCollectorMXBean> garbageCollectorMXBeanList;     /**     *  获取memoryMBean     */    private static void initMemoryMXBean() {        synchronized (MemoryMXBeanTest.class) {            if (memoryMBean == null) {                try {                    memoryMBean = AccessController.doPrivileged(                            new PrivilegedExceptionAction<MemoryMXBean>() {                                @Override                                public MemoryMXBean run() throws DrsException {                                    return ManagementFactory.getMemoryMXBean();                                }                            });                } catch (Exception exp) {                    log.error("", exp);                }            }        }    }     /**     * 获取GarbageCollectorMXBean     */    private static void initGarbageCollectorMXBean() {        synchronized (MemoryMXBeanTest.class) {            if (garbageCollectorMXBeanList == null) {                try {                    garbageCollectorMXBeanList = AccessController.doPrivileged(                            new PrivilegedExceptionAction<List<GarbageCollectorMXBean>>() {                                @Override                                public List<GarbageCollectorMXBean> run() throws DrsException {                                    return ManagementFactory.getGarbageCollectorMXBeans();                                }                            });                } catch (Exception exp) {                    log.error("", exp);                }            }        }    }     public static MemoryMXBean getMemoryMBean() {        if (memoryMBean == null) {            initMemoryMXBean();        }        return memoryMBean;    }     public static List<GarbageCollectorMXBean> getGCMXBeanList() {        if (garbageCollectorMXBeanList == null) {            initGarbageCollectorMXBean();        }        return garbageCollectorMXBeanList;    }     private Map<String, Object> getMemStatus() {        Map<String, Object> memStatus = new HashMap<String, Object>();        // 堆内存        memStatus.put("Heap mem Committed", getMemoryMBean().getHeapMemoryUsage().getCommitted());        memStatus.put("Heap mem Init", getMemoryMBean().getHeapMemoryUsage().getInit());        memStatus.put("Heap mem Max", getMemoryMBean().getHeapMemoryUsage().getMax());        memStatus.put("Heap mem Used", getMemoryMBean().getHeapMemoryUsage().getUsed());        // 堆内存使用率        memStatus.put("Heap mem Used Rato",                (getMemoryMBean().getHeapMemoryUsage().getUsed() * 100 / getMemoryMBean().getHeapMemoryUsage().getMax()) + "%");         // 堆外内存        memStatus.put("Non-Heap mem Committed", getMemoryMBean().getNonHeapMemoryUsage().getCommitted());        memStatus.put("Non-Heap mem Init", getMemoryMBean().getNonHeapMemoryUsage().getInit());        memStatus.put("Non-Heap mem Used", getMemoryMBean().getNonHeapMemoryUsage().getUsed());        return memStatus;    }     private Map<String, Object> getGcStatus() {        Map<String, Object> gcStatus = new HashMap<String, Object>();        if (!CollectionUtils.isEmpty(getGCMXBeanList())) {            // 不同的垃圾回收器            for (GarbageCollectorMXBean gcMXBean : getGCMXBeanList()) {                gcStatus.put(gcMXBean.getName() + "-" + Arrays.toString(gcMXBean.getMemoryPoolNames()) + "-count", gcMXBean.getCollectionCount());                gcStatus.put(gcMXBean.getName() + "-" + Arrays.toString(gcMXBean.getMemoryPoolNames()) + "-time", gcMXBean.getCollectionTime());            }        }        return gcStatus;    }     public void print() {        log.info("jvm mem status: {}", GsonUtils.toJson(getMemStatus()));         log.info("jvm gc status: {}", GsonUtils.toJson(getGcStatus()));    } }运行结果:2020-03-09 08:24:30,001 jvm mem status: {"Non-Heap mem Used":201168408,"Heap mem Used":710231248,"Heap mem Used Rato":"48%","Heap mem Committed":1467482112,"Non-Heap mem Init":2555904,"Non-Heap mem Committed":207945728,"Heap mem Init":1474297856,"Heap mem Max":1467482112}2020-03-09 08:24:30,001 jvm gc status: {"PS Scavenge-[PS Eden Space, PS Survivor Space]-count":210,"PS MarkSweep-[PS Eden Space, PS Survivor Space, PS Old Gen]-time":842,"PS MarkSweep-[PS Eden Space, PS Survivor Space, PS Old Gen]-count":4,"PS Scavenge-[PS Eden Space, PS Survivor Space]-time":2213}使用案例2      有业务功能大量并发,同时占用了大量数据库连接;从而导致连接池中可用连接长时间无空闲的话,就会导致业务持久化操作异常。下面就以使用Druid数据库连接池为例,通过Druid自带的MXbean获取连接池相关信息。PS:      1、多数Java连接池都会注册MXbean并记录重要监控数据,具体实现和数据线略有差别;      2、druid自带monitor;需要配置额外的数据库进行存储,可参见:https://github.com/alibaba/druid/wiki/druid-monitor%E8%AE%BE%E8%AE%A1      通过JMX连接JVM,可以看到DruidDataSource下有两个数据源,他们的ObjectName为:com.alibaba.druid:type=DruidDataSource,id=XXX,每个数据源的MXBean中各有一组Attribute记录相关监控项。实现代码:public class DruidMXBeanTest {     private static volatile MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();     private static void initMBeanServer() {        synchronized (DruidMXBeanTest.class) {            if (mBeanServer == null) {                try {                    mBeanServer = AccessController.doPrivileged(                            new PrivilegedExceptionAction<MBeanServer>() {                                @Override                                public MBeanServer run() throws DrsException {                                    return ManagementFactory.getPlatformMBeanServer();                                }                            });                } catch (Exception exp) {                    log.error("", exp);                }            }        }    }     private static MBeanServer getMBeanServer() {        if (mBeanServer == null) {            initMBeanServer();        }        return mBeanServer;    }     public static Set<ObjectInstance> queryMBeans(String objectName) {        try {            if (getMBeanServer() != null) {                return getMBeanServer().queryMBeans(new ObjectName(objectName), null);            }        } catch (Exception e) {            log.error("", e);        }        return null;    }     public static Map<String, Object> getAttributes(String objectName, List<String> attrNameList) {        try {            return getAttributes(new ObjectName(objectName), attrNameList);        } catch (Exception e) {            log.error("", e);        }        return null;    }     public static Map<String, Object> getAttributes(ObjectName objectName, List<String> attrNameList) {        Map<String, Object> result = new HashMap<String, Object>();        if (CollectionUtils.isEmpty(attrNameList) || getMBeanServer() == null) {            return result;        }        try {            AttributeList attributeList = getMBeanServer().getAttributes(objectName, attrNameList.toArray(new String[] {}));            for (int i = 0; i < attrNameList.size(); i++) {                result.put(attrNameList.get(i), i < attributeList.size() ? ((Attribute) attributeList.get(i)).getValue() : "");            }            return result;        } catch (Exception e) {            log.error("", e);        }        return result;    }     private Map<String, Map<String, Object>> getDruidDataSourceStatus() {        Map<String, Map<String, Object>> druidDataSourceMap = new HashMap<String, Map<String, Object>>();        try {            // 结果数量不固定并且ID每次随机,使用带通配符的ObjectName进行批量查询            Set<ObjectInstance> druidDataSourceSet = queryMBeans("com.alibaba.druid:type=DruidDataSource,id=*");            if (druidDataSourceSet != null) {                 // 一个数据源一组attribute                druidDataSourceSet.stream().forEach(objectInstance -> {                    Map<String, Object> druidDataSource = new HashMap<String, Object>();                     /**                     * 需要获取到的监控项                     *                      * druid更多相关监控项可以在com.alibaba.druid.pool.DruidDataSource中查看(注意使用时需要大写驼峰格式)                     */                    List<String> attrList = new ArrayList<String>() {                        {                            // 数据源用户名                            add("Username");                            // 最大连接池数量                            add("MaxActive");                            // 最小连接池数量                            add("MinIdle");                            // 连接池中空闲连接数                            add("PoolingCount");                            // 连接池中正在使用的连接数                            add("ActiveCount");                        }                    };                    druidDataSource = getAttributes(objectInstance.getObjectName(), attrList);                    druidDataSourceMap.put(String.valueOf(druidDataSource.get("Username")), druidDataSource);                });            }         } catch (Exception e) {            log.error("", e);        }        return druidDataSourceMap;    }     public void print() {        log.info("druid dataSource status: {}", GsonUtils.toJson(getDruidDataSourceStatus()));    }} 运行结果:2020-03-09 08:24:30,002 druid dataSource status: {"db1":{"Username":"db1","MaxActive":20,"MinIdle":5,"ActiveCount":0,"PoolingCount":5},"db2":{"Username":"db2","MaxActive":20,"MinIdle":10,"ActiveCount":1,"PoolingCount":9}}  总结很多开源中间件都会使用Management方式进行自定义扩展,记录相关运行状况数据;例如Kafka、logback等,都可以使用类似方式获取数据。参考资料:https://www.jianshu.com/p/5d854245051dhttps://baike.baidu.com/item/java.lang.management/5179868?fr=aladdinhttp://www.voidcn.com/article/p-cwctaeex-bsq.htmlhttps://zimt8.com/questions/16275207/https://docs.oracle.com/javase/tutorial/jmx/mbeans/mxbeans.htmlhttps://docs.oracle.com/javase/8/docs/api/java/lang/management/package-summary.html
  • 使用Java访问得到301,并且无法redirect
    listFile方法得到异常:com.obs.services.internal.ServiceException: Try to redirect, but location is null!,经过检查,发现服务端返回301,并且header中没有location,得到这个错误的概率大概是30%,请问如何解决呢
  • [分享交流] java 调用smc2.0 调用到认证接口的时候 lineNumber: 1; columnNumber: 1; 文件提前结
    问题   调用 Authenticate方法返回上面的信息  是什么原因  登录方法已经拿到了cookie    问题2  二次SHA256加密的   密码  是什么   问题3  放入cookie  是httpHeaders.put("Set-Cookie",Cookie);   Set-Cookie 还是cookie  
  • [技术干货] ServiceComb CSE Java Chassis 启动失败
    # ServiceComb CSE Java Chassis 启动失败 > 初次使用 **ServiceComb Java Chassis** 框架 启动的时候总是发生报错. ### content held by this instance and the service center is different ![start_error_1.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/10/0041220fhd2ru6cr7ponjc.png) 这个问题一般是对 服务端 **接口** 进行了修改, 造成生成的 **契约** 发生了变化. 有以下处理方式: * 直接升级服务版本号, 修改 **microservice.yaml** 配置文件配置 **service_description.version** , 增加一个小的版本号就好, 例如从 **0.0.1** 升级为 **0.0.2** ![start_error_2.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/10/004138n1whaygnzdqp0ooo.png) * 也可以直接到 **服务中心** , 删除 同版本老的 契约 ![start_error_3.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/10/0041554pjawdaii0ykq67c.png) * 如果既不想升级版本号, 也不想去服务中心删除契约,可以设置 变量 **service_description.environment** 为 **development** ![start_error_4.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/10/004210xltehhhf7xbrdk6m.png) > 如果是生产环境, 确定啥都没改, 就是重启了下实例, 发现报了这个错误. 可以参考帖子 https://bbs.huaweicloud.com/forum/thread-12624-1-1.html ### 服务启动成功, 但是服务中心没找到实例. * 全局搜索关键词 `running microservice register task` 或者 `running microservice instance register task` > 如果找不到, 确定是否配置了 **local.registry.file** . 该参数控制是否使用 **本地服务中心**, 如果这个参数不为空, 就会使用本地服务中心, 而不会往远端服务中心注册. > > 如果有相关注册日志, 可以接着往下排查: * 确定 **servicecomb.service.registry.address** 是否配置的 是目标服务中心 * 确定 服务中心 的 **选中的环境** 是否 和 本服务配置 **service_description.environment** 保持一致. ![start_error_5.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/10/004343pzao1vuseqydj3lg.png) ## Connection timed out > 这里要注意下, 连接配置中心 连接不上也有可能报 **Connection timed out** , 但是配置中心连接失败 不影响服务 启动 和 服务注册. > 看日志要看的细致一点, 如果同行 还有 **registry** 关键字, 那就是 注册的时候发生了 **超时** 注册时 发生超时, 要自己检查 本机 和 服务中心 **是否是连通的** . 如果你说你本地 能 **curl** 同 服务中心, 但是程序确实连不上, 请检查自己代理和网络. > 如何在ServiceComb 配置代理可参考 : https://docs.servicecomb.io/java-chassis/zh_CN/general-development/dai-li-she-zhi/#_1 > > 一般不需要主动配置代理, 程序直接使用系统代理就没问题. 反正我没主动配置过. **连接超时问题, 不要找 ServiceComb 开发人员支撑, ServiceComb 开发不懂网络** ## Must be a concrete type 服务启动失败,报错"[simple type, class xxx] is interface. Must be a concrete type". 详情可查看帖子: https://bbs.huaweicloud.com/forum/thread-50505-1-1.html 报错日志: ```log Exception in thread "main" java.lang.IllegalStateException: ServiceComb init failed. at org.apache.servicecomb.core.SCBEngine.init(SCBEngine.java:231) at org.apache.servicecomb.core.CseApplicationListener.onApplicationEvent(CseApplicationListener.java:81) at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347) at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:883) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93) at org.apache.servicecomb.foundation.common.utils.BeanUtils.init(BeanUtils.java:54) at org.apache.servicecomb.foundation.common.utils.BeanUtils.init(BeanUtils.java:47) at mylearning.servicecomb.ServiceCombConsumerMain.main(ServiceCombConsumerMain.java:23) Caused by: java.lang.Error: generate operation swagger failed, mylearning.servicecomb.service.ThirdPartyService:thirdSayHello at org.apache.servicecomb.swagger.generator.core.SwaggerGenerator.scanMethods(SwaggerGenerator.java:252) at org.apache.servicecomb.swagger.generator.core.SwaggerGenerator.generate(SwaggerGenerator.java:141) at org.apache.servicecomb.core.definition.schema.AbstractSchemaFactory.generateSwagger(AbstractSchemaFactory.java:102) at org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory.createSchema(ProducerSchemaFactory.java:115) at org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory.createSchema(ProducerSchemaFactory.java:54) at org.apache.servicecomb.core.definition.schema.AbstractSchemaFactory.getOrCreateSchema(AbstractSchemaFactory.java:58) at org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory.getOrCreateProducerSchema(ProducerSchemaFactory.java:76) at org.apache.servicecomb.provider.rest.common.RestProducerProvider.init(RestProducerProvider.java:45) at org.apache.servicecomb.core.provider.producer.ProducerProviderManager.init(ProducerProviderManager.java:54) at org.apache.servicecomb.core.SCBEngine.doInit(SCBEngine.java:264) at org.apache.servicecomb.core.SCBEngine.init(SCBEngine.java:219) ... 13 more Caused by: org.apache.servicecomb.foundation.common.exceptions.ServiceCombException: [simple type, class javax.servlet.http.HttpServletResponse] is interface. Must be a concrete type. at org.apache.servicecomb.swagger.extend.ModelResolverExt.checkType(ModelResolverExt.java:119) at org.apache.servicecomb.swagger.extend.ModelResolverExt.resolveProperty(ModelResolverExt.java:151) at io.swagger.jackson.ModelResolver.resolveProperty(ModelResolver.java:125) at io.swagger.converter.ModelConverterContextImpl.resolveProperty(ModelConverterContextImpl.java:83) at io.swagger.converter.ModelConverters.readAsProperty(ModelConverters.java:63) at io.swagger.converter.ModelConverters.readAsProperty(ModelConverters.java:57) at org.apache.servicecomb.swagger.generator.springmvc.processor.parameter.SpringmvcDefaultParameterProcessor.process(SpringmvcDefaultParameterProcessor.java:39) at org.apache.servicecomb.swagger.generator.core.OperationGenerator.scanMethodParameters(OperationGenerator.java:298) at org.apache.servicecomb.swagger.generator.core.OperationGenerator.generate(OperationGenerator.java:181) at org.apache.servicecomb.swagger.generator.core.SwaggerGenerator.scanMethods(SwaggerGenerator.java:248) ... 23 more ``` > 服务报这个错误是由于在接口定义中使用了接口类型的参数。如下面的代码,接口中使用了`HttpServletResponse`。 ```java @RequestMapping(path = "/thirdSayHello", method = RequestMethod.GET) public String thirdSayHello(@RequestParam(name = "name") String name, HttpServletResponse HttpServletResponse) { // invoke 3rd party rest service String response = commonServerIntf.sayHello(name); LOGGER.info("name: {}.", response); return response; } ``` > ServiceComb关于接口定义和数据类型的支持可参考开发者指导[接口定义和数据类型](https://docs.servicecomb.io/java-chassis/zh_CN/build-provider/interface-constraints/)
  • [技术干货] ServiceComb Java Chassis CSE SDK 报错 Connection Refused
    # ServiceComb Java Chassis CSE SDK 报错 Connection Refused > 查看服务的运行日志, 会发现运行是报错 **Connection Refused** ![conn_refused_1.png](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/08/09344356pgdgiywycm3ksj.png) 发送连接, 连接被拒绝, 这种通常是发送请求的时候 服务端实例 **不可用** 了. 一般是发生在如下场景: 1. 服务上下线和升级, 造成实例重启. 在重启期间 会短暂有这种报错 2. 服务实例运行期间, 实例发生重启, 也会造成这种报错. > 发生这种报错, CSE 只有以上简单建议, 无法帮助客户 debug 看日志排查问题. 如果客户可以抽出demo 复现问题, 可以找CSE 支撑人员排查
  • [技术干货] ServiceComb Java SDK 直接调用RPC 服务端
    # RPC Server 端支持使用 POSTMAN 直接调用 > 如果服务端 是使用 Java Chassis **RPC 风格开发的**, 如果想是用 `postman` 等工具直接调用时, 需要根据 swagger 契约查找 调用路径 ### 示例 ```java @RpcSchema(schemaId = "test") @SwaggerDefinition(basePath = "/pojo/rest") public class CodeFirstPojo { public Person sayHello(Person user) { user.setName("hello " + user.getName()); return user; } public String sayHi(String name) { return "hello " + name; } } ``` ### POSTMAN 调用 要想知道调用路径, 需要查看 **契约**. > 契约可以在 `日志` 中查看, 也可以在 `服务中心` 中查找. ```yaml swagger: "2.0" info: version: "1.0.0" title: "swagger definition for org.apache.servicecomb.demo.pojo.server.CodeFirstPojo" x-java-interface: "gen.swagger.CodeFirstPojoIntf" basePath: "/pojo/rest" schemes: - "http" consumes: - "application/json" produces: - "application/json" paths: /sayHello: post: operationId: "sayHello" parameters: - in: "body" name: "user" required: false schema: $ref: "#/definitions/Person" responses: "200": description: "response of 200" schema: $ref: "#/definitions/Person" /sayHi: post: operationId: "sayHi" parameters: - in: "body" name: "name" required: false schema: $ref: "#/definitions/sayHiBody" responses: "200": description: "response of 200" schema: type: "string" definitions: Person: type: "object" properties: name: type: "string" x-java-class: "org.apache.servicecomb.demo.compute.Person" sayHiBody: type: "object" properties: name: type: "string" ``` > 根据 `basePath` 和 `path` 进行拼接. 例如 我想调用 **sayHi()** 请求路径是 `/pojo/rest/sayHi` , 调用方法是 `post` ![rpc_1.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/07/224719zyb4ccgyo9m5ki5m.png) ![rpc_2.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/07/224729b3tkutusxtruwtln.png)
  • [技术干货] ServiceComb Java Chassis 自定义 Handler 链参数传递
    ServiceComb 官方文档地址 https://docs.servicecomb.io/java-chassis/zh_CN/question-and-answer/question_answer/详情在 二 楼
  • [技术干货] ServiceComb Java Chassis SDK 设置自定义 rest 接口的 http status code
    # ServiceComb Java Chassis 如何自定义 rest 接口的 http status code 在使用 Java Chassis的时候, 有时我们需要自定义 调用返回的 状态码. 详情可参考 **[ServiceComb官方文档](https://docs.servicecomb.io/java-chassis/zh_CN/question-and-answer/faq/)** > 官方文档地址 : https://docs.servicecomb.io/java-chassis/zh_CN/question-and-answer/faq/ ### 设置正常调用自定义 HTTP 状态码 ```java @GetMapping("/userDefinedCode") public String userDefinedCode(@RequestParam(value = "code") int code) { InvocationContext invocationContext = ContextUtils.getInvocationContext(); invocationContext.setStatus(code); return "Set response code : " + code; } ``` ![statusCode_1.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/06/153620degjvtizkn0i5tdq.png) ### 设置异常调用 HTTP 状态码 ```java @GetMapping("/throwException") public String testThrowException(@RequestParam(value = "code") int code) { InvocationContext invocationContext = ContextUtils.getInvocationContext(); throwException(code); return "Throw exception with status code :" + code; } public String throwException(int code) { if (code == 200) { return "Success with status code: 200"; } throw new InvocationException(code, "test exception code", "user defined error code"); } ``` ![statusCode_2.PNG](https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/attachment/forum/202004/06/153639msjpqdew1bnml0am.png)
  • [技术研讨] smc2.0用的什么什么语言呢?是java么,还是其他的
    smc2.0的系统用的什么什么开发语言呢?是java么,还是其他的
  • [交流吐槽] CodeLab-我要领奖-13590440714@139.com
    APP Engine平台“拖拉拽”模式开发看起来比较方便,但个人认为如果对系统理解不深,开发就会显得举步维艰。有的东西当你不知道它在哪里,但是你又不得不需要它才能实现功能,你与它的距离就会是“世界上最遥远的距离”,当你知道了它的存在,你就会觉得如此简单。学习这个系统还需要的就是转换思维,对于传统java程序员来说,很难理解和适应它背后的逻辑,因为当你做java开发的时候,你会很清楚自己的数据是如何变化,如何传递,但是当用到这个系统的时候,你就会觉得心里不踏实,很多东西别人实现了,可是你很大可能摸不透别人是如何实现的,不能从中学习到别人的思维方式,从而提高拓宽自己的思维方式,这会限制到你自己。相对来说,“拖拉拽”式开发一定是未来的趋势,希望公司在完善IDE系统的同时,同时丰富它的生态,租户可以将已有的优秀组件下载下来作为该租户的可研究组件,该租户可以修改编辑该组件来看背后具体的逻辑。对于优秀的组件应当通过技术社区进行细致的设计思路步骤分享,达到共同提高的目的。
  • [技术干货] 【深圳HDZ】王松-Spring Boot要么学?要不要先学 SSM?
          可能很多刚接触 Spring Boot 的小伙伴都会有这样的疑问,Spring Boot 要怎么学,要不要先学 SSM?今天结合自己的经验,和大家说一说我的看法,也顺便推荐几个 Spring Boot 学习资料。 1.Spring Boot 是什么       我们刚开始学习 JavaWeb 的时候,使用 Servlet/JSP 做开发,一个接口搞一个 Servlet ,很头大,后来我们通过隐藏域或者反射等方式,可以减少 Servlet 的创建,但是依然不方便。      再后来,我们引入 Struts2/SpringMVC 这一类的框架,来简化我们的开发 ,和 Servlet/JSP 相比,引入框架之后,生产力确实提高了不少,但是用久了,又发现了新的问题,即配置繁琐易出错,要做一个新项目,先搭建环境,环境搭建来搭建去,就是那几行配置,不同的项目,可能就是包不同,其他大部分的配置都是一样的。      Java 总是被人诟病配置繁琐代码量巨大,这就是其中一个表现。那么怎么办?Spring Boot 应运而生,Spring Boot 是 Pivotal 团队在 2013 年开始研发的一个基于 Spring 的全新框架,试图将 Spring 中臃肿的配置进行简化,使 Java 开发更加轻量与快速,这个框架非常活跃,官方也非常重视。 Spring Boot 主要提供了如下功能:1. 为所有基于 Spring 的 Java 开发提供方便快捷的入门体验。2. 开箱即用,有自己自定义的配置就是用自己的,没有就使用官方提供的默认的。3. 提供了一系列通用的非功能性的功能,例如嵌入式服务器、安全管理、健康检测等。4. 绝对没有代码生成,也不需要XML配置。      Spring Boot 的出现让 Java 开发又回归简单,因为确确实实解决了开发中的痛点,因此这个技术得到了非常广泛的使用,大概从 2017 年年初开始,Spring Boot 基本上面试必问,现在流行的 Spring Cloud 微服务也是基于 Spring Boot,因此,所有的 Java 工程师都有必要掌握好 Spring Boot。从 Spring Boot 诞生的过程中,我们可以看到:1. Spring Boot 并非另起炉灶,而是在现有的 Spring 框架的基础上整出来的,它把 Spring 中繁琐的配置进行了简化。2. Spring Boot 降低了 Spring 家族的使用门槛,使新手更易上手 Spring 框架。      既然 Spring Boot 不是另起炉灶,那么 Spring Boot 学习要不要跳过 SSM 呢?听松哥来分析。 2.要不要跳过 SSM      这是很多人问我的一个问题,我的建议是:【不要】。      Spring Boot 基于 Spring,简单且容易上手,很多人想当然的跳过 SSM 直接上 Spring Boot。但是当我们细究 Spring Boot 中的自动化配置、条件注解、Java 配置等东西时,实在找不出太多新鲜玩意,Java 配置是 Spring3 开始提供的,条件注解 也是 Spring 中的东西,很多很多,都是 Spring 中就有的,只不过这些东西在 Spring Boot 时代大放异彩。      也就是说,即使你跳过了 SSM 直接去学习 Spring Boot,实际上还是在学习 Spring 中的东西,那既然这样,我们还不如坐下来,老老实实把 Spring 过一遍。      各个领域的开发工程师其实都会面临类似的问题,学习了一些优秀的封装框架之后,还有没有必要去学习底层?当然有必要!因为底层的东西可以让你深刻的理解你目前用的这个东西,也能让你在出问题时快速解决掉问题。      其实无论你想搞什么技术,都要有牢固的基础知识,这些牢固的基础知识就像肥沃的土壤,可以孕育出各种不同技术方向的牛人,基础掌握好了,学什么框架都快。今天你跳过 SSM 直接学了 Spring Boot,假如有一天 Spring Boot 不行了,Pivotal 团队又基于 Spring 框架搞了一个新的框架出来,那你是不是又要去学一遍?但是如果你一开始就掌握了 Spring 的各种用法,无论基于它搞出来什么样的框架,你都能快速上手。更进一步,如果你研究透了 Spring 中的 AOP、Ioc/DI,你会发现很多框架大同小异,核心思想就是这些东西,那么你在学习 Spring 之外的框架,就会容易很多。      **如果你对 SSM 还不太熟悉的话,可以在松哥公号(江南一点雨)后台分别回复 `spring`、`springmvc`、`mybatis` 获取松哥手敲 5 万余字的干货教程。** 3.都要学哪些       那么 Spring Boot 学习都要学哪些东西呢?我这里列举了一个进阶路线:1. 最基础的当然是 Spring/SpringMVC 相关的东西了。2. 搭配各种页面模版的使用,例如 Jsp/Thymeleaf/Freemarker/Groovy Templates 等。3. 和各种 SQL 数据库的整合,以及一些常见的数据持久化框架,例如 JdbcTemplate、MyBatis、Jpa 等。4. 和各种 NoSQL 数据库的整合,例如 Redis、MongoDB、Elasticsearch 等。5. 搭配安全管理相关的知识点,例如 Spring Security、Shiro 等。6. 缓存的使用,例如 JCache、Ehcache 等。7. 和消息中间件的搭配整合,如 ActiveMQ、RabbitMQ、Kafka 等。8. 数据校验/定时任务/邮件发送等。9. 各种监控的使用。10. 结合 WebSocket 的使用。11. Spring Cloud 中相关组件。12. ...      上面这些只是我列出来的一些比较常见的技术点,每个技术点都还可以延伸出很多其他的东西,大家可以结合自己的情况,按照顺序一个一个来学,这里边还涉及到很多第三方的框架,例如 Redis、MongoDB、RabbitMQ 等,Spring Boot 的出现只是让这些组件在和 Spring 家族的产品整合时变得更加方便,但是并不会简化这些组件原本的用法,所以,该学 Redis、该学 MongoDB、该学 RabbitMQ 等等,还是一个不能少。以 Redis 为例,学会了 Redis,学会了 Spring 整合 Redis,再回过头来看 Spring Boot 整合 Redis,那简直太 easy 了(**大家在公众号后台回复 redis,有松哥手敲的 redis 教程**)。      当然,学习 Spring Boot 最终我们还是奔着快速开发和微服务去的,所以,像 Docker、Spring Cloud 等技术,也是需要去了解一下的。 4.怎么学       Spring Boot 发展到今天,网上的资料和图书现在是越来越多了。在看资料学习的同时,大家也要留意以下几个点:1. 多看源码。不同于其他全新的框架源码你可能会看懵了,由于 Spring Boot 是基于 Spring 的,所以只要你 Spring 基础扎实,看 Spring Boot 源码可以说是毫无压力。如果看 Spring Boot 源码觉得有压力,那可能你 Spring 基础不牢靠,这个时候不妨放下 Spring Boot,去复习下 Spring。2. 每当学会 Spring Boot 中的一个知识点,不妨想想这个功能在 Spring 框架中要如何使用,如何配置,两边都搞懂了,互相印证,加深对一个知识点的理解。3. 多多关注 Spring Boot 的发展动态。不同于传统的框架可能一年更新一两次,Spring Boot 更新非常频繁,二次每次更新都会带来一些好玩的东西,可能会有新的 API 加入进来,也可能会有旧的 API 失效,变化大,因此多多关注,避免掉坑。      最后,我这里给大家列举几个我自己经常关注的几个资源。 4.1 官方文档       老实说,Spring Boot 的官方文档是我接触的所有官方文档中最条理清晰浅显易懂的,大家做开发,多多少少都接触过一些第三方的开放平台,很多平台的文档真是让人忍不住想吐槽,框架都做出来了,认认真真写个文档有那么难么?      不过 Spring Boot 的官方文档可以算是非常非常友好了。虽然是英文的,但是实际上对英文要求并不高,连读带猜,其实很容易明白它的含义,我一般对 Spring Boot 中某个知识点有疑问的时候,都是首选官方文档,当前最新版的官方文档地址是:- https://docs.spring.io/spring-boot/docs/2.2.4.RELEASE/reference/html      当然,如果你嫌官方文档打开慢,松哥也帮你下载好了最新版的 pdf,公众号后台回复 `springboot2.2.4` 可以获取。 4.2 Spring 官方博客       每次 Spring 或者 Spring Boot 发新版本,松哥都会去看一下新版本有哪些好玩的东西,增加了哪些内容。我不可能把源码读一遍然后总结出来它的变化,那一般是如何获取权威的第一手信息呢?关注 Spring 官方博客即可。      打开 Spring 官网,在顶部菜单里有一个选项就是 Blog,关于 Spring 家族产品的任何更新计划,更新结果,都会在这里通知到大家。             松哥也推荐大家多多关注这个 Blog,一方面能够及时接收到一手信息,另一方面还能提高英语,一举两得。宅在家,泡一壶茶,细细的品一品这个网站,真的蛮不错。      Blog 地址:- https://spring.io/blog  4.3 中文资料       说到中文资料,就不得不说松哥自己的在线教程和离线 pdf 文档了。手敲了 274 页教程,囊括了 Spring Boot2 常见的各种用法,即有离线的 pdf 供大家下载,也有在线的学习网站,这就是满满的诚意,还没下载 pdf 的小伙伴不要错过。       在线教程地址:- http://springboot.javaboy.org      离线 pdf 下载文档,在公众号后台回复 springboot 获取百度网盘地址。 4.4 学习案例       除了这些文字性的东西之外,一些在线案例也至关重要。这里给大家推荐两个仓库,这两个仓库中的所有案例都是基于 Spring Boot2 来做的。      首先就是我公众号上文章的配套案例:      GitHub 地址:https://github.com/lenve/javaboy-code-samples      Gitee 地址:https://gitee.com/lenve/javaboy-code-samples      这个仓库中的大部分案例都是针对 Spring Boot 的,而且有一个好处就是这些案例都有对应的讲解文章,每个案例都对应一个文章,岂不美哉。       另一个仓库就是我整理的比较完善的一个仓库,但是就没有对应的讲解文章了:      GitHub 地址:https://github.com/lenve/javaboy-video-samples      Gitee 地址:https://gitee.com/lenve/javaboy-video-samples 5.小结       资料贵精不贵多,关键是要动手去学。大学时候,有的同学热衷于收集各种资料,电脑硬盘塞得满满的,但是就是不学,这些资料再多也没有用。      当然,如果大家对松哥自己录制的 Spring Boot+Vue+微人事+Spring Cloud 视频教程感兴趣,也可以看看这篇文章:[Spring Boot + Vue 视频教程喜迎大结局,西交大的老师竟然都要来一套!](https://mp.weixin.qq.com/s/8FmgtWyz6HUIbF4smXQOwQ),或者加下面的微信咨询。关于作者   王松,江湖人称“松哥”出书《Spring Boot +Vue全栈开发实战》,清华大学出版社个人公众号:“江南一点雨”,2019年产出117篇原创技术干货,包含“Spring Boot系列”、“前后端分离系列”、“系列教程等”联系作者添加好友时麻烦请备注来源、公司及名称,谢谢HDZ社区—携手全球开发者 共建开放、创新、多元的开发者社区组织       HDZ是Huawei Developers Zone的英文缩写,是华为开发者生态面向全球开发者建立开放、创新、多元的开发者社区组织。      致力于帮助开发者学习提升、互动交流、挖掘机会,推动ICT、互联网等产业生态的建立和发展。      对云计算、IoT、人工智能、5G、区块链、鲲鹏、昇腾、软件开发与运维、开源等各技术领域感兴趣的开发者、软件工程师、创业者、运营人、产品人、大学生、老师等都可以参与到HDZ。      HDZ秉承开放、创新、多元的社区文化,完全由各地HDZ组织者、志愿者自发组建和领导。华为公司不直接参与HDZ组织建设和领导,只按需对HDZ社区活动提供必要的方向指导、资源支持、活动支撑等,并为各地HDZ组织者提供与全国组织者互动交流的机会。
  • [热门活动] 【招人啦!!!】急聘Web前端开发/Java软件开发/移动客户端开发工程师,欢迎加入华为云官网团队!
    有需要的小伙伴请联系邮箱地址:weihualv@huawei.com
  • [问题求助] 北向如何用Java API Demo启动一个本地应用服务器来接收平台推送的消息
    在平台订阅已经用公网地址订阅成功,苦于无法在本地服务器接收平台推送的消息,求助各位大神,这样的接口应该怎么写
总条数:2294 到第 页
上滑加载中