当前位置: 首页 > news >正文

java6.1 springboot

目录

    • 1.概述
    • 2.初识springboot
        • 2.1 第一个 demo
        • 2.2 阅读源码
    • 3.配置文件
        • 3.1 配置文件优先级
        • 3.2 yaml语法结构
        • 3.3 JSR303校验
        • 3.4 自动装配原理
    • 4.springboot web开发
        • 4.1 静态资源导入
        • 4.2 模板引擎 Thymeleaf
        • 4.3 装配扩展SpringMVC
        • 4.4 拓展-国际化
        • 4.5 拦截器
        • 4.6 跨域
    • 5.spring Data
        • 5.1 JDBC
        • 5.2 Druid
        • 5.3 整合Mybatis
        • 5.4 Spring Security
        • 5.5 Shiro
        • 5.6 jwt
    • 6. Swagger
    • 7.任务
        • 7.1 异步
        • 7.2 定时
        • 7.3 发送邮件
    • 8.分布式
        • 8.1 Dubbo
        • 8.2 zookeeper

参考文档路径:https://www.yuque.com/atguigu/springboot

1.概述

【springBoot】

Spring Boot 就是一个javaweb的开发框架,其的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件。

【微服务架构】

微服务架构是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。它可以把一个大型的单个应用程序和服务拆分为数个甚至数十个的支持微服务,它可扩展单个组件而不是整个的应用程序堆栈,从而满足服务等级协议。

围绕业务领域组件来创建应用,这些应用可独立地进行开发、管理和迭代。在分散的组件中使用云架构和平台式部署、管理和服务功能,使产品交付变得更加简单。

2.初识springboot

2.1 第一个 demo

【方式一】

在这里插入图片描述

选择完成后点击generate创建并下载该项目,即可到idea中导入。

【方式二】

在这里插入图片描述

打开 IDEA,选择 Spring Initializr 创建项目。

【测试启动】

直接写一个controller,并在主函数中直接启动

在这里插入图片描述

【修改端口号】

在 application.properties 中添加以下代码

#更改项目端口号
server.port=8033

【彩蛋】

在 resources 下新建一个 banner.txt 文件,即可替换运行时的 spring logo
在这里插入图片描述

2.2 阅读源码

【自动装配】

pom.xml

  • spring-boot-dependencies:核心依赖在父工程中

  • dependency (依赖)中不需要指定版本,就是因为父工程中有版本仓库

  • 启动器:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

如果我们需要使用什么功能,就只需要导入对应的启动器(启动器会自动去导入依赖);比如spring-boot-starter-web就会自动导入web环境所有依赖。

主程序

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        //通过反射,加载该对象
        SpringApplication.run(DemoApplication.class, args);
    }
}
  • @SpringBootApplication

    • @SpringBootConfiguration >> springboot的配置

      • @Configuration >> spring配置类( 代替 springConfig.xml )

      **结论:**这个主程序也只是spring的一个组件,底层也是spring的配置

    • @EnableAutoConfiguration >> 自动装配的配置

      • @AutoConfigurationPackage >> 自动配置包

        • @Import({Registrar.class}) >> 导入注册器

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OTXsDm7H-1661850777128)(F:\study\note\img\image-20220816171849213.png)]

      • @Import({AutoConfigurationImportSelector.class}) >> 自动配置导入选择(核心)

      结论:springboot 所有的自动配置都是在启动的时候扫描并加载,所有的自动配置类都在 spring.factories(在spring-boot-autoconfigure 的 jar 包中)这里面,但不是全部都生效。要导入对应的启动器,自动装配才能生效。

    • @ComponentScan >> 扫描当前主启动类同级的包

  • main

    • init加载初始化
      1. 推断应用程序是否是web
      2. 加载所有可用初始化器
    1. 设置所有可用程序监听器
    2. 推断并设置main方法的定义类,找到运行的主类
    • 开始执行run方法
      1. 监听器初始化、启动
      2. 装配环境参数
      3. 打印banner
      4. 上下文相关配置处理

