我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringBoot详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringBoot详解

前言

所有的技术框架的发展似乎都遵循了一条主线规律:

  1. 从一个复杂应用场景衍生一种规范框架, 人们只需要进行各种配置而不需要自己去实现它, 这时候强大的配置功能成了优点;
  2. 发展到一定程度之后, 人们根据实际生产应用情况, 选取其中实用功能和设计精华, 重构出一些轻量级的框架;
  3. 之后为了提高开发效率, 嫌弃原先的各类配置过于麻烦, 于是开始提倡 “约定大于配置″, 进而衍生出一些一站式的解决方案。
    这就是 Java 企业级应用 ->J2EE-> spring-> spring boot 的过程。

一、SpringBoot 是什么?

1.1、概念

  • SpringBoot 是一个 javaweb 开发的框架。
  • 对比于其他 Javaweb 框架,更简化开发,约定大于配置。

1.2、目的

  • 让大家更容易使用 spring,更容易集成各种常用的中间件、开源软件。
  • SpringBoot 基于 Spring 开发, SpringBoot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。
  • SpringBoot 不是用来替代 spring 的解决方案,而是和 spring 框架紧密结合提升 spring 开发者体验的工具。

1.3、什么是微服务

  • 微服务是一种架构风格, 它要求我们在开发一个应用的时候, 这个应用必须构建成一系列小服务的组合; 可以通过 http 的方式进行互通。
  • MVC 架构,MVVM 架构,微服务架构。
  • 微服务架构, 就是把每个功能元素独立出来。把独立出来的功能元素的动态组合, 需要的功能元素才去拿来组合, 需要多一些时可以整合多个功能元素。
  • 所以微服务架构是对功能元素进行复制, 而没有对整个应用进行复制。

优点:1. 节省了调用资源。2. 每个功能元素的服务都是一个可替换的、可独立升级的软件代码。

1.4、单体应用架构

  • 单体应用架构 (all in one) 是指,我们将一个应用的中的所有应用服务都封装在一个应用中;
  • 无论是 ERP、CRM 或是其他什么系统看,都把数据库访问,web 访问,等等各个功能放到一个 war 包内。

优点:易于开发和测试,方便部署;当需要扩展时,只需要将 war 复制多份, 然后放到多个服务器上, 再做个负载均衡就可以了。
缺点:修改一个非常小的地方, 都需要停掉整个服务, 重新打包部署这个应用 War 包;对于一个大型应用,如何维护,如何分工合作都是问题。

1.5、如何构建微服务

二、SpringBoot 原理

2.1、pom.xml

  1. spring-boot-dependencie:核心依赖在父工程中。大部分依赖的版本都是在父工程中管理着,我们拿过来调用即可,因此我们引用一些依赖时不需要指定版本。并且父工程中已经帮我们配置好资源过滤和一些插件。

2.2、启动器

<dependency>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-webartifactId>dependency>
  1. 启动器其实就是 springboot 的启动场景,比如 spring-boot-starter-web 启动器会帮我们自动导入 web 环境所有依赖。
  2. springboot 会将所有的功能场景,都变成一个个启动器。
  3. 我们要使用什么功能,只需要找到对应的启动器就可以了即 starter

2.3、主程序

2.3.1、注解

@SpringBootApplication

  1. @SpringBootConfiguration:springboot 的配置。
  2. @EnableAutoConfiguration:自动导入配置。
    1. @AutoConfigurationPackage:自动配置包。
      • @Import({Registrar.class}):自动配置包注册。
    2. @Import({AutoConfigurationImportSelector.class}):自动配置导入选择器。(自动导包的核心)
  3. @ComponentScan():扫描当前主启动类同级的包。(扫描的包到 Registrar.class 注册)

自动导包的核心 AutoConfigurationImportSelector 类:选择了什么东西
AutoConfigurationImportSelector 类中的方法:

// 1.获得自动配置实体(调用“获取所有候选配置”的方法获取实体)。protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata)// 2.获取所有候选配置(候选配置是哪些配置)。List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes){    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");        return configurations;}// 3.候选配置是所有标注@EnableAutoConfiguration注解的类下的所有配置。(即获取主启动类下的所有配置)protected Class<?> getSpringFactoriesLoaderFactoryClass() {        return EnableAutoConfiguration.class;    }// 4.获取所有的配置从哪里来,上面第二个方法调用了loadFactoryNames方法public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {        String factoryTypeName = factoryType.getName();        return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());    }// 5.loadFactoryNames方法调用了loadSpringFactories方法// 6.loadSpringFactories方法从项目资源和系统资源中获取配置文件classLoader.getResources("META-INF/spring.factories") ClassLoader.getSystemResources("META-INF/spring.factories")

