微服务
简介
单一职责的。一个微服务应该都是单一职责的,这才是“微”的体现,一个微服务解决一个业务问题(注意是一个业务问题而不是一个接口),而一个真正面向客户的服务往往由不同个微服务组合起来。
将自己的业务能力封装并对外提供服务,这是继承SOA(Service-Oriented Architecture)的核心思想,一个微服务本身也可能使用到其它微服务的能力。(https://www.jianshu.com/p/7293b148028f)
微服务最重要的特性在于松耦合,可独立部署,这意味着不同的微服务,如评论,支付等模块可以在不同端口同时运作同时编码而不易相互干扰
但同时,这也使得系统更复杂,增加架构难度和运维成本
通信方式
同步通信:Rest,RPC(有些微服务架构不可用)
异步:消息队列
RPC和Restful的比较
使用RPC的服务在自己的类中声明了需要的服务,当真正需要时,会把具体参数序列化发往对方,等待响应数据。而Restful相当于是把自己的接口展露出来,有对应接口路径的就可以访问。RPC耦合度较高,但没有那么多规范,效率较高,适合高性能要求且高成本维护的项目
微服务和分布式的关系
分布式是一种协调手段,将微服务和旁边的组件组合起来,组件如进来时分配服务器的网关,保证数据安全的熔断器等,微服务可以缺少分布式,但分布式依赖于微服务
分布式必知组件
负载均衡
过去使用DNS完成负载均衡,通过域名解析前往不同的服务器,但存在一个问题,就是可靠性极低,例如当出现目标服务器毁坏时DNS会仍然响应毁坏ip;当DNS服务器毁坏时,所存的服务器地址就都会失去
客户端的流量首先会到达负载均衡服务器,由负载均衡服务器通过一定的调度算法将流量分发到不同的应用服务器上面,同时负载均衡服务器也会对应用服务器做周期性的健康检查,当发现故障节点时便动态的将节点从应用服务器集群中剔除,以此来保证应用的高可用。
https://www.cnblogs.com/danbing/p/7459224.html
CDN
静态资源加载往往较慢,所以我们往往不在主服务器拿数据,而是通过地方的CDN缓存服务器,然而这还不够,为了减少成本,CDN对应域名常常不止一个,当正常通过域名访问时可以找到,CDN可以通过**SNI机制(一种未知的预知所需域名手段)**获得ip对应域名,当通过ip地址时会无法确认域名而找不到
SpringBoot
定义
springboot是一个通过自动装配简化原spring开发配置的框架,并且可以集成各种组件,如过滤器,也可以集成数据库,是一种约定大于配置的类maven型框架
新建项目
1 官网
生成后通过IDEA打开即可
2 IDEA建立
springboot结构初览
三个pom的自带功能
以上三个,第一个解决web配置包括内嵌Tomcat,配置web.xml和配置DispatcherServlet(出现注解无法识别的情况,在错误处通过Alt+enter手动将该此包导入类路径)
第二个帮忙完成测试配置
第三个配置完成打包的插件,通过点击此处完成打包
打包成功后jar包位置,可以复制到其他地方使用
编写当前项目的位置
SpringbootApplication是项目启动的入口,它只会识别到GroupId下ArtifactName里的文件,从而方便于其他项目对接
开始出现的动画图案
在此处建立banner.txt文件,从中加入所需图案即可
关于端口号
在application.properties(yaml等类型也可以)中可以进行更改
配置原理
主启动类原理
新的配置文件类型:yaml
作用
配置文件,类似.properties,但是properties只能存放键值对,而yaml还可以存放对象和数组等,
方便批量导出数据,适用于JavaBean类型
基本语法
对于yaml来说,空格非常重要,用于区分每个变量的逻辑关系,不可以用tab代替
# 普通键值对
key: value
# 两种对象配置方法
student:
name: xiaozhi
no: 200000
student: {name: xiaozhi,no: 200000}
# 两种数组配置方法
stu:
- 20
- pet
stu: [20,pet]
# 改变服务器端口
server:
port: 8080
# 调用yaml其他对象的值
student:
name: xiaoling
lover: ${student.name}
yml使用时的配置
1 建立实体类/property类,为其附上扫描注释(一般为@Component,如果不注释的话需要在配置类上添加@EnableConfigurationProperties来使实体类可以被spring识别),添加注释@ConfigurationProperties(prefix = “对象名”)
2 在yml中配置@ConfigurationProperties(prefix = "对象名")
对应对象(yaml实行松散绑定,即last-name可以对应Bean类的lastName)
3 配置类中写好实体类的@bean方法
3 在需要使用的地方通过@Autowired自动配置
配置原理
在程序的入口会有@SpringbootApplication
,其中有@EnableAutoConfiguration
,其中通过@import
导入AutoConfigurationImportSelector
,其中调用getAutoConfigurationEntity
获得配置实体,获取实体需调用getCandidateConfiguration
,获得全部候选配置类需要bean的类加载器(getBeanClassLoader
)和通过SpringFactoryloader
方法读取spring.factories中所有configuration型bean类
在spring.factories中包含各种@xxxxAutoConfiguration
配置类,配置类会通过@EnableConfigurationProperties
指向一个实体类,如果该实体类有相应starter的话,@onConditional
注解会通过,实体类就可以通过前缀@ConfigurationProperties
在yaml中搜索指定前缀得到属性,并实例化为对象(这一步和前面使用配置一样)
web开发
静态资源导入
1.在properties等配置文件中直接设置导入位置
2.webjars方式,url请求方式需要输入webjars,并按照webjars结构进行补充
3.使用默认资源导入方式,resource>static(默认放静态资源)>public
首页切换
在resource,static,public 文件夹中重写index.html页面或在templates文件夹中(需要导入thymeleaf)
jsp的模板引擎thymeleaf
什么是thymeleaf
Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text.
Thymeleaf是一个现代服务器端Java模板引擎,可以在单机和联网环境使用,用来加载HTML,XML,JS,CSS和纯文本
Thymeleaf的主要目的是提供一个优雅且高可维护性的创建模板的方法,为了达到这个目的,它以自然模板为建造基石,通过一种不影响模板被当作设计原型的方式来将它的逻辑注入模板文件。这改善了设计的沟通和连接了设计和研发团队之间的隔阂
预备工作
1 在pom.xml导入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2 在template处建立对应html页面
3 修改html页面的<html>
标签如下:
<html lang="en" xmlns:th="http://www.thymeleaf.org">
使用thymeleaf后的页面请求
需要通过Controller对应路径,映射到Templates文件夹
基础语法
${}
用于文本
以下两者都是用来显示后端键值对文本,而当value中有html标签时,<th:text>
不会解析,<th:utext>会
,值类型为Object,也可以承载数组类型
<div th:text="${msg}"></div>
<div th:utext="${msg}"></div>
用于递归遍历
<h3 th:each="user:${users}" th:text="${user}"/>
用于判断条件
${ ? :}
除此之外还有value
@{}
用于超链接,src载体,表单传递
th:href="@{/user/signup}"
th:src="@{/img/logo-white.png}"
th:action="@{/user/login}
#{}
用于国际化
~{}
用于fragment组件插入
<div th:replace="~{common/common::topbar}">
thymeleaf嵌restful
thymeleaf只对最后一个允许变量拼接,所以当有两处以上restful传输,前面应为常量
th:href="@{/repman/rejectrep/4/{repairsId}(repairsId=${repair.getRepairsId()})}
-----html-----
-----java-----
@RequestMapping("/repman/rejectrep/{status}/{repairsId}")
public String submitRepairs(@PathVariable int repairsId,@PathVariable int status){
repairsService.updateRepairsStatus(status,repairsId);
return "/repman/main";
}
实现页面选择输出
th:action="${comment==null?'/app/insertcom/':'/app/updatecom/'}+${repairsId}"
th:value="${comment==null?5:comment.getEvaluateScore()}"
---三目---
---th:if--
<textarea class="form-control card-text" rows="3" name="evaluateComment" placeholder="详细描述" th:if="${comment==null}">[[${'师傅维修又快又好,负责热情'}]] </textarea>
<textarea class="form-control card-text" rows="3" name="evaluateComment" placeholder="详细描述" th:unless="${comment==null}" >[[${comment.getEvaluateComment()}]]</textarea>
装配扩展springMVC
SpringBoot为SpringMVC提供了可以和绝大多数应用顺畅合作的自动配置
自动配置在Spring的默认配置上增加以下特点
包括ContentNegotiatingViewResolver
和BeanNameViewResolver
的bean
支持静态资源,包括WebJars
自动注册Converter
,GenericConverter
, 和Formatter
的bean
支持HttpMessageConverters
自动注册MessageCodesResolver
静态index.html支持
自动使用ConfigurableWebBindingInitializer的bean
(节自SpringBoot官网)
自定义SpringBoot的MVC(包括拦截器,格式转换器,视图控制器和解析器):
1 可以通过在配置文件中修改xxxxproperty的默认属性
2 可以用继承WebMvcConfigurer
的JavaConfig,但是不能注解@EnableWebMvc
,因为它会破坏WebMvcAutoConfiguration的@ConditionalOnMissingBean
条件
组件
关于自定义组件的需要
无论是国际化,拦截器还是解析器等组件,都需要通过以下步骤:
1 它们其实都已经有了自己的实体类,在spring-boot-autoconfigurer/factories中可以找到配置类,从其注释可以进入实体类,自建一个实现同样组件接口的类,重写需要重定义的方法即可
2 自建完实体类后yml使用时的配置
关于Template组件的需要
Template组件即是已经填好参数的模板实体类,方便使用
SpringBoot存在XXRegistrationBean,参数往往有XXServlet()/XXFilter等组件名,它替代了web.xml,替代其完成模板组件的注册,使得代码更加简洁
JSR303
1 在pom.xml中加入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2 在实体类上加入@Validated,在所需的方法上加入对应检验
前端日期型显示,和日期型输入数据库
由于java会把日期序列化变成Date格式,所以出入都需要重新定义为“yyyy-mm-dd”型,这样数据库才能匹配
后端到前端:
th:value="${#dates.format(repairs.getRepairsTime(),'yyyy-MM-dd')}
前端到后端
public class Evaluate {
int repairsId;
Date evaluateTime;
int evaluateScore;
String evaluateComment;
@TableField(exist = false)
String evaluateTimeStr;
}
//将前端传来的字符串转换为固定格式的Date型
Date date1 = StringToDate.stringToDate(evaluate.getEvaluateTimeStr());
public class StringToDate {
public static Date stringToDate(String date){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");//设置转化格式
try{
return sdf.parse(date);
}
catch (ParseException e){
System.out.println("日期输入有误");
return null;
}
}
}
国际化
1 在File Encoding中改变property的编码集
2 在resource中建立i18n,建立所需.property文件,建立name.property为默认属性文件,根据语言需要再建立name_language.properties,将同样的属性多次填写
3 在yml中更改spring.messages.basename=i18n.login
4 在页面中用th:#{},[[#{}]]写入属性
5 写实现了LocaleResolver的类,重写响应对其他语言请求的方法,并在JavaConfig中注册
6 在页面中写请求其他语言的超链接,完成语言转换
拦截器
1 创建拦截器实体类,重写方法,通过判断决定是否通过拦截器
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if(request.getSession().getAttribute("loginUser")==null) {
request.setAttribute("msg","权限不足");
request.getRequestDispatcher("/user/login").forward(request, response);
return false;
}
return true;
}
2 在MVC配置类中注册拦截器,并设置不拦截对象
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").
excludePathPatterns("/","/index.html","/user/login","/user/signup");
}
关于拦截器重返主页
由于主页的Controller有夹带参数用以判断
@RequestMapping("/user/login")
public String hello(String username, @RequestParam("password") String password, Model model, HttpSession session){
if(!CheckEmpty.isEmpty(username)&&password.equals("123456")){
System.out.println("OK");
session.setAttribute("loginUser",username);
return "redirect:/main.html";
}
model.addAttribute("msg","用户名为空或密码错误");
return "signin";
}
所以拦截器一般需要再重写一个方法来返回主页
集成数据库
JDBC
1 配置JDBC集成
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2 为JDBC自动配置类写好properties
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/table_name?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
# mysql8以前用com.mysql.jdbc.Driver,8以后用com.mysql.cj.jdbc.Driver
datasourse配置(Druid为例)
未配置数据源时默认数据源为Hikari,这是性能优于Druid的数据源,现在应用非常广泛
1 为datasource自动配置类写好properties
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/table_name?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource # 自定义数据源
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
2 配置datasource集成
</dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<!-- 仅以log4j示范-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Mybatis
@Mapper和@MapperScan
两者效果相同,都是Mybatis实现数据库功能的,但前者是标识类的,后者是在SpringBoot入口标识
Druid
安全集成
shiro
Spring Security
拓展集成
异步
邮件
任务
Swagger
分布式集成
Dubbo+Zookeeper
Springcloud
对比dubbo(摘自狂神说)
最大区别:Spring Cloud采用的是Rest通信而Dubbo采用RPC
dubbo采用二进制传输,效率更高,Spring Cloud牺牲了服务调用的性能,采用了http协议,占用带宽较多,但也避免了上面提到的原生RPC带来的问题。而且REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这个优点在当下强调快速演化的微服务环境下,显得更加合适。
hello world
使用maven搭建空白模板
删除当前工程src,以便作为父工程
spring cloud参考网站
SpringCloud Netflix 中文文档:https://springcloud.cc/spring-cloud-netflix.html
SpringCloud 中文API文档(官方文档翻译版):https://springcloud.cc/spring-cloud-dalston.html
SpringCloud中国社区:http://springcloud.cn/
SpringCloud中文网:https://springcloud.cc