3.配置文件

springboot 适用一个全局的配置文件,文件名称是固定的。

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

3.1 配置文件优先级

【配置文件位置】

  1. file:./config/ 根目录下的config文件夹下创建
  2. file:./ 根目录下直接创建
  3. classpath:/config/ 资源包下的config文件夹下创建
  4. classpath:/ 资源包下直接创建(默认)

注:优先级1最高,4最低

【同优先级设置多套环境】

方式一:
在这里插入图片描述

方式二:

通过 --- 分隔多个配置文件

spring:
  profiles:
    active: test

server:
  port: 8080

---
spring:
  profiles: test

server:
  port: 8088

3.2 yaml语法结构

# 普通赋值  
key: value
# 对象赋值
student1:
  name: zheng
  age: 19
student2: {name: zheng,age: 18}
# 数组赋值
arr1:
  - num1
  - num2
arr2: [num1,num2]
# 锚点:&用来建立锚点,<<表示合并到当前数据,\*用来引用锚点
defaults: &defaults
  num1: 11
  num2: 22
a:
  database: mya
  <<: *defaults

b:
  database: myb
  <<: *defaults
# 以上关于锚点的配置等价于:
#defaults:
#  num1: 11
#  num2: 22
#a:
#  database: mya
#  num1: 11
#  num2: 22
#b:
#  database: myb
#  num1: 11
#  num2: 22

【举例】:适用 yaml 配置一个实体类

说明:@ConfigurationProperties:默认从全局配置文件中获取值

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String myname;
    private int myage;
    private Dog mydog;
    
    //...省略一个Dog实体类...
    //...省略该类的get/set/toString/构造器...
}

说明:${random.int} 是一个文件占位符,设置一个随机数,甚至可以是uuid

person:
  myname: zheng
  myage: ${random.int}
  mydog: {dname: 旺财,dage: 4}

【举一反三】

当有一个类似于 springConfig 的配置类时间,即可通过 yaml 的方式进行配置

3.3 JSR303校验

使用前,需导入对应的启动器

<dependency>
    <groupId>org.wildfly.swarm</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>1.0.0.Alpha2</version>
</dependency>

在这里插入图片描述

补充:

在这里插入图片描述

【举例】

@Component
@ConfigurationProperties(prefix = "login")
@Validated     //开启数据校验
public class Login {
    private String userName;
    @Length(min = 6, max = 19, message = "密码长度是6-18位")
    private String userPass;
    //...省略该类的get/set/toString/构造器...
}
login:
  user-name: zheng  # user-nam的写法松散语法,yaml支持松散语法
  user-pass: 123

3.4 自动装配原理

Springboot项目,都会有一个父项目管理依赖,父项目中定义了几乎所有常见依赖的版本(可自定义更改)。通过启动器spring-boot-starter,会按需加载该场景所需的依赖,然后导入到容器中。

而每一个starter中间接导入了autoconfigure依赖,它定义了所有依赖的默认配置。这些默认配置最终映射到某个名为 xxxProperties的类上。

总结

  1. springboot 启动会加载大量的自动配置类
  2. 我们只需要看我们需要的功能有没有在springboot默认写好的配置类中
  3. 再看自动配置类中装配了哪些组件
  4. 给容器中自动配置类添加组件时,会从properties(yaml)类中获取某些属性

4.springboot web开发

4.1 静态资源导入

  1. 存放于resources下的 resources、static、public(按优先级从高到低排列)文件夹中的静态资源,访问路径为http://localhost:8080/xxx即可直接访问文件夹下资源。

  2. 若添加yaml配置

  3. 配置yaml

