首页 文章 精选 留言 我的

精选列表

搜索[SpringBoot],共4373篇文章
优秀的个人博客,低调大师

SpringBoot分布式 - SpringCloud

一:介绍 Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种简单的开发方式。 微服务(Microservices Architecture)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。 Spring Cloud 中文文档 https://springcloud.cc/spring-cloud-dalston.html Spring Cloud 官方文档 http://projects.spring.io/spring-cloud/#quick-start SpringCloud 教程PDF下载:https://download.csdn.net/download/yueshutong123/10501017 二:入门 在IDEA新建空白工程 1. 注册中心 在工程下新建模块eureka-server 1)导包 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> 2 )application.yml配置Eureka信息 server: port: 8761 eureka: instance: hostname: eureka-server #eureka实例的主机名 client: register-with-eureka: false #不把自己注册到eureka fetch-registry: false #不从eureka上获取服务的注册信息 service-url: defaultZone: http://localhost:8761/eureka/ 3)开启@EnableEurekaServer注解 package cn.zyzpp.eurekaserver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** * 开启@EnableEurekaServer注解 */ @EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } 4)开启注册中心 启动该应用,访问http://localhost:8761/ 进入Spring Eureka页面即成功。 2.服务提供者 新建模块:provider-ticket 1)导入依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> 2)application.yml配置Eureka信息 server: port: 8001 #8002 spring: application: name: provider-ticket eureka: instance: prefer-ip-address: true #注册服务的时候使用服务的Ip地址 client: service-url: defaultZone: http://localhost:8761/eureka/ 3)Service层方法 package cn.zyzpp.providerticket.service; import org.springframework.stereotype.Service; /** * Create by yster@foxmail.com 2018/6/4/004 18:37 */ @Service public class TicketService { public String getTicket(){ return "《厉害了,我的国》"; } } 4)暴露HTTP接口 /** * Create by yster@foxmail.com 2018/6/4/004 18:39 */ @RestController public class TicketControllert { //轻量级HTTP @Autowired private TicketService ticketService; @GetMapping("/ticket") public String getTicket(){ System.out.println("8001"); //8002 return ticketService.getTicket(); } } 5)然后更改端口,分别打包该模块为jar包。运行。 3.服务消费者 新建模块consumer-user 1)application.yml配置Eureka信息 server: port: 8200 spring: application: name: consumer-user eureka: instance: prefer-ip-address: true #注册服务的时候使用服务的Ip地址 client: service-url: defaultZone: http://localhost:8761/eureka/ 2)开启发现服务的功能,使用负载均衡机制(默认轮询) import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @EnableDiscoveryClient /*开启发现服务功能*/ @SpringBootApplication public class ConsumerUserApplication { public static void main(String[] args) { SpringApplication.run(ConsumerUserApplication.class, args); } @LoadBalanced /*开启负载均衡机制*/ @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } } 3)获取服务 /** * Create by yster@foxmail.com 2018/6/4/004 19:13 */ @RestController public class UserController { @Autowired private RestTemplate restTemplate; @GetMapping("/buy") public String getTicket(){ String s = restTemplate.getForObject("http://PROVIDER-TICKET/ticket",String.class); return "购买了 "+s; } } 启动服务消费者模块。查看服务提供者的控制台打印。 会发现第一次请求8001,第二次8002,8001,8002,,这是因为使用了负载均衡。 本文只讲解了服务的注册与发现,Spring cloud的更多内容推荐阅读:SpringCloud分布式教程

优秀的个人博客,低调大师

SpringBoot(二)_项目属性配置