META-INF/spring.factories:自动配置的核心文件。

// 遍历所有的资源,封装成properties供我们使用Properties properties = PropertiesLoaderUtils.loadProperties(resource);

结论: springboot 所有自动配置都是在启动的时候扫描并加载: 所有的自动配置类都在 spring.factories 里面,但是不一定生效;要判断条件是否成立:只要导入了对应的 start,就有对应的启动器,有了启动器,我们自动装配就会生效,然后自动配置就可以成功。

详细步骤

  1. springboot 在启动的时候, 从类路径下 / META-INF/spring.factories 获取指定的值。
  2. 将这些自动配置的类导入容器, 自动配置就会生效, 帮我进行自动配置。
  3. 以前我们需要自动配置的东西, 现在 springboot 帮我们做了。
  4. 整合 javaEE, 解决方案和自动配置的东西都在 spring-boot-autoconfigure-2.2.0.RELEASE.jar 这个包下。
  5. 它会把所有需要导入的组件, 以类名的方式返回, 这些组件就会被添加到容器中。
  6. 容器中也会存在非常多的 XXXAutoConfiguration 的文件 (@Bean), 就是这些类给容器中导入了这个场景需要的所有组件并自动配置。@Configuration(JavaConfig)
  7. 有了自动配置类, 免去了我们手动编写配置文件的工作。

2.3.2、Run 方法

main 方法中的 run 方法启动会开启一个服务。

@SpringBootApplicationpublic class SpringbootWeb01Application {    public static void main(String[] args) {        // 该方法返回一个ConfigurableApplicationContext对象        // 参数一:应用入口的类, 参数二:命令行参数        SpringApplication.run(SpringbootWeb01Application.class, args);    }}

2.3.3、SpringApplication.run 分析

主要两部分

  • 一是 SpringApplication 的实例化。
  • 二是 run 方法的执行。

2.3.4、SpringApplication 类主要做了四件事情

  • 判断应用的类型是普通项目还是 web 项目。(普通项目直接就结束了,web 项目可以一直启动)
  • 查找并加载所有可用初始化器,设置到 initializers 属性中。
  • 查找所有的应用程序监听器,设置到 listeners 属性中。(获取上下文处理 bean)
  • 推断并设置 main 方法的定义类,找到运行的主类。

2.4、自动装配再理解

springboot 配置文件能够配置的东西都有一个固有的规律:
他们都有对应的 xxxAutoConfiguration 配置类,这个配置类都会绑定一个 xxxProperties 类,xxxProperties 类和 springboot 的配置文件绑定;这样我们就可以在 springboot 配置文件中自定义配置了。

2.4.1、自动装配原理再理解

  1. springboot 启动会加载大量的自动配置类。
  2. 我们要看我们需要的功能有没有在 springboot 默认写好的自动配置类中。
  3. 我们看这个自动配置类中配置了哪些组件。(不存在就需要全部手动写,如果存在我们就不需要再手动配置;也可以自定义配置覆盖默认的配置)
  4. 给容器中自动配置类添加组件时,会从 xxxProperties 类中获取相应的属性。我们只需要在 springboot 配置中指定这些属性就可以了。
  • xxxAutoConfiguration:自动配置类(给容器中添加组件)
  • xxxProperties:封装配置文件中的属性

2.5、自动配置类中存放了大量的配置没有全部都生效的原因

spring 的底层注解:根据不同的条件,来判断当前配置或者类是否生效。@Conditionalxxx

三、SpringBoot

3.1、yaml 语法

SpringBoot 使用一个全局的配置文件,配置文件名是固定的。

  • application.properties(语法结构:key=value)
  • application.yml(语法结构:key: 空格 value)

全局配置文件的作用:修改 SpringBoot 自动配置的默认值,它会在底层帮我们自动配置。

3.1.1、基本语法

# 对象student:  name: 'zs'  age: 12# 对象的行内写法student1: {name: 'zs',age: 12}# 数组pets:  - cat  - dog  - pig# 数组行内写法pets1: [cat,dog,pig]

3.1.2、@ConfigurationProperties绑定 application.yml 配置的属性(属性需要 set 方法才能取值)