spring:
  mvc:
    static-path-pattern: /diy/**

则访问路径为http://localhost:8080/diy/xxx

【首页及图标配置】

直接把首页 index.html 及图标 favicon.ico 放在某一个静态资源文件下即可生效。(注意命名规范)

4.2 模板引擎 Thymeleaf

【使用步骤 】

  1. 使用前,需导入对应的启动器
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  1. 并且在需要使用模板引擎的页面导入该头文件<html xmlns:th="http://www.https://www.thymeleaf.org">
  2. 在templates下创建一个html页面即可使用。

原理:模板引擎会解析字符串,加前缀 classpath:/templates/ ,及后缀 .html ,然后返回templates包中对应名称的html。注意的是该controller类注解只能是普通的组件,不能是@RestController。

【举个例子】

<!DOCTYPE html>
<html xmlns:th="http://www.https://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>home页面</title>
    <style>
        .box{
            color: #fc011a;
            font-size: 40px;
            margin-top: 100px;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="box">home</div>
    <div th:text="${msg}"></div>  //转义文本
    <div th:utext="${msg}"></div> //不转义文本
</body>
</html>
@RequestMapping("/homepage")
public String homepage(Model model){
    model.addAttribute("msg","<a href='https://www.baidu.com/'>百度一下</a>");
    return "home";
}

4.3 装配扩展SpringMVC

4.4 拓展-国际化

* 要提前将设置中 Editor > File Encodings 设置为utf-8

  1. 创建一组对应语言的properties配置文件(父文件名为xxx,则对应的中文文件名为xxx_zh_CN)

在这里插入图片描述

  1. 配置路径
spring:
  messages:
    basename: i18n.login
    encoding: UTF-8
  1. 通过链接携带参数,访问后台并传回页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.https://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" th:href="@{/style.css}">
</head>
<body>
    <div class="header" th:text="#{login.welcom}">welcome to my web!</div>
    <div class="links">
        <a th:href="@{/index.html(lang='zh_CN')}">中文</a>
        &nbsp; | &nbsp;
        <a th:href="@{/index.html(lang='en_US')}">English</a>
    </div>
</body>
</html>
  1. 自定义一个拦截器,并注入到配置中
public class MyLocaleResolver implements LocaleResolver {
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        String lang = request.getParameter("lang");
        Locale locale = Locale.getDefault();
        if(!StringUtils.isEmpty(lang)){
            String[] s = lang.split("_");
            locale = new Locale(s[0], s[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) { }
}
@Configuration
public class MyMvcConfig {
    @Bean
    public LocaleResolver localeResolver(){
        return new MyLocaleResolver();
    }
}

4.5 拦截器

public class LoginInterceptor implements HandlerInterceptor {
    /**
     *进入拦截器之前
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        //登录检查逻辑
        HttpSession session = request.getSession();
        Object loginUser = session.getAttribute("loginUser");
        if(loginUser != null){
            return true;
        }
        //拦截。未登录。跳转到登录页
        request.setAttribute("msg","请先登录");
        request.getRequestDispatcher("/").forward(request,response);
        return false;
    }

}
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //拦截所有,但排除登录页及静态资源
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**");
    }
}

4.6 跨域

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Bean
    public WebMvcConfigurer corsConfigurer()
    {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").
                        allowedOrigins("http://localhost:8080/"). //允许跨域的域名,可用*表示允许任何域名
                        allowedMethods("*"). //允许任何方法(post、get)
                        allowedHeaders("*"). //允许任何请求头
                        allowCredentials(true). //带上cookie信息
                    	//maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
                        exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); 
            }
        };
    }
}

5.spring Data

5.1 JDBC

  1. 导入 JDBC 和 mysql 启动器配置
<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>
  1. 配置数据源
spring:
  datasource:
    username: root
    password: 123
    url: jdbc:mysql://localhost:3306/batisdb?useUnicode=true&characterEncoding=utf8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
  1. 通过模板即可获取数据
@RestController
public class jdbcController {
    @Autowired
    JdbcTemplate jdbcTemplate;

    @RequestMapping("/userList")
    public List<Map<String,Object>> sqUser(){
        String sql="select * from user";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
        return maps;
    }
}

Hikari DataSource

默认情况下使用该数据源,号称是 Java Web 当前速度最快的数据源

5.2 Druid

描述:是阿里巴巴开源平台下的一个数据库连接池(数据源),加入了日志监控

特点:Druid可以很好的监控DB连接池和SQL的执行情况,天生就是针对监控而生的DB连接池。

  1. 导包
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.11</version>
</dependency>
  1. 配置(通过 type 切换数据源)
spring:
  datasource:
    username: root
    password: 123
    url: jdbc:mysql://localhost:3306/batisdb?useUnicode=true&characterEncoding=utf8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    #配置监控统计拦截的 filters: stat(监控统计),log4j(日志记录),wall(防御sql注入)
    #使用log4j需要导包
    filters: stat
  1. 通过配置类导入
@Configuration
public class DruidConfig {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druidDataSource(){
        return new DruidDataSource();
    }

    @Bean
    public ServletRegistrationBean statViewServlet(){
        ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
        HashMap<String, String> init = new HashMap<>();
        init.put("loginUsername","admin");
        init.put("loginPassword","123456");
        //允许访问
        init.put("allow","http://localhost:8080/");
        bean.setInitParameters(init);
        return bean;
    }
}

5.3 整合Mybatis

  1. 添加 mybatis 启动器配置
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.2</version>
</dependency>
  1. 配置别名及mapper位置
mybatis:
  type-aliases-package: com.zheng.pojo  #配置别名
  mapper-locations: classpath:mybatis/mapper/*.xml
  1. 编写程序(注意注解)

【user类省略…】

@Mapper
@Repository
public interface UserMapper {
    List<User> getAllUsers();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.zheng.mapper.UsersMapper">

    <select id="getUserList" resultType="Users">
        select * from users
    </select>
</mapper>
@Autowired
UserMapper userMapper;
@RequestMapping("/users")
public List<User> myUser(){
    List<User> allUsers = userMapper.getAllUsers();
    return allUsers;
}

5.4 Spring Security

安全问题 ==> 认证(authentication)、授权(authorization) [ 代替 拦截器、过滤器 实现功能 ]

SpringSecurity是针对spring项目的安全框架,也是spring boot底层安全模块的默认选型,它可以实现强大的web安全控制。

  1. 添加启动类
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 编码
  • WebSecurityConfigurerAdapter:自定义 security 策略
  • AuthenticationManagerBuilder:自定义认证策略
  • @EnableWebSecurity:开启webSecurity模式
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //请求授权的规则
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3");
        //没有权限时,跳转到登录页。触发登录默认跳转路径"/login",自定义登录页"/toLogin“
        //修改了登录页之后,用户提交的表单路径也要改成“/toLogin”
        //同时表单对应name属性用户名:username ,密码:password ,记住我:remember
        http.formLogin().loginPage("/toLogin");
        //开启注销功能  注销功能提交url路径"/logout"
        http.logout().logoutSuccessUrl("/");
        //开启记住我功能
        http.rememberMe();
    }
    //认证
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("youke").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1")
                .and()
                .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3");
    }
}

5.5 Shiro

  • Apache Shiro 是一个java的安全框架

【】核心方法

  1. 获取对象:Subject currentUser = SecurityUtils.getSubject();
  2. 获取session:currentUser.getSession();
  3. 判断用户是否认证:currentUser.isAuthenticated();
  4. 获取用户认证:currentUser.getPrincipal();
  5. 获取用户拥有角色:currentUser.hasRole(“参数”);
  6. 获取用户权限:currentUser.isPermitted(“…”);
  7. 注销用户:currentUser.logout();

【】三大对象

  1. Subject 当前用户

  2. SecurityManager 安全管理(管理用户)

  3. Realm 连接数据

  1. 导入jar包
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.9.1</version>
</dependency>
  1. 编码

【代码注释】

拦截 === 添加shiro的内置过滤器
anon(无需认证即可访问)
authc(认证才能访问)
user(有 记住我 功能才能访问)
perms(拥有对某个资源的权限才能访问)
role(拥有某个角色权限才能访问)

授权与认证:shiro中用户的授权、认证需要放在realm中,即请求都在config中进行过滤,但是真正的权限操作需要在realm中进行,它会将config类和realm类联动起来

public class UserRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("用户授权=====");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //通过subject获取当前用户——在认证时注入的用户
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User)subject.getPrincipal();
        info.addStringPermission(currentUser.getPerms());
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //假数据
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("admin", "123456", "user:add"));
        users.add(new User("zheng", "123456", ""));
        User LoginUser = null;

        //调用 subject.login(token); 会进入这里做认证
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        String username = token.getUsername();
        System.out.println("用户认证====="+username);
        //查询用户,如果找不到用户就返回 null
        for (User user : users) {
            if (user.getName().equals(username))LoginUser=user;
        }
        if (LoginUser==null)return null;
 		//密码认证shiro不允许我们自己进行,我们只能将我们设置好的密码传进去
        return new SimpleAuthenticationInfo(LoginUser,LoginUser.getPass(),"");
    }
}

配置类

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shiroFactory(@Qualifier("securityManager") DefaultWebSecurityManager manager){
        ShiroFilterFactoryBean shiroFactory = new ShiroFilterFactoryBean();
        shiroFactory.setSecurityManager(manager);
        Map<String, String> map = new LinkedHashMap<>();
        map.put("/toPage1","anon");  //请求路径,设置访问权限
        map.put("/toPage2","authc");
        map.put("/toPage3","perms[user:add]");
        shiroFactory.setFilterChainDefinitionMap(map);
        shiroFactory.setLoginUrl("/toLogin"); //登录请求页

        return shiroFactory;
    }
    @Bean
    public DefaultWebSecurityManager securityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(userRealm);
        return manager;
    }
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }
}

处理请求:前端参数的获取需要我们在controller中进行,所以我们需要在controller中写一个获取前端参数,调用shiro进行用户认证

@RequestMapping("/login")
public String login(String username, String password, Model model){
    System.out.println("用户登录——"+username);
    //获取当前用户
    Subject subject = SecurityUtils.getSubject();
    //封装用户的登录数据
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    try{
        subject.login(token);  //>>  进入用户认证
        return "index";
    }catch (UnknownAccountException e){
        model.addAttribute("msg","用户名错误!");
    }catch (IncorrectCredentialsException e){
        model.addAttribute("msg","密码错误!");
    }
    return "login";
}
@RequestMapping("/logout")
public String logout(Model model){
    SecurityUtils.getSubject().logout();    //注销
    model.addAttribute("msg","请重新登录!");
    return "login";
}

5.6 jwt

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
/**
 * String secret;  //密钥
 * long expireHour;//有效时间(小时)
 * String header;
 */
