网站建设 10万元,网站项目分析怎么做 方法有哪些,办公室装修报价表,手机电脑网站建设标签#xff1a; gblfy技术文档 文章目录六、 git核心概念6.1. git学习地址6.2. github和码云的介绍6.3. git常用命令和操作6.3.1. 命令行常用命令6.3. IDEA操作方法(具体看视频)6.3.1. 合并分支6.3.2. compare with6.3.3. rename6.3.4. 看历史记录#xff08;所有的和单个文…标签 gblfy技术文档
文章目录六、 git核心概念6.1. git学习地址6.2. github和码云的介绍6.3. git常用命令和操作6.3.1. 命令行常用命令6.3. IDEA操作方法(具体看视频)6.3.1. 合并分支6.3.2. compare with6.3.3. rename6.3.4. 看历史记录所有的和单个文件的6.3.5. revert 6.stash6.3.7. cherry pick6.3.8. reset curent branch6.4 git技巧6.4.1. 分支用法实战6.4.2. 解决冲突6.4.3. rebase6.4.4. bug修复流程6.4.4.1. 暂存手头工作如果有没完成的工作的话6.4.4.2. 新建bugfix分支6.4.4.3. 测试bug是否修复完成6.4.4.4. 合并分支6.4.4.5. 继续进行之前手头上的工作6.5 maven知识点6.5.1. 仓库的概念6.5.2. pom详解6.5.3. maven命令6.5.4. 继承6.5.5. 聚合6.5.6. 依赖冲突6.5.7. SNAPSHOT6.6 maven搭建多模块项目6.6.1. 建立父模块6.6.2. 整合两个子模块6.6.3. 模块A依赖模块B6.7. spring boot核心原理6.7.1. 自动配置6.7.2. 起步依赖6.8. 简洁代码6.8.1. 规范统一的类和方法注释6.8.2. 逻辑的注释6.9. 组织包结构6.9.1. config包6.9.2. core包6.9.3. modular包6.10. 常量和枚举6.10.1. 常量6.10.2. 枚举6.11. 接口和抽象类6.11.1. 接口多用在制定规范6.11.2. 抽象类多用在封装六、 git核心概念
6.1. git学习地址
git是开发所需要必备的非常重要的基础技能 https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
6.2. github和码云的介绍
watchstar和fork的作用详情见视频
6.3. git常用命令和操作
6.3.1. 命令行常用命令
# 克隆仓库
git clone xxx# 查看当前状态
git status# 新建分支
git checkout -b dev# 切换分支
git checkout dev# 拉取代码
git pull
git pull origin master:master# 提交代码
git push origin master# 打tag
git tag -a v1.0 -m 正式发布1.0# stash
git stash# unstash
git stash pop6.3. IDEA操作方法(具体看视频)
6.3.1. 合并分支
6.3.2. compare with
6.3.3. rename
6.3.4. 看历史记录所有的和单个文件的
6.3.5. revert 6.stash
6.3.7. cherry pick
6.3.8. reset curent branch
6.4 git技巧
6.4.1. 分支用法实战
master分支上线用跟线上代码保持一致。 dev分支开发分支开发人员写完提到本分支。 test分支相对稳定的分支供上线前的测试。 feature分支开发部分功能用的分支。 bug分支修复线上bug用。 分支的作用一方面分支的建立可以让并行开发互不影响另一方面分支的建立可以让代码保留多种状态。
6.4.2. 解决冲突
冲突产生于合并代码拉取远程代码的时候会经常遇到。 产生冲突的时候建议用IDEA解决很智能很方便如果你不用IDEA开发同样的我建议你用IDEA开发感觉比Eclipse好些。 为了解决冲突时不会丢失你自己写的本地代码不要先pull代码再去提交代码每次要先commit你的代码再去pull代码再去解决冲突。这和svn不一样svn是以一个文件为一个提交单位git是以一整个commit为一个提交单位。
合并时候重点是比对你和别人代码冲突的部分如果你不确定该用谁的代码一定要询问和你代码冲突部分是谁写的你们商量一下或者直接请示你的项目负责人。
在idea中出现冲突会提示如下
解决冲突过程如下 6.4.3. rebase
merge和rebase都可以理解为合并的意思merge合并之后会产生新的提交记录rebase不会产生新的记录而是把所有两个分支的提交归并为一条线上。
在拉取代码的时候我们一般选rebase如下 但是在合并代码的时候我们选merge为了体现合并的过程合并代码的时候我们一般用–no-ff模式禁用fast-forward模式并加上注释-m
git merge dev --no-ff -m 合并dev到test增加修改人员接口修复多个bug完善查看订单功能xxxxxxx6.4.4. bug修复流程
如果生产环境出现bug若不是很紧急可以在dev分支开发等下次上线一起发布如果bug需要紧急修复请按以下步骤进行
6.4.4.1. 暂存手头工作如果有没完成的工作的话
如果手头有没写完的代码并且不能提交提交后可能影响别人开发那么可以把这些没写完的代码进行暂存git stash等修复完bug之后再恢复这些代码git stash pop如果用的IDEA可以选择如下选项
然后填入备注信息
6.4.4.2. 新建bugfix分支
stash完之后切换到master分支master为线上的代码在master分支新建一个bugfix分支例如订单详情有个bug需要修复
image_1d2puvmr714d959e1lem1chkisp13.png-25.2kB
之后在此分支修复bug改完后可不提交到远程仓库如果多人协作修改这个bug需要提交到远程分支。
6.4.4.3. 测试bug是否修复完成
代码写完之后本地进行测试也可以在jenkins上发布到test环境测试一下确保bug修复完毕并且没有影响到其他业务运行。
6.4.4.4. 合并分支
合并刚才创建的bugfix_order_detail分支到master分支并打标签如下
git merge bugfix_order_detail --no-ff -m 合并bugfix_order_detail到master修复了订单详情显示的问题上线成功后可删除掉本地的bugfix_order_detail分支。
6.4.4.5. 继续进行之前手头上的工作
恢复暂存的代码如下 或者直接用命令
git stash pop6.5 maven知识点
6.5.1. 仓库的概念
本地仓库 本地存放jar包的地方默认存放路径在路径名为
.m2/respository/,可以再settings.xml中配置。 中央仓库 Maven 中央仓库是由 Maven 社区提供的仓库其中包含了大量常用的库。中央仓库包含了绝大多数流行的开源Java构件以及源码、作者信息、SCM、信息、许可证信息等。一般来说简单的Java项目依赖的构件都可以在这里下载到。 nexus私服 开发人员自己定制仓库包含了所需要的代码库或者其他工程中用到的 jar 文件。一般公司都会搭建一个自己的私服加快jar包下载速度也可以deploy公司内部的jar包。
6.5.2. pom详解
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd!-- 父项目坐标 --parent!--被继承的父项目的构件标识符 --artifactId /!--被继承的父项目的全球唯一标识符 --groupId /!--被继承的父项目的版本 --version /!-- 父项目的pom.xml文件的相对路径 --relativePath //parent!--项目的全球唯一标识符通常使用全限定的包名区分该项目和其他项目。 --groupIdasia.banseon/groupId!-- 构件的标识符它和group ID一起唯一标识一个构件 --artifactIdbanseon-maven2/artifactId!--项目产生的构件类型jar、war、pom。 --packagingjar/packaging!--项目当前版本格式为:主版本.次版本.增量版本-限定版本号 --version1.0-SNAPSHOT/version!--项目的名称, Maven产生的文档用 --namebanseon-maven/name!-- 项目的详细描述, Maven 产生的文档用. --descriptionA maven project to study maven./description!-- 项目内的一些常量 --propertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingproject.reporting.outputEncodingUTF-8/project.reporting.outputEncodingjava.version1.8/java.versionjwt.version0.9.0/jwt.version/properties!-- 项目的依赖管理 --dependencyManagementdependencies/dependencies/dependencyManagement!-- 项目的依赖 --dependenciesdependencygroupIdcn.stylefeng.roses/groupIdartifactIdkernel-core/artifactIdversion1.1.0/version!-- 排除依赖 --exclusionsexclusionartifactIdslf4j-api/artifactIdgroupIdorg.slf4j/groupId/exclusion/exclusions/dependency/dependencies!-- 项目构建配置 --build!-- 插件 --pluginsplugingroupIdorg.apache.maven.plugins/groupIdartifactIdmaven-compiler-plugin/artifactIdversion3.7.0/versionconfigurationsource1.8/sourcetarget1.8/target/configuration/plugin/plugins!-- 资源文件夹 --resourcesresourcedirectorysrc/main/resources/directory/resourceresourcedirectorysrc/main/java/directoryincludesinclude**/*.xml/include/includes/resource/resources/build!-- 不同环境构建参数 --profilesprofileidlocal/idpropertiesspring.activelocal/spring.active/propertiesactivationactiveByDefaulttrue/activeByDefault/activation/profileprofileiddev/idpropertiesspring.activedev/spring.active/properties/profile/profiles/project6.5.3. maven命令
# 1. 清除工作空间编译的文件
mvn clean# 2. 编译并打包
mvn package# 3. 编译打包构建到本地仓库
mvn install# 4. 发布到远程仓库
mvn deploy# 5. 跳过测试
-Dmaven.test.skiptrue6.5.4. 继承
子maven模块可以继承父maven模块的一些属性。子模块可以用如下一段配置来继承某个父模块。
parent groupIdcom.xxx/groupIdartifactIdparent-project/artifactIdversion0.0.1-SNAPSHOT/versionrelativePath../pom.xml/relativePath
/parent6.5.5. 聚合
父模块可以用如下一段配置来聚合多个子模块以便在clean和package等命令时自动帮我们执行父子模块的操作。一般父模块的packaging属性为pom。
modulesmodulemoduleA/module modulemoduleB/module modulemoduleC/module
/modules6.5.6. 依赖冲突
Maven采用最近获胜策略的方式处理依赖冲突。如下图resolev-web会依赖project-
解决方法 第一种显式加入对project-common 2.0版本的依赖。
dependency groupIdproject-common/groupId artifactIdproject-commmon/artifactId version2.0/version
/dependency第二种resolve-web对project-A的dependency声明中将project-common排除掉。
dependency groupIdproject-A/groupId artifactIdproject-A/artifactId version1.0/version exclusions exclusion groupIdproject-common/groupId artifactIdproject-commmon/artifactId /exclusion /exclusions
/dependency6.5.7. SNAPSHOT
在框架持续开发期间如果该框架被多个项目依赖每次升级一个版本都要通知被调用的人版本升级给调用者会带来极大的不便采用SNAPSHOT可以避免此问题。
正式版本和快照版本的主要区别在于本地获取这些依赖的机制有所不同。假设你依赖一个库的正式版本构建的时候构建工具会先在本次仓库中查找是否已经有了这个依赖库如果没有的话才会去远程仓库中去拉取。
快照版本会每隔一定时间去远程仓库拉去看有没有更新的变化。频率共有四种分别是always、daily、interval分钟为单位、never跟正式版本一样。
repositoriesrepositoryidxxx/idurlxxx/urlsnapshotsenabledtrue/enabledupdatePolicyalways/updatePolicy/snapshots/repository
/repositories6.6 maven搭建多模块项目
6.6.1. 建立父模块
packing改为pom增加modules标签
6.6.2. 整合两个子模块
将子模块的parent设置为父模块的坐标信息相关的version可根据继承减少依赖。
6.6.3. 模块A依赖模块B
如果模块之间需要引用直接加入对方模块坐标即可
6.7. spring boot核心原理
推荐一本系统讲解spring boot的书籍《Spring Boot实战》Craig Walls著
6.7.1. 自动配置
针对很多spring应用程序常见的应用功能spring boot能自动提供相关配置。
如何覆盖自动配置
6.7.2. 起步依赖
告诉spring boot需要什么功能他就能引入需要的库。
6.8. 简洁代码
6.8.1. 规范统一的类和方法注释
/*** 修改用户状态返回修改生效的行数** param userId 用户id* param status 用户的状态* return 被修改的行数* author fengshuonan* Date 2019/2/24 21:34*/int setStatus(Param(userId) Long userId, Param(status) String status);/*** 跳转到角色列表页面** author fengshuonan* Date 2018/12/23 6:30 PM*/
RequestMapping()
public String index() {return PREFIX /role.html;
}6.8.2. 逻辑的注释
//如果开启了记住我功能
if (on.equals(remember)) {token.setRememberMe(true);
} else {token.setRememberMe(false);
}//执行shiro登录操作
currentUser.login(token);//登录成功记录登录日志
ShiroUser shiroUser ShiroKit.getUserNotNull();
LogManager.me().executeLog(LogTaskFactory.loginLog(shiroUser.getId(), getIp()));6.9. 组织包结构
在日常开发中业务模块的包结构划分一般划分为三个config、core、modular
6.9.1. config包
config包存放整个模块的配置类因为项目基于spring boot开发大部分的spring配置都换成了java bean方式的配置所以单独分一个包来存放配置config包中除了存放配置类还有一些以Properties结尾的类这些类的作用是启动应用的时候把application.yml中的配置映射到类的属性上
6.9.2. core包
core包存放当前模块所运行的一些核心机制例如全局的异常拦截器日志AOP权限的AOP项目初始化后的监听器工具类等还可以存放一些对某些框架的扩展例如对beetl模板的扩展配置和工具类对flowable的扩展类shiro的一些拓展类等等
6.9.3. modular包
modular存放按业务划分的业务代码若本模块中包含多个模块业务则在modular中建立多个业务包在具体的业务包下再建立controller、entity、service、factory、mapper、model、service、wrapper这几个包如果当前模块中只存在一类业务那么没有必要在modular包下再建立多个业务模块可直接在modular模块建立controller、entity、service等等
这样拆分的好处在于把业务配置和运行机制清晰的拆分开提高项目的可维护性加快项目的开发效率!
6.10. 常量和枚举
目的更优雅的写出代码避免出现魔法值。
6.10.1. 常量 代码中的固定值一般用public static final标识 常用在某种标识上比如说缓存前缀标识系统环境常量等 表现的形势一般分两种
public class DefaultSystem {public static final String DEFAULT_PWD 111111;
}
public interface DefaultSystem {String DEFAULT_PWD 111111;
}6.10.2. 枚举
一般用在状态和类型等这样具有可列举的项时使用。
//第一种
public enum Color { RED, GREEN, BLANK, YELLOW
}//第二种
public enum ManagerStatus {OK(ENABLE, 启用), FREEZED(LOCKED, 冻结), DELETED(DELETED, 被删除);String code;String message;ManagerStatus(String code, String message) {this.code code;this.message message;}public static String getDescription(String value) {...}
}//第三种
public enum BizExceptionEnum implements AbstractBaseExceptionEnum {TOKEN_EXPIRED(700, token过期),TOKEN_ERROR(700, token验证失败);...Overridepublic Integer getCode() {return code;}Overridepublic String getMessage() {return message;}
}6.11. 接口和抽象类
6.11.1. 接口多用在制定规范 1.Feign远程接口使用接口 RequestMapping(/api/dict)
public interface DictApi {RequestMapping(value /addDict, method RequestMethod.POST)void addDict(RequestBody Dict dict);RequestMapping(value /updateDict, method RequestMethod.POST)void updateDict(RequestBody Dict dict);RequestMapping(value /deleteDict, method RequestMethod.POST)void deleteDict(RequestParam(dictId) Long dictId);
}2.作为方法参数用一个接口接收不同子类 public interface AbstractBaseExceptionEnum {/*** 获取异常的状态码*/Integer getCode();/*** 获取异常的提示信息*/String getMessage();
}3.为了拓展写不同的实现切换时减少代码修改量 public interface SmsManager {/*** 发送短信** param phoneNumber 电话号码* param templateCode 模板号码* param params 模板里参数的集合* author fengshuonan* Date 2018/7/6 下午2:32*/void sendSms(String phoneNumber, String templateCode, MapString, Object params);}有需要拓展的地方预判是否需要接口。
6.11.2. 抽象类多用在封装 1.封装模板代码模板方法模式里常用 public abstract class AbstractTreeBuildFactoryT {/*** 树节点构建整体过程** author fengshuonan* Date 2018/7/26 上午9:45*/public ListT doTreeBuild(ListT nodes) {//构建之前的节点处理工作ListT readyToBuild beforeBuild(nodes);//具体构建的过程ListT builded executeBuilding(readyToBuild);//构建之后的处理工作return afterBuild(builded);}/*** 构建之前的处理工作** author fengshuonan* Date 2018/7/26 上午10:10*/protected abstract ListT beforeBuild(ListT nodes);/*** 具体的构建过程** author fengshuonan* Date 2018/7/26 上午10:11*/protected abstract ListT executeBuilding(ListT nodes);/*** 构建之后的处理工作** author fengshuonan* Date 2018/7/26 上午10:11*/protected abstract ListT afterBuild(ListT nodes);
}2.封装核心算法到抽象类子类只需继承并编写一小部分逻辑实现整个类功能 public abstract class BaseControllerWrapper {...SuppressWarnings(unchecked)public T T wrap() {/*** 包装结果*/if (single ! null) {wrapTheMap(single);}if (multi ! null) {for (MapString, Object map : multi) {wrapTheMap(map);}}/*** 根据请求的参数响应*/if (page ! null) {return (T) page;}if (pageResult ! null) {return (T) pageResult;}if (single ! null) {return (T) single;}if (multi ! null) {return (T) multi;}return null;}protected abstract void wrapTheMap(MapString, Object map);
}5.5 业务异常
场景 试着想象一下下面的场景
例如一个下单逻辑首先经过Controller之后Controller调用了AServiceAservice调用了BServiceBservice调用了CService
经过了这4层的业务逻辑后在CService的代码里有个判断如下
if(用户余额 0){ 直接返回这个“用户余额”为0的消息给前端 } 常规的方法CService返回给BServiceB返回给AA返回给控制器
那么有没有更方便的方法
有的那就是用自定义异常
如何使用 首先创建一个属于系统的自定义异常
/*** 业务异常的封装** author fengshuonan* date 2016年11月12日 下午5:05:10*/
public class ServiceException extends RuntimeException {private Integer code;private String errorMessage;public ServiceException(Integer code, String errorMessage) {super(errorMessage);this.code code;this.errorMessage errorMessage;}public ServiceException(AbstractBaseExceptionEnum exception) {super(exception.getMessage());this.code exception.getCode();this.errorMessage exception.getMessage();}...
}那么如何使用在程序的控制器层service层都可以抛出异常
//判断当前用户id不是超级管理员的用户id一言不合就抛出异常 if (userId.equals(Const.ADMIN_ID)) { throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN); } 如果程序制定到这个逻辑判断成立的话看一下前端接收到内容是啥
{ “code”:600, “data”:, “exceptionClazz”:, “message”:“不能删除超级管理员”, “success”:false } 疑问在哪里拦截的异常
统一拦截异常 全局统一拦截的异常cn.stylefeng.guns.core.aop.GlobalExceptionHandler
ControllerAdvice控制器加强
ExceptionHandler(ServiceException.class)拦截制定参数的异常拦截到之后执行方法内的逻辑
ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)返回前端的http状态码
整体写法跟spring mvc的控制器很相似
ControllerAdvice Order(-1) public class GlobalExceptionHandler {
/*** 拦截业务异常*/
ExceptionHandler(ServiceException.class)
ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
ResponseBody
public ErrorResponseData bussiness(ServiceException e) {return new ErrorResponseData(e.getCode(), e.getMessage());
}...} 6.1 项目导入和运行 1.项目导入 登录https://gitee.com/stylefeng/roses找到子项目地址 image.png-48.6kB
可fork之后clone也可直接下载zip包 image.png-86kB
之后打开idea点open选择下载的项目即可 image.png-16.5kB
2.项目的运行 导入完所有项目后可按如下步骤启动各个组件
启动roses-config-server配置中心 启动roses-cloud-register注册中心 启动roses-spring-boot-admin监控中心 启动roses-system系统管理基础服务 启动roses-gateway网关
3.如何修改roses-kernel核心框架 如果公司业务的开发需要涉及到框架的修改则可以导入roses-kernel项目然后修改升级版本mvn install到本地仓库或者公司的私服推荐即可。
6.2 快速开发微服务 1.服务提供者 在roses-system开发一个provider作为服务提供者。
1.编写api
/** 示例服务 author fengshuonan Date 2019/3/7 8:17 PM */ RequestMapping(/api/example) public interface ExampleSysApi { /** 测试远程接口author fengshuonanDate 2019/3/7 8:17 PM */ RequestMapping(value “/test1”, method RequestMethod.POST) ResponseData test1(RequestParam(“param”) String param);
} 2.编写provider
/*** 测试提供者** author fengshuonan* Date 2019/3/7 8:18 PM*/
RestController
public class ExampleSysProvider implements ExampleSysApi {Autowiredprivate SysUserService sysUserService;Overridepublic ResponseData test1(String param) {ListSysUser list sysUserService.list();return ResponseData.success(list);}
}2.服务消费者 1.引入openfeign包 org.springframework.cloud spring-cloud-starter-openfeign 2.启动类增加注解
EnableFeignClients
EnableDiscoveryClient
3.配置eureka注册地址eureka:instance:prefer-ip-address: truelease-expiration-duration-in-seconds: 20 lease-renewal-interval-in-seconds: 5 client:service-url:defaultZone: http://127.0.0.1:8761/eurekaregistry-fetch-interval-seconds: 10 4.编写消费者接口
/*** 测试服务消费者** author fengshuonan* date 2018-08-07-下午3:12*/
FeignClient(roses-system)
public interface ExampleServiceConsumer extends ExampleSysApi {}5.注入消费者调用接口编写测试
/*** 网关服务** author fengshuonan* Date 2017/11/10 上午11:24*/
SpringBootApplication(exclude {DataSourceAutoConfiguration.class})
EnableFeignClients(basePackages cn.stylefeng.roses.gateway.modular.consumer)
EnableZuulProxy
public class RosesGatewayApplication {Autowiredprivate ExampleServiceConsumer exampleServiceConsumer;public static void main(String[] args) {SpringApplication.run(RosesGatewayApplication.class, args);}Beanpublic CommandLineRunner commandLineRunner() {return new CommandLineRunner() {Overridepublic void run(String... args) throws Exception {System.out.println(exampleServiceConsumer.test1(123));}};}}
想学习更多微服务、分布式、中间件、数据库、项目快速构建等系列技术 请访问http://gblfy.com 让我们一起进步