 // 可以直接拿到复杂类型的值@Component@ConfigurationProperties(prefix = "person")@Datapublic class Person {    private String name;    private Integer age;    private Boolean flag;    private Date birth;    private Map<String,Object> map;    private List<Object> list;    private Dog dog;}
// application.ymlperson:  name: zs  age: 12  flag: false  birth: 2021/04/20  map: {k1: v1,k2: v2}  list: [code,music,girl]  dog:    name: 旺财    age: 3
<dependency>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-configuration-processorartifactId>    <optional>trueoptional>dependency>

3.1.3、@Configuration@Value配合取值(没有 set 方法也可以取值)

// 复杂类型不能用@Value直接取值@Configuration@Datapublic class Person {    @Value("${person222.name}")    private String name;    @Value("${person222.age}")    private Integer age;    @Value("${person222.flag}")    private Boolean flag;    @Value("${person222.birth}")    private Date birth;    private Map<String,Object> map;    private List<Object> list;    private Dog dog;}
// application.ymlperson222:  name: zs  age: 12  flag: false  birth: 2021/04/20  map: {k1: v1,k2: v2}  list: [code,music,girl]  dog:    name: 旺财    age: 3

3.1.4、@PropertySource读取 xxx.properties 配置(没有 set 方法也可以取值)

@Component@PropertySource(value = "classpath:test.properties")//可以这样配置@PropertySource({"classpath:test.properties"})@Datapublic class Person {    // SPEL表达式取出配置文件的值    @Value("${name}")    private String name;    @Value("${age}")    private Integer age;    private Boolean flag;    private Date birth;    private Map<String,Object> map;    private List<Object> list;    private Dog dog;}
// test.propertiesname=zhangsanage=13

3.1.5、松散绑定

yml 配置属性的 - 可以和实体属性的驼峰对应绑定

@Component@ConfigurationProperties(prefix = "person")@Datapublic class Person {    private String firstName;}
// application.ymlperson:  first-name: zs

3.1.6、JSR303 数据校验

@Component@ConfigurationProperties(prefix = "person")@Data@Validated //数据校验public class Person {    @Email(message="邮箱格式错误")    private String name;}

HibernateValidator 是 BeanValidation 的参考实现;HibernateValidator 提供了 JSR 303 规范中所有内置 constraint 的实现;和附加的 constraint

HibernateValidator 附加的 constraint

3.2、多环境配置和配置文件位置

3.2.1、配置文件位置

3.2.2、多环境配置切换

四、SpringBootWeb 开发

4.1、SpringBootWeb 开发需要解决的问题

  • 导入静态资源
  • 首页定制
  • 模板引擎 Thymeleaf
  • 装配扩展 springMVC
  • 增删改查
  • 拦截器
  • 国际化
  • SpringMvcConfig 配置
  • 错误页定制

4.2、静态资源导入