修改端口 在main/resources/application.properties修改端口 server.port=8088 此时启动访问localhost:8088/hello 就会看到 Hello Spring Boot! 使用yml文件替换properties 文件 (1)在main/resources 文件下新建一个application.yml 文件 (2)在yml文件中修改端口 server: port: 8099 (3) 删除掉application.properties文件,只保留yml文件 (4) 运行程序,此时访问8099端口即可 获取配置文件的值 (1) 在application.yml 文件中,编写上其他内容 server: port: 8099 name: maomao age: 18 (2) 利用@Value 注解 @RestController public class HelloController { @Value("${name}") private String name; @Value("${age}") private int age; @RequestMapping(value = {"/hello"},method = RequestMethod.GET) public String say(){ return name+age; } } (3)访问8099端口,就获取到值 maomao 18 使用自定义配置类 如果属性很多,我们每个属性都需要写,显得有些费事,我们可以利用自定义配置类进行获取 (1) 修改yml 文件 server: port: 8099 girl: name: maomao age: 18 (2) 创建properties/GirlProperties.java @Component @ConfigurationProperties(prefix = "girl") public class GirlProperties { private String name; private int age; //get和set方法省略 } (3) 我在使用@ConfigurationProperties 这个注解时,提示找不到class,需在pom文件中引入 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> (4) 修改controller文件 @RestController public class HelloController { @Resource private GirlProperties girlProperties; @RequestMapping(value = {"/hello"},method = RequestMethod.GET) public String say(){ return girlProperties.getName(); } } (5)验证结果 maomao 开发环境和生成环境配置不同的问题 这个问题经常见,比如我们开发环境 name 是maomao ,生成环境是 毛毛,我们大部分都是修改配置文件,但是这样还是很麻烦。 (1) 复制2个yml文件,分别是application-dev.yml (开发环境) application-prod.yml(生产环境) (2) 修改application-prod.yml(生产环境)文件 server: port: 8088 girl: name: 毛毛 age: 18 (3) application-dev.yml (开发环境)文件内容 server: port: 8099 girl: name: maomao age: 18 (4)application.yml文件内容,这个就代表使用dev的配置文件 spring: profiles: active: dev (5)上篇文章讲过java -jar 的启动方式 先执行 mvn install 在执行启动 java -jar girl-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod (6)此时就是访问的prod 的配置8088,(注意我们配置的application.yml 中用的是dev 这个配置文件,但是我们启动的时候加上后面的参数就自动切换到 prod 文件上) 总结 在使用yml进行配置更加简单方便,使用java -jar 启动 加上参数,就可以避免我们来回修改配置文件,有漏掉的情况。 源码下载:github 学习不是要么0分,要么100分的。80分是收获;60分是收获;20分也是收获。有收获最重要。但是因为着眼于自己的不完美,最终放弃了,那就是彻底的0分了。

优秀的个人博客,低调大师

SpringBoot 手写拦截器

如何手写一个拦截器呢。假设我现在需要一个计时拦截器,我想把每一次调用服务锁花费的时间打印到控制台,我该怎么做呢? 拦截机制有三种: 1. 过滤器(Filter)能拿到http请求,但是拿不到处理请求方法的信息。 2. 拦截器(Interceptor)既能拿到http请求信息,也能拿到处理请求方法的信息,但是拿不到方法的参数信息。 3. 切片(Aspect)能拿到方法的参数信息,但是拿不到http请求信息。 他们三个各有优缺点,需要根据自己的业务需求来选择最适合的拦截机制。 拦截机制图 好了下面开始正文。 手写拦截器实战 /** * Time 时间拦截器(比时间过滤器准)) * Created by Fant.J. */ @Component public class TimeInterceptor implements HandlerInterceptor { //controller 调用之前被调用 @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception { System.out.println("preHandle"); System.out.println(((HandlerMethod)handler).getBean().getClass().getName()); System.out.println(((HandlerMethod)handler).getMethod().getName()); httpServletRequest.setAttribute("startTime",System.currentTimeMillis()); return true; } //controller 调用之后被调用,如果有异常则不调用 @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); long startTime = (long) httpServletRequest.getAttribute("startTime"); System.out.println("时间拦截器耗时:"+(System.currentTimeMillis() -startTime)); } //controller 调用之后被调用,有没有异常都会被调用,Exception 参数里放着异常信息 @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { System.out.println("afterCompletion"); long startTime = (long) httpServletRequest.getAttribute("startTime"); System.out.println("时间拦截器耗时:"+(System.currentTimeMillis() -startTime)); } } 代码解释: 其中,preHandle()方法再controller 调用之前被调用 postHandle()在controller 调用之后被调用,如果有异常则不调用 afterCompletion()在controller 调用之后被调用,有没有异常都会被调用,Exception 参数里放着异常信息。 但是值写这个处理拦截器还不行,还需要进一步的配置,请看下面一段代码: /** * 引入第三方过滤器 将其放入spring容器 * Created by Fant.J. */ @Configuration public class WebConfig extends WebMvcConfigurerAdapter{ // 注入Time 拦截器 @Autowired private TimeInterceptor timeInterceptor; //添加拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { //往拦截器注册器里添加拦截器 registry.addInterceptor(timeInterceptor); } 首先我们继承WebMvcConfigurerAdapter类,重写它的addInterceptors()方法,该方法是添加拦截器至Spring容器中。 然后调用拦截器注册器InterceptorRegistry 进行注册。 介绍下我的所有文集: 流行框架 SpringCloudspringbootnginxredis 底层实现原理: Java NIO教程Java reflection 反射详解Java并发学习笔录Java Servlet教程jdbc组件详解Java NIO教程Java语言/版本 研究

优秀的个人博客,低调大师

SpringBoot学习之集成dubbo

一、摘自官网的一段描述 1.背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。 单一应用架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。 垂直应用架构 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。 分布式服务架构 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。 流动计算架构 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。 为什么我贴出这段话,它描述了互联网架构的演变,关键要素及dubbo存在的意义,可谓简约而不简单 官网地址,在这里关于dubbo的介绍我就不再这里阐述了,官网有中文的说明而且很详细 2、需求 在大规模服务化之前,应用可能只是通过 RMI 或 Hessian 等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过 F5 等硬件进行负载均衡。 当服务越来越多时,服务 URL 配置管理变得非常困难,F5 硬件负载均衡器的单点压力也越来越大。此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。并通过在消费方获取服务提供方地址列表,实现软负载均衡和 Failover,降低对 F5 硬件负载均衡器的依赖,也能减少部分成本。 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。这时,需要自动画出应用间的依赖关系图,以帮助架构师理清理关系。 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。 以上是 Dubbo 最基本的几个需求。 点评:其实前半段就是描述了注册中心必要性,后半段说明了监控与分析的重要性,恰好dubbo有独特的monitor模块 3、架构 这个图不多说了,描述了一个服务注册与发现的场景 : 服务容器负责启动,加载,运行服务提供者。 服务提供者在启动时,向注册中心注册自己提供的服务。 服务消费者在启动时,向注册中心订阅自己所需的服务。 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。 二、使用spring-boot快速搭建dubbo 1.项目结构图 2. 编写service-api层代码 IStudentService: package com.hzgj.lyrk.dubbo.api; import com.hzgj.lyrk.dubbo.dto.StudentDTO; public interface IStudentService { StudentDTO getStudentById(Integer id); } View Code StudentDTO:注意必须实现serializable接口 package com.hzgj.lyrk.dubbo.dto; import lombok.Data; import java.io.Serializable; @Data public class StudentDTO implements Serializable { private Integer id; private String name; } View Code 3.编写student-server模块 3.1首先添加gradle依赖项: dependencies { // testCompile group: 'junit', name: 'junit', version: '4.12' compile 'com.alibaba.boot:dubbo-spring-boot-starter:0.1.0' // https://mvnrepository.com/artifact/com.101tec/zkclient compile group: 'com.101tec', name: 'zkclient', version: '0.10' compile project(":service-api") } View Code 3.2 StudentServer: package com.hzgj.lyrk.dubbo.student.server; import com.alibaba.dubbo.config.annotation.Service; import com.hzgj.lyrk.dubbo.api.IStudentService; import com.hzgj.lyrk.dubbo.dto.StudentDTO; @Service public class StudentService implements IStudentService { @Override public StudentDTO getStudentById(Integer id) { StudentDTO studentDTO = new StudentDTO(); studentDTO.setId(id); studentDTO.setName("学号为" + id + "的学生"); return studentDTO; } } View Code 注意此处@Service要用 com.alibaba.dubbo.config.annotation.Service 3.3 编写启动类: package com.hzgj.lyrk.dubbo.student; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class StudentApplication { public static void main(String[] args) { SpringApplication.run(StudentApplication.class, args); } } View Code 3.4 application.yml文件 server: port: 8100 spring: application: name: student-server dubbo: application: name: student-server id: student-server version: 1.0 scan: base-packages: com.hzgj.lyrk.dubbo.student.server registry: address: zookeeper://localhost:2181 View Code 在这里面我们注意以下几点: 1)首先定义spring.application.name这个不多说了 遵守规范就行 2)dubbo集成的配置时通常以dubbo.xxxx打头 3)dubbo.scan.base-packages:主要是扫描dubbo的注解包 4)dubbo.registry.address:是指定注册中心的地址,这里我们使用zookeeper作为注册中心 3.5 启动成功时,我们通过zkCli能够发现在zookeeper存在如下节点: 这里面的结构为:/dubbo/接口的类全名/节点 4、编写消费端:project-portal 4.1 添加gradle依赖: dependencies { compile 'com.alibaba.boot:dubbo-spring-boot-starter:0.1.0' // https://mvnrepository.com/artifact/com.101tec/zkclient compile group: 'com.101tec', name: 'zkclient', version: '0.10' compile project(":service-api") } View Code 4.2 编写controller package com.hzgj.lyrk.dubbo.portal.controller; import com.alibaba.dubbo.config.annotation.Reference; import com.hzgj.lyrk.dubbo.api.IStudentService; import com.hzgj.lyrk.dubbo.dto.StudentDTO; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class StudentController { @Reference private IStudentService studentService; @GetMapping("/student/id/{stuId}") public StudentDTO getStudent(@PathVariable Integer stuId) { return studentService.getStudentById(stuId); } } View Code 注意:@Reference注解的使用 4.3 编写启动类 package com.hzgj.lyrk.dubbo.portal; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class PortalApplication { public static void main(String[] args) { SpringApplication.run(PortalApplication.class, args); } } View Code 4.4 编写application.yml spring: application: name: project-portal server: port: 8101 dubbo: registry: address: zookeeper://localhost:2181 application: version: 1.0 id: project-portal name: project-portal View Code 测试一下: 三 、后话- Dubbo与SpringCloud 其实,这两者都是当下微服务典型的技术解决方案,可谓一时瑜亮,只不过在国内dubbo比较流行一些,原因其实很简单: 1. dubbo官方文档详细且有中文,而且运行原理技术解决方案描述比较透彻 2.国内的架构师有许多来自于阿里,对dubbo的推广起到了不可磨灭的作用 3.由于dubbo出现的较早,当然也开源。对于当时可谓轰动一时,各大公司争先使用,即使到现在谁也不愿意将原先的项目大刀阔斧的用新技术重构。 相反,在国外的社区,dubbo的使用广度恐怕就远不及SpringCloud了。原因其实也很明了:就公司而言,dubbo出自于阿里,属于商业公司。我觉得阿里的框架肯定优先满足于自己的业务与利益。而springcloud出自于Spring的产品族,而其公司本身就是为了简化企业的开发模式,为各大企业所服务。因此他们的本身出发点就不同,我觉得这个才是必要因素。 但是有几点我在这里重点提一下: 1. 就完成的功能而言:dubbo其实是SpringCloud组件中的一部分,也就相当于netflix中的eureka+小半个Hystrix+ribbon+feign。但是SpringCloud集成的诸如:链路跟踪,分布式配置,网关路由等,目前dubbo里还没有找到,也有可能我没有发现。因此在dubbo里需要使用这些功能,我们还要借助于第三方的实现。 2. dubbo是基于rpc实现远程调用,springcloud各个服务之间调用还是经过http,就性能而言是要弱于dubbo的,毕竟dubbo是经过阿里庞大的业务产品族和并发量考验的,不过这并不代表springcloud性能会很差 3. 常用的dubbo的技术使用方案还是基于spring,因此,我还是愿意把幕后英雄归功于spring 4. spring-cloud就相当于电脑的品牌机,拿来很方便的使用,因此它绝对是中小型公司(没有过多的精力和成本去搞基础研发)福音。而dubbo就好比是组装机,我们通过其已有的实现,完整的文档装配成我们自己想要的一套微服务方案。

优秀的个人博客,低调大师

SpringBoot】Spring 事务的失效问题

# Spring 事务的失效问题 ## **一、调用方式不对(自调用)?**? - 场景:在同一个类里,一个方法调用另一个加了 `@Transactional` 的方法。 - 原因:Spring 事务是通过代理实现的,内部方法调用不会走代理,事务不会生效。 - 解决:把需要事务的方法放到另一个类里,或通过 AopContext 获取代理调用。 ## **二、方法不是 `public`?**? - Spring 默认只对 `public` 方法生效。 - 如果 `@Transactional` 标注在 `private`、`protected` 或 `default` 方法上,事务不会生效。 ## **三、异常没抛出?**? - 默认回滚规则:Spring 只会对 **运行时异常(RuntimeException 或其子类)** 回滚。 - 如果你捕获异常后没抛出,事务不会回滚。 - 如果抛的是受检异常(如 `IOException`),默认也不会回滚。 - 解决: - 重新抛出运行时异常。 - 或在注解里指定 `rollbackFor`: ``` @Transactional(rollbackFor = Exception.class) ``` ## **四、数据库引擎不支持事务** - MySQL 如果表引擎是 MyISAM,不支持事务,事务自然无效。 - 必须用 InnoDB 才能支持。 ## **五、多线程调用?**? - 如果事务方法里开了新线程,线程里的操作不受当前事务控制。 - 解决:避免在事务方法里直接用多线程,或者手动管理事务。 ## **六、配置问题** - `@EnableTransactionManagement` 没配置。 - 事务管理器没有正确注入。 ## **七、手动设置了传播属性** - 如果事务传播属性设置不当(如 `PROPAGATION_NEVER`),也会导致失效。 ## ✅ **快速排查清单** 1. 方法必须是 `public` 1. 确保是代理调用(不是同类内调用) 1. 确保异常能抛出,没被吞掉 1. 数据库表必须支持事务 1. 确认 Spring 的事务配置启用

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册