@Component
@ConfigurationProperties(prefix = "markerhub.jwt")
public class JwtUtil {
    private String secret;
    private long expireHour;
    private String header;

    /**
     * 生成token
     */
    public String generateToken(long id){
        Date now = new Date();
        Date expireDate = new Date( now.getTime()+(expireHour*1000*60*60) );
        return Jwts.builder()
                .setHeaderParam("typ","JWT")
                .setSubject(id+"")
                .setIssuedAt(now)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512,secret)
                .compact();
    }
    /**
     * token校验
     */
    public Claims getClaimByToken(String token){
        try {
            return Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        }catch (Exception e){
            return null;
        }
    }
    /**
     * token是否过期
     */
    public boolean isTokenExpired(Date expiration){
        return expiration.before(new Date());
    }

}

6. Swagger

  1. 导包
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

需要加上这个配置

  1. 编码

【代码注释】

RequestHandlerSelectors:配置要扫描的接口

  • any() 全部扫描
  • none() 全部不扫描
  • basePackage(“com.zheng.controller”) 指定要扫描的包
  • withClassAnnotation(PostMapping.class) 扫描类上的注解,参数是一个注解的反射对象
  • withMethodAnnotation() 扫描方法上的注解,参数是一个注解的反射对象

配置文件:(基本信息;分组;启动阀;选择扫描条件及过滤)

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    //Docket可以有多个,对应其分组名groupName,可用于对api进行分类
    @Bean
    public Docket docketPost(Environment environment){
        //判断当前环境是否处于“dev”环境,用以开启和关闭swagger
        boolean flag = environment.acceptsProfiles(Profiles.of("dev"));
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("post")  //设置组名可进行分组
                .enable(flag)  //是否启动swagger
                .select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(PostMapping.class))
                //.paths(PathSelectors.ant("/zheng/**"))   //过滤的路径
                .build();
    }
    @Bean
    public Docket docketGet(Environment environment){
        //判断当前环境是否处于“dev”环境,用以开启和关闭swagger
        boolean flag = environment.acceptsProfiles(Profiles.of("dev"));
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .groupName("get")
                .enable(flag)  //是否启动swagger
                .select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(GetMapping.class))
                .build();
    }
    private ApiInfo apiInfo(){
        return new ApiInfo("Api 文档",
                "Api 文档",
                "v1.0",
                "urn:tos",
                new Contact("", "", ""),
                "返回首页",
                "http://localhost:8081",
                new ArrayList());
    }
}
  1. 配置