  1. 在 SpringBoot,可以使用以下方式处理静态资源。
    • webjars 文件夹下:映射访问 localhost:8080/webjars/
    • public 文件夹,static 文件夹,resources 文件夹下和 @Override public void addViewControllers(ViewControllerRegistry registry) { // 访问/test跳转到test.html页面 registry.addViewController("/test").setViewName("test"); }}

      4.6、CRUD

      4.7、拦截器

      1. 自定义拦截器。
      package com.sywl.config;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class LoginHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {     // 登录成功之后,应该有用户的session     Object loginUser = request.getSession().getAttribute("loginUser");     if (loginUser == null) {// 1.没有登录         // 2.给出提示信息         request.setAttribute("msg", "没有权限,请先登录");         // 3.转发到登录页面         request.getRequestDispatcher("index.html").forward(request, response);         return false;     } else {         return true;     } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { }}
      1. 通过 springMVC 配置文件注入自定义拦截器并设置拦截所有请求和排除拦截的路径。
      package com.sywl.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.LocaleResolver;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class SpringMvcConfig implements WebMvcConfigurer {  @Override public void addInterceptors(InterceptorRegistry registry) {     registry.addInterceptor(new LoginHandlerInterceptor())// 1.添加自定义拦截器             // 2.添加拦截所有的的路径和页面             .addPathPatterns("public class MyLocaleResolver implements LocaleResolver {  @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) {     // 1.获取请求中的语言参数。     String language = httpServletRequest.getParameter("l");     // 2.如果没有就使用默认的。     Locale locale = Locale.getDefault();     // 3.如果请求的链接携带了国际化的参数。     if (!StringUtils.isEmpty(language)){         // zh_CN         String[] split = language.split("_");         // 国家,地区         locale = new Locale(split[0], split[1]);     }     return locale; } @Override public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) { }}
      1. 在 springMVC 配置文件把自定义国际化组件注入到 spring 容器中。
      package com.sywl.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.LocaleResolver;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class SpringMvcConfig implements WebMvcConfigurer {  @Bean public LocaleResolver localeResolver() {     return new MyLocaleResolver(); }}
      1. 登录界面切换国际化时带上参数。

      4.9、SpringMvcConfig 配置

      package com.sywl.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.LocaleResolver;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class SpringMvcConfig implements WebMvcConfigurer {    @Override    public void addViewControllers(ViewControllerRegistry registry) {        // 访问localhost:8080/跳转到index.html        registry.addViewController("/").setViewName("index");        // 访问localhost:8080/index.html跳转到index.html        registry.addViewController("/index.html").setViewName("index");        // 访问localhost:8080/main.html跳转到dashboard.html        // "redirect:/main.html"即跳转到dashboard.html        registry.addViewController("/main.html").setViewName("dashboard");    }        @Bean    public LocaleResolver localeResolver() {        return new MyLocaleResolver();    }        @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(new LoginHandlerInterceptor())// 1.添加自定义拦截器                // 2.添加拦截所有的的路径和页面                .addPathPatterns(" @ConfigurationProperties("spring.datasource") @Bean public DataSource druidDataSource(){     return new DruidDataSource(); } // 后台监控:web.xml,ServletRegistrationBean // 因为springboot内置了Servlet容器,所以没有web.xml;替代方法:ServletRegistrationBean  @Bean public ServletRegistrationBean a(){     // 1.配置访问路径localhost:8080/druid     ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(),"/druid @Bean public FilterRegistrationBean webStatFilter(){     FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();     bean.setFilter(new WebStatFilter());     HashMap<String, String> initParameters = new HashMap<>();     // 可以过滤哪些请求(这些东西不进行统计)     initParameters.put("exclusions","*.js,*.css,/druid @Override protected void configure(HttpSecurity http) throws Exception {     // 首页所有人可以访问,功能页只有对应有权限的人可以访问。     // 1.请求权限的规则     http.authorizeRequests()             .mvcMatchers().permitAll()             .mvcMatchers("/level1 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception {          // 这些数据正常从数据库中取     auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())             .withUser("sywl").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")             .and()             .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")             .and()             .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1"); }}
      1. 扩展整合 thymeleaf。
      <dependency> <groupId>org.thymeleaf.extrasgroupId> <artifactId>thymeleaf-extras-springsecurity4artifactId> <version>3.0.4.RELEASEversion>dependency>
      1. html 页面使用 sec:xxx 语法。
      <div class="nav" th:fragment="nav-menu">  <div sec:authorize="!isAuthenticated()">     <a th:href="@{/toLogin}">登录a> div> <div sec:authorize="isAuthenticated()">     用户名:<span sec:authentication="name">span>     <a th:href="@{/logout}">注销a> div>div>

      6.5、shiro 使用

      1. 导入 shiro 依赖和 shiro 整合 thymeleaf 的依赖。
      <dependency> <groupId>org.apache.shirogroupId> <artifactId>shiro-springartifactId> <version>1.4.1version>dependency><dependency> <groupId>com.github.theborakompanionigroupId> <artifactId>thymeleaf-extras-shiroartifactId> <version>2.0.0version>dependency>
      1. 自定义 UserReam 类继承 AuthorizingRealm 类重写两个方法。用于认证和授权
      public class UserRealm extends AuthorizingRealm { @Autowired UserMapper userMapper;  @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {     System.out.println("执行了授权");     SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();     // 拿到当前登录对象:subject.getPrincipal()可以获得认证时SimpleAuthenticationInfo传递的user     Subject subject = SecurityUtils.getSubject();     User currentUser = (User) subject.getPrincipal();     info.addStringPermission(currentUser.getPerms());     return info; }  @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {     System.out.println("执行了认证");     // 1.拿到用户输入的用户名和密码     UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;     // 2.连接真实数据库     User user = userMapper.selectUser(userToken.getUsername());     if (user==null){         return null;     }     Session session = SecurityUtils.getSubject().getSession();     session.setAttribute("loginUser",user);     return new SimpleAuthenticationInfo(user,user.getPassword(),""); }}
      1. ShiroConfig 配置类,配置 Ream,SecurityManager,ShiroFilterFactoryBean。
      @Configurationpublic class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {     ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();     bean.setSecurityManager(securityManager);          LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();     filterMap.put("/user/add", "perms[user:add]");     filterMap.put("/user/update", "perms[user:update]");     filterMap.put("/user @Bean public ShiroDialect shiroDialect() {     return new ShiroDialect(); }}
      1. 登录方法。
      @RequestMapping("/login") public String login(String username, String password, Model model){     Subject subject = SecurityUtils.getSubject();     UsernamePasswordToken token = new UsernamePasswordToken(username,password);     try {         subject.login(token);         return "index";     } catch (UnknownAccountException e) {         model.addAttribute("msg","用户名不存在");         return "login";     }catch (IncorrectCredentialsException e){         model.addAttribute("msg","密码错误");         return "login";     } }
      1. html 使用 shrio:xxx 语法需要导入头文件。
      DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"   xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro"><head> <meta charset="UTF-8"> <title>首页title>head><body><h1>首页h1><div th:if="${session.loginUser!=null}"> <a th:href="@{/logout}">注销a>div><div th:if="${session.loginUser==null}"> <a th:href="@{/toLogin}">登录a>div><hr><div shiro:hasPermission="user:add"> <a th:href="@{/user/add}">adda>div><div shiro:hasPermission="user:update"> <a th:href="@{/user/update}">updatea>div>body>html>

      6.6、整合 swagger

      1. 导入依赖。
      <dependency> <groupId>io.springfoxgroupId> <artifactId>springfox-swagger2artifactId> <version>2.9.2version>dependency><dependency> <groupId>io.springfoxgroupId> <artifactId>springfox-swagger-uiartifactId> <version>2.9.2version>dependency>
      1. 配置类 SwaggerConfig。
      @Configuration@EnableSwagger2 // 开启swagger2public class SwaggerConfig {}
      1. 测试访问:http://localhost:8080/swagger-ui.html
      2. 自定义 swagger 相关配置。
      @Configuration@EnableSwagger2 // 开启swagger2public class SwaggerConfig { // 注册多个Docket实例可以实现分组 @Bean public Docket docket(){     return new Docket(DocumentationType.SWAGGER_2)             .apiInfo(info())             .groupName("sywl")// 组名             .enable(true)// 是否开启访问swagger;默认true             .select()             // 配置需要扫描接口的方式RequestHandlerSelectors             // basePackage:指定要扫描的包             // any():扫描全部             // none():不扫描             // withClassAnnotation():扫描类上的注解;参数是注解的反射对象             // withMethodAnnotation():扫描方法上的注解             .apis(RequestHandlerSelectors.basePackage("com.sywl.controller"))             // paths:过滤路径(只扫描这些请求下的接口)             .paths(PathSelectors.ant("/user @Bean public ApiInfo info(){     // 作者信息     Contact contact = new Contact("sywl", "", "xxx@163.com");     return new ApiInfo("SwaggerApi文档",             "这是一个文档描述",             "1.0",             "http://www.xxx.com",             contact,             "Apache 2.0",             "http://www.apache.org/licenses/LICENSE-2.0",             new ArrayList()); }}
      1. 常用标识注解
      • @ApiModel(“用户实体类”):用在实体类上,对类的说明。
      • @ApiModelProperty(“用户名”):用在实体类的属性字段上,对字段的说明。
      • @ApiOperation(“跳转首页的接口”):用在方法上,对方法的说明。
      • @ApiParam(“用户名”):用在请求参数上,对请求参数的说明。

      6.7、整合 redis

      1. 导入依赖。
      <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-data-redisartifactId>dependency>
      1. 配置 redis 连接。
      // application.ymlspring:     redis:       host: 127.0.0.1       port: 6379       username: root       password: xxx
      1. 测试。

      七、springboot 实现任务

      • 异步任务:执行的程序需要时间时,需要开启一个线程执行,并给客户一个提示。
      • 定时任务:可以在某一个时间点执行一个任务。
      • 邮件发送:

      7.1、异步任务

      1. springboot 开启异步任务。
      @SpringBootApplication@EnableAsync // 开启异步任务public class Springboot05taskApplication { public static void main(String[] args) {     SpringApplication.run(Springboot05taskApplication.class, args); }}
      1. 在需要开启线程的方法上加上@Async注解。
      @Servicepublic class AsyncService { @Async public void hello(){     try {         Thread.sleep(3000);     } catch (InterruptedException e) {         e.printStackTrace();     } }}
      1. 执行时,可以先给用户反馈信息”OK”,任务仍在执行,不需要用户在加载页面等待。
      @RestControllerpublic class AsyncController { @Autowired private AsyncService asyncService; @RequestMapping("/hello") public String Async(){     asyncService.hello(); // 睡眠3秒     System.out.println("正在处理数据");     return "OK"; }}

      7.2、邮件发送

      1. 导入 mail 依赖
      <dependency>  <groupId>org.springframework.bootgroupId>  <artifactId>spring-boot-starter-mailartifactId>dependency>
      1. 配置 mail
      // application.ymlspring:   mail:     username: xxx@qq.com     password: xxx     host: smtp.qq.com     # QQ邮箱需要开启加密验证;其他的邮箱不需要。     properties: {mail.smtp.ssl.enable: true}
      1. 编写邮件发送。
      @SpringBootTestclass Springboot05taskApplicationTests { @Autowired private JavaMailSenderImpl mailSender; @Test void contextLoads01() {     SimpleMailMessage message = new SimpleMailMessage();     message.setSubject("你好啊!");     message.setText("这是一个问候邮件");     message.setFrom("xxx@qq.com");     message.setTo("xxx@qq.com");     mailSender.send(message); } @Test void contextLoads02() throws MessagingException {     // 1.一个复杂的邮件。     MimeMessage mimeMessage = mailSender.createMimeMessage();     // 2.组装。     MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);     helper.setSubject("你好啊!");     helper.setText("

      这一个问候邮件!

      "
      ,true); // 附件 helper.addAttachment("1.jpg",new File("C:\\Users\\SYWL\\Desktop\\2.jpg")); helper.setFrom("xxx@qq.com"); helper.setTo("xxx@qq.com"); mailSender.send(mimeMessage); }}

      八、dubbo 和 Zookeeper

      8.1、分布式理论

      在《分布式系统原理与范型》一书中有如下定义:“分布式系统是若干独立计算机的集合, 这些计算机对于用户来说就像单个相关系统”。

      8.1.1、分布式系统概念

      分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。

      8.1.2、分布式系统目的

      为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。(其目的是利用更多的机器,处理更多的数据)

      8.1.3、发展

      1. 单一应用架构。
        当网站流量很小时, 只需—个应用, 将所有功能都部署在一起, 以减少部署节点和成本。此时, 用于简化增删改查工作量的数据访问框架 (ORM) 是关键。
        优点:适用于小型网站, 小型管理系统, 将所有功能都部署到一个功能里, 简单易用。
        缺点:1 性能扩展比较难。2 协同开发问题。3 不利于升级维护。
      2. 垂直应用架构。
        当访问量逐渐增大, 单一应用增加机器帶来的加速度越来越小, 将应用拆成互不相干的几个应用, 以提升效率。此时, 用于加速前端页面开发的 Web 框架 (MVC) 是关键。
        优点:通过切分业务来实现各个模块独立部署, 降低了维护和部署的难度, 团队各司其职更易管理, 性能扩展也更方便, 更有针对性。
        缺点:公用模块无法重复利用, 开发性的浪费。
      3. 分布式服务架构。
        当垂直应用越来越多, 应用之间交互不可避免, 将核心业务抽取出来, 作为独立的服务, 逐渐形成稳定的服务中心, 使前端应用能更快速的响应多变的市场需求。此时, 用于提高业务复用及整合的分布式服务框架(RPC)是关键。
      4. 流动计算架构。
        当服务越来越多, 容量的评估, 小服务资源的浪费等问题逐渐显现, 此时需增加一个调度中心基于访问压力实时管理集群容量, 提高集群利用率。此时, 用于提高机器利用率的资源调度和治理中心 (SOA)[Service Oriented Architecture]是关键。

      8.2、什么是 RPC

      RPC【Remote procedure cal】是指远程过程调用, 是—种进程间通信方式, 他是一种技术的思想, 而不是规范。它允许程序调用另一个地址空间 (通常是共亨网络的另一台机器上) 的过程或函数而不用程序员显式编码这个远程调用的细节。(即程序员无论是调用本地的还是远程的函数, 本质上编写的调用代码基本相同)

      RPC 两个核心模块:

      • 通讯
      • 序列化(数据传输需要转换)

      8.3、什么是 dubbo

      Apache dubbob 是一款高性能、轻量级的开源 Java rpc 框架。
      它提供了三大核心能力:

      • 面向接口的远程方法调用。
      • 智能容错和负载均衡。
      • 以及服务自动注册和发现。

      8.4、dubbo

      • 服务提供者(provider):暴露服务的服务提供方, 服务提供者在启动时, 向注册中心注册自己提供的服务。
      • 服务消费者(Consomer):调用远程服务的服务消费方, 服务消费者在启动时, 向注册中心订阅自己所需的服务, 服务消费者, 从提供者地址列表中, 基于软负载均衡算法, 选一台提供者进行调用, 如果调用失败, 再选另一台调用。
      • 注册中心(Registy):注册中心返回服务提供者地址列表给消费者, 如果有变更, 注册中心将基于长连接推送变更数据给消费者。
      • 监控中心:服务消费者和提供者, 在内存中累计调用次数和调用时间, 定时每分钟发送一次统计数据到监控中心。

      8.5、zookeeper

      zookeeper 是注册中心

      1. 下载 zookeeper
        https://downloads.apache.org/zookeeper/
      2. 修改配置文件名称
        修改 apache-zookeeper-3.6.3-bin/conf/zoo_sample.cfg 名称为 zoo.cfg
      3. 启动 zookeeper
        windows 下密令:双击 apache-zookeeper-3.6.3-bin/bin/zkServer.cmd
      4. 可以启动客户端连接
        windows 下密令:双击 apache-zookeeper-3.6.3-bin/bin/zkCli.cmd

      8.6、dubbo-admin

      dubbo-admin 是一个监控管理后台,查看我们注册了哪些服务,哪些服务被消费了

      1. 下载 dubbo-admin
        https://github.com/apache/dubbo-admin/tree/master
      2. 进入到项目中打包
      • dubbo-admin-master 目录下打开 cmd
      • 执行打包密令 mvn clean package -D maven.test.skip=true
      • 启动 dubbo-admin 项目
      • 启动 jar 包密令:java -jar xxx.jar
      • 访问 localhost:7001 (默认端口 7001)

      8.7、springboot 整合 dubbo+zookeeper

      1. 启动 zookeeper 注册中心
        默认端口号是 2181
      2. 提供者提供服务。
        1. 导入依赖。
       <dependency>     <groupId>org.apache.dubbogroupId>     <artifactId>dubbo-spring-boot-starterartifactId>     <version>2.7.3version> dependency>  <dependency>     <groupId>com.github.sgroschupfgroupId>     <artifactId>zkclientartifactId>     <version>0.1version> dependency>  <dependency>     <groupId>org.apache.curatorgroupId>     <artifactId>curator-frameworkartifactId>     <version>5.1.0version> dependency> <dependency>     <groupId>org.apache.curatorgroupId>     <artifactId>curator-recipesartifactId>     <version>5.1.0version> dependency> <dependency>     <groupId>org.apache.zookeepergroupId>     <artifactId>zookeeperartifactId>     <version>3.6.3version>          <exclusions>         <exclusion>             <groupId>org.slf4jgroupId>             <artifactId>slf4j-log4j12artifactId>         exclusion>     exclusions> dependency>
      1. 配置注册中心地址,提供者提供的服务名,需要扫描的包
      // application.ymlserver:   port: 8081dubbo:   application:     name: provider-server # 注册的服务应用名称   registry:     address: zookeeper://localhost:2181 # 注册中心地址   scan:     base-packages: com.sywl.service # 哪些服务要被注册
      1. 在想被注册的服务上面增加一个 dubbo 的@Service注解。
      import org.apache.dubbo.config.annotation.Service;// zookeeper:服务注册与发现@Service //dubbo的@sevice注解:可以被扫描到,在项目一启动就自动注册到注册中心public class TickerServiceImpl implements TicketService {@Overridepublic String getTicket() { return "你好啊";}}
      1. 消费者如何消费
        1. 导入依赖。
       <dependency>     <groupId>org.apache.dubbogroupId>     <artifactId>dubbo-spring-boot-starterartifactId>     <version>2.7.3version> dependency>  <dependency>     <groupId>com.github.sgroschupfgroupId>     <artifactId>zkclientartifactId>     <version>0.1version> dependency>  <dependency>     <groupId>org.apache.curatorgroupId>     <artifactId>curator-frameworkartifactId>     <version>5.1.0version> dependency> <dependency>     <groupId>org.apache.curatorgroupId>     <artifactId>curator-recipesartifactId>     <version>5.1.0version> dependency> <dependency>     <groupId>org.apache.zookeepergroupId>     <artifactId>zookeeperartifactId>     <version>3.6.3version>          <exclusions>         <exclusion>             <groupId>org.slf4jgroupId>             <artifactId>slf4j-log4j12artifactId>         exclusion>     exclusions> dependency>
      1. 配置注册中心地址,消费者自己的的服务名。
      // application.ymlserver:   port: 8082dubbo:   application:         name: consumer-server # 消费者去拿服务需要暴露自己的名字   registry:         address: zookeeper://localhost:2181 # 注册中心地址
      1. 从远程注入服务@Reference
      import org.springframework.stereotype.Service;@Service // 注入容器public class UserService {// 去注册中心拿provider-server提供的票@Reference //引用(远程调用),需要定义服务提供者路径相同的接口名TicketService tiketService;public void buyTiket(){ String ticket = tiketService.getTicket(); System.out.println("在注册中心拿到服务:"+ ticket);}}

      来源地址:https://blog.csdn.net/qq_34124252/article/details/126246129

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringBoot详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringBoot详解

前言 所有的技术框架的发展似乎都遵循了一条主线规律: 从一个复杂应用场景衍生一种规范框架, 人们只需要进行各种配置而不需要自己去实现它, 这时候强大的配置功能成了优点;发展到一定程度之后, 人们根据实际生产应用情况, 选取其中实用功能
2023-08-19

SpringBoot底层注解详解

这篇文章主要介绍了SpringBoot底层注解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
2023-05-20

SpringBoot各种注解详解

SpringBoot的一个核心功能是IOC,就是将Bean初始化加载到容器中,Bean是如何加载到容器的,可以使用SpringBoot注解方式或者SpringXML配置方式。SpringBoot注解方式减少了配置文件内容,更加便于管理,并且使用注解可以大大提高了开发效率
2022-12-27

SpringBoot整合MyBatisPlus详解

这篇文章详细介绍了SpringBoot整合mybatisplus的全过程,文中有详细的代码示例,具有一定的参考价值,需要的朋友可以参考一下
2023-05-16

SpringBoot Application核心注解详解

进入到@SpringBootApplication的源码,可以看到里面组合了三个我们感兴趣的注解@ComponentScan、@EnableAutoConfiguration、@SpringBootConfiguration,我们一一分析这三个注解
2022-11-13

详解SpringBoot的常用注解

详解SpringBoot的常用注解 在SpringBoot中,注解是一种非常重要的编程方式,它可以简化代码,提高开发效率。本文将详细介绍SpringBoot中的常用注解,以及它们的使用方法和场景。 1. @SpringBootApplica
2023-08-20

【SpringBoot】18张图,详解SpringBoot解析yml全流程

文章目录 加载监听器执行run方法加载配置文件封装Node调用构造器思考 前几天的时候,项目里有一个需求,需要一个开关控制代码中是否执行一段逻辑,于是理所当然的在yml文件中配置了一个属性作为开关,再配合nacos就可以随时
2023-08-16

springboot-controller的使用详解

Controller的使用一、 @Controller:处理http请求 @RestController:Spring4之后新加的注解,原来返回json需要@ResponseBody配合@Controller @RequestMapp
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录