spring:
    mvc:
      pathmatch:
        matching-strategy: ant_path_matcher
  1. 注解

@Api(tags = “登录及注销”) //用于类上

@ApiOperation(“处理登录请求api”) //用于方法上

7.任务

7.1 异步

@EnableAsync(开启异步注解)

@Async(异步方法上添加)

在异步方法上加注解@Async,并在main方法上加@EnableAsync注解开启异步注解。

7.2 定时

@EnableScheduling(开启定时功能的注解)

@Scheduled(什么时候执行)

cron表达式

在service中编写一个需要设置定时的方法,为该方法添加@Scheduledz注解,并且为该注解传入cron参数。最后在main方法上加@EnableScheduling注解开启定时功能的注解。

//每秒执行10次
@Scheduled(cron = "0/10 * * * * ?")
public void timeTest(){
    System.out.println("启动...");
}

7.3 发送邮件

导入启动器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

配置

spring:
  mail:
    username: 2655244515@qq.com
    password: fgbmxpydemynebhj
    host: smtp.qq.com
#    qq需要开启加密验证
spring.mail.properties.mail.smtp.ssl.enable: true

编码

@Autowired
JavaMailSender mailSender;

//一般邮件
@Test
void contextLoads1() {
    SimpleMailMessage mailMessage = new SimpleMailMessage();
    mailMessage.setSubject("heading...");
    mailMessage.setText("正文正文...");
    mailMessage.setTo("lxt4132@sina.com");
    mailMessage.setFrom("2655244515@qq.com");
    mailSender.send(mailMessage);
}
//添加附件邮件
@Test
void contextLoads2() throws MessagingException {
    MimeMessage mimeMessage = mailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
    helper.setSubject("headin。。。");
    helper.setText("你好","<span style='color:red;'>你好啊</span>");
    //附件
    helper.addAttachment("a.png",new File("B:\\bg\\a.png"));

    helper.setTo("lxt4132@sina.com");
    helper.setFrom("2655244515@qq.com");

    mailSender.send(mimeMessage);
}

8.分布式

分布式定义:分布式系统就是若干个独立计算机的集合,这些计算机对用户而言就像单个相关系统。它是通过网络进行通信、为完成共同的任务而协调工作的计算机节点组成的系统。

RPC(远程过程调用):是一种进程间的通信方式,它允许程序调用另一个地址空间的过程或函数,而不用程序员显式的编码这个远程调用的细节。即使得程序员本地调用和远程调用的代码基本相同。

RPC核心:通讯、序列化。

RPC与HTTP的区别:RPC是一种技术思想,而非一种规范和协议。

8.1 Dubbo

  • dubbo是一款高性能、轻量级的开源java RPC框架
  • 它提供三大核心能力:
    • 面向接口的远程方法调用
    • 智能容错和负载均衡
    • 服务自动注册和发现

8.2 zookeeper

  • zookeeper是一个分布式应用程序协调服务,提供服务的注册与发现

下载及安装:https://www.runoob.com/w3cnote/zookeeper-setup.html

【dubbo+zookeeper开发】

  • 需要先安装zookeeper,并运行
  1. 导入依赖
        <!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-spring-boot-starter -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.12.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
  1. 配置
server.port=8081

#服务应用名字
dubbo.application.name=provider-server
#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
#哪些服务要被注册
#客户端不需要登记扫描包
dubbo.scan.base-packages=com.zheng.service
  1. 定义一个接口并实现,然后通过注解将服务暴露服务
@Service     //import org.apache.dubbo.config.annotation.Service; 暴露服务
@Component   //import org.springframework.stereotype.Component;  注册bean
public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello() {
        return null;
    }
}
  1. 客户端也需要如上同样的依赖、配置及接口
@Service   //import org.springframework.stereotype.Service;  注册bean
public class UserService {
    @Reference  //远程调用
    DemoService demoService;  //和服务端一样的接口,需要在同样的路径中定义

    public void getTiket(){
        System.out.println("客户端:"+demoService.sayHello());
    }
}

* 注意:后续dubbo版本更新后,注解需要改变

相关文章:

  • Linux高性能服务器之I/O复用之实例 ET AND LT(图像理解)(14)
  • 计算机毕业设计django基于python大学生心理健康系统(源码+系统+mysql数据库+Lw文档)
  • java计算机毕业设计个性化推荐的扬州农业文化旅游管理平台源码+数据库+系统+lw文档+mybatis+运行部署
  • C#进阶03——常用泛型数据结构类
  • 第4章Linux实操篇-远程登录到Linux服务器
  • 【FPGA教程案例66】硬件开发板调试6——基于FPGA的UDP网口通信和数据传输
  • 第2章Linux基础篇-VM和Linux的安装
  • [NOI2022] 众数 题解
  • linux文件IO
  • 自已定义一个Java异常——子定义异常,和异常遇到的面试题。
  • 计算机视觉+人工智能面试笔试总结——目标检测/图像处理基础题
  • 【html】面试问题总结
  • Python:for循环语句
  • 第9章Linux实操篇-组管理和权限管理
  • java计算机毕业设计基于安卓Android/微信小程序的产后康复APP
  • [LeetCode] Wiggle Sort
  • django开发-定时任务的使用
  • node-glob通配符
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • webpack4 一点通
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 给第三方使用接口的 URL 签名实现
  • 聊聊redis的数据结构的应用
  • 驱动程序原理
  • 如何设计一个比特币钱包服务
  • 入门级的git使用指北
  • 双管齐下,VMware的容器新战略
  • 我建了一个叫Hello World的项目
  • 优秀架构师必须掌握的架构思维
  • ​如何在iOS手机上查看应用日志
  • ​香农与信息论三大定律
  • #《AI中文版》V3 第 1 章 概述
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (论文阅读40-45)图像描述1
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (三分钟)速览传统边缘检测算子
  • .apk文件,IIS不支持下载解决
  • .NET delegate 委托 、 Event 事件
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • @GetMapping和@RequestMapping的区别
  • [20150629]简单的加密连接.txt
  • [Android Pro] AndroidX重构和映射
  • [hive] sql中distinct的用法和注意事项
  • [jQuery]使用jQuery.Validate进行客户端验证(中级篇-上)——不使用微软验证控件的理由...
  • [LeetCode]—Anagrams 回文构词法
  • [LeetCode]Multiply Strings
  • [linux运维] 利用zabbix监控linux高危命令并发送告警(基于Zabbix 6)
  • [PAT] 1041 Be Unique (20 分)Java
  • [Phoenix] 七、如何使用自增ID
  • [Python]Django类视图
  • [Python基础]Python文件处理小结
  • [Redis]——数据一致性,先操作数据库,还是先更新缓存?
  • [VulnHub靶机渗透] Nullbyte