狂神说java --springboot笔记

狂神说Java SpringBoot

狂神说SpringBoot01:Hello,World!

狂神说SpringBoot02:运行原理初探

狂神说SpringBoot03:yaml配置注入

狂神说SpringBoot04:JSR303数据校验及多环境切换

狂神说SpringBoot05:自动配置原理

狂神说SpringBoot06:自定义starter

狂神说SpringBoot07:整合JDBC

狂神说SpringBoot08:整合Druid

狂神说SpringBoot09:整合MyBatis

狂神说SpringBoot10:Web开发静态资源处理

狂神说SpringBoot11:Thymeleaf模板引擎

狂神说SpringBoot12:MVC自动配置原理

狂神说SpringBoot13:页面国际化

狂神说SpringBoot14:集成Swagger终极版

狂神说SpringBoot15:异步、定时、邮件任务

狂神说SpringBoot16:富文本编辑器

狂神说SpringBoot17:Dubbo和Zookeeper集成

狂神说SpringBoot18:集成SpringSecurity

一、运行原理初探

注解:

狂神说java --springboot笔记_第1张图片

//获取所有配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes);

 

获取候选配置:

    protected 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;
    }

二、JSR303数据校验及多环境切换

  1. 配置文件加载位置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Nr27xHV-1594913883189)(D:\我\MyBlog\狂神说Java SpringBoot.assets\image-20200709213144157.png)]

​ file : 文件路径,就是项目路径

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MmY445bN-狂神说java --springboot笔记_第2张图片

三、SpringBoot Web开发

自动装配:

SpringBoot到底帮我们配置了什么?我们能不能进行修改?能修改哪些东西?能不能扩展?

  • xxxAutoConfiguration…向容器中自动配置组件
  • xxxProperties:自动配置类,装配配置文件中自定义的一些内容

要解决的问题:

  • 导入静态资源…

  • 首页

  • jsp, 模板引擎Thymeleaf

    thymeleaf依赖

  • 装配扩展SpringMVC

  • 增删改查

  • 拦截器

  • 国际化

四、员工管理系统

  1. 首页配置
    1. 注意点,所有页面的静态资源都需要使用thymeleaf接管;(导入thymeleaf依赖)
    2. url: @{}
  2. 页面国际化
    1. 我们需要配置i18n文件
    2. 我们如果需要在项目中进行按钮自动切换,我们需要自定义一个组件LocaleResolver
    3. 记得将自己写的组件配置到spring容器@Bean
    4. #{}

五、整合MyBatis

整合包

mybatis-spring-boot-starter

  1. 导入包

    
    <dependency>
        <groupId>org.mybatis.spring.bootgroupId>
        <artifactId>mybatis-spring-boot-starterartifactId>
        <version>2.1.1version>
    dependency>
    
  2. 配置yml文件

    application.yml

    # 配置spring自带的数据源
    spring:
      datasource:
        username: root
        password: root
        url: jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
        driver-class-name: com.mysql.cj.jdbc.Driver
    
    # 整合mybatis
    mybatis:
      # 别名
      type-aliases-package: com.kuang.pojo
      # mapper文件位置
      mapper-locations: classpath:mybatis/mapper/*.xml
    
  3. mybatis配置

    • User

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {
          private int id;
          private String name;
          private String password;
      }
      
    • UserMapper接口

      @Repository
      @Mapper
      public interface UserMapper {
          public User queryUserByName(String name);  
      }
      
    • UserMapper.xml配置文件

      
      <mapper namespace="com.kuang.mapper.UserMapper">
          <select id="getUserList" resultType="com.kuang.pojo.User" parameterType="String">
          select * from USER where name = #{name}
        	select>
      mapper>
      
  4. 编写sql

  5. service层调用dao层

    • UserService 接口

      public interface UserService {
          public User queryUserByName(String name);
      }
      
    • UserServiceImpl实现类

      @Service
      public class UserServiceImpl implements UserService{
          @Autowired
          UserMapper mapper;
          public User queryUserByName(String name) {
              User user = mapper.queryUserByName(name);
              return user;
          }
      }
      
  6. controller调用service层

    @Autowired
    UserServiceImpl userService;
    public void mian(String args[]){
        User user = userService.queryUserByName("dog");
    }
    

六、SpringSecurity

  1. 引入 Spring Security 模块

  2. 编写 Spring Security 配置类

    参考官网:https://spring.io/projects/spring-security

  3. 编写基础配置类

    • 定制请求的授权规则
    • 定义认证规则
    //AOP : 拦截器
    @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");
    
            //没有权限默认会到登录页面,需要开启登录的页面
            http.formLogin()
                    .loginPage("/toLogin")
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .loginProcessingUrl("/login");
    
            http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求
            // 开启注销功能
            http.logout().logoutSuccessUrl("/");
            //开启记住我功能
            http.rememberMe().rememberMeParameter("rememberme");
        }
    
        //认证
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       //在内存中定义,也可以在jdbc中去拿....
       //Spring security 5.0中新增了多种加密方式,也改变了密码的格式。
       //要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
       //spring security 官方推荐的是使用bcrypt加密方式。
    
            auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                    .withUser("kuangshen").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
                    .and()
                    .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
                    .and()
                    .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
        }
    }
    

七、Shiro

  • Subject 用户
  • SecurityManager 管理用户
  • Realm 连接数据
    狂神说java --springboot笔记_第3张图片
    简单实验:
  1. 导入依赖

    <dependency>
        <groupId>org.apache.shirogroupId>
        <artifactId>shiro-springartifactId>
        <version>1.5.3version>
    dependency>
    
  2. 编写Shiro配置类

    @Configuration
    public class ShrioConfig {
        //ShiroFilterFactoryBean : Step3
        @Bean
        public ShiroFilterFactoryBean getShrioFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            //设置安全管理器
            bean.setSecurityManager(defaultWebSecurityManager);
            return bean;
        }
        
        //DefaultWebSecurityManager : Step2
        @Bean("securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联userRealm
            securityManager.setRealm(userRealm);
            return securityManager;
        }
        
        //创建 realm 对象, 需要自定义类:Step1
        @Bean
        public UserRealm userRealm(){
            return new UserRealm();
        }
    }
    
  3. 自定义UserRealm

    //自定义的 UserRealm
    public class UserRealm extends AuthorizingRealm {
    
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            return null;
        }
    
        //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            return null;
        }
    }
    

一个小Demo:

  1. 导入依赖

    • springboot-mybatis整合
    • shiro-thymelea整合
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
        <parent>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-parentartifactId>
            <version>2.3.1.RELEASEversion>
            <relativePath/> 
        parent>
        <groupId>com.kuanggroupId>
        <artifactId>shiro-springbootartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>shiro-springbootname>
        <description>Demo project for Spring Bootdescription>
    
        <properties>
            <java.version>1.8java.version>
        properties>
    
        <dependencies>
            
            <dependency>
                <groupId>com.github.theborakompanionigroupId>
                <artifactId>thymeleaf-extras-shiroartifactId>
                <version>2.0.0version>
            dependency>
    
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>8.0.20version>
            dependency>
            
            <dependency>
                <groupId>log4jgroupId>
                <artifactId>log4jartifactId>
                <version>1.2.17version>
            dependency>
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druidartifactId>
                <version>1.1.22version>
            dependency>
            
            <dependency>
                <groupId>org.mybatis.spring.bootgroupId>
                <artifactId>mybatis-spring-boot-starterartifactId>
                <version>2.1.1version>
            dependency>
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>1.18.12version>
            dependency>
            <dependency>
                <groupId>org.apache.shirogroupId>
                <artifactId>shiro-springartifactId>
                <version>1.5.3version>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-thymeleafartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintagegroupId>
                        <artifactId>junit-vintage-engineartifactId>
                    exclusion>
                exclusions>
            dependency>
        dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                plugin>
            plugins>
        build>
    
    project>
    
  2. 整合MyBatis

    • 编写实体类
    • 编写mapper接口、mapper.xml、application.yml配置mybatis(别名,mapper.xml文件位置)
    • 编写service接口,serviceImpl类
      狂神说java --springboot笔记_第4张图片
  3. 编写Shiro配置类

    @Configuration
    public class ShrioConfig {
    
        //ShiroFilterFactoryBean : Step3
        @Bean
        public ShiroFilterFactoryBean getShrioFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            //设置安全管理器
            bean.setSecurityManager(defaultWebSecurityManager);
    
            //添加shiro的内置过滤器
            /*
                anno: 无需认证就可以访问
                authc: 必须认证了才可以访问
                user: 必须拥有 记住我 功能才能用
                perms: 拥有对某个资源的权限才能访问
                role: 拥有某个角色权限才能访问
            */
    
            Map<String, String> filterMap = new LinkedHashMap<>();
    
            //用户授权,正常情况下没有授权会跳转到授权页面
            filterMap.put("/user/add","perms[user:add]");
            filterMap.put("/user/update","perms[user:update]");
    
            //拦截
            //filterMap.put("/user/add","authc");
            //filterMap.put("/user/update","authc");
            filterMap.put("/user/*","authc");
    
            //设置登录请求
            bean.setLoginUrl("/toLogin");
            //设置未授权页面
            bean.setUnauthorizedUrl("/noauth");
            bean.setFilterChainDefinitionMap(filterMap);
            return bean;
        }
    
        //DefaultWebSecurityManager : Step2
        @Bean("securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联userRealm
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    
        //创建 realm 对象, 需要自定义类:Step1
        @Bean
        public UserRealm userRealm(){
            return new UserRealm();
        }
    
        //整合 ShiroDialect:用来整合shiro thymeleaf
        @Bean
        public ShiroDialect getShiroDialect(){
            return new ShiroDialect();
        }
    }
    
  4. 自定义UserRealm

    //自定义的 UserRealm
    public class UserRealm extends AuthorizingRealm {
    
        @Autowired
        UserServiceImpl userService;
    
        //授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            System.out.println("执行了 => doGetAuthorizationInfo");
    
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            // 拿到当前登录的这个对象
            Subject subject = SecurityUtils.getSubject();
            // 拿到User对象
            User currentUser = (User) subject.getPrincipal();
            // 设置当前用户的权限
            System.out.println(currentUser.getName() + "的权限为 " + currentUser.getPerms());
            info.addStringPermission(currentUser.getPerms());
    
            return info;
        }
    
        //认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("执行了 => 认证AuthenticationToken");
    
            UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
            //连接真实的数据库
            User user = userService.queryUserByName(userToken.getUsername());
            if(user == null){
                //没有这个人
                return null; //抛出异常 UnknownAccountException
            }
    
            // 登录成功 将用户信息存入session
            Subject currentSubject = SecurityUtils.getSubject();
            Session session = currentSubject.getSession();
            session.setAttribute("loginUser",user.getName());
    
            // 密码认证,shiro做
            return new SimpleAuthenticationInfo(user,user.getPassword(),"");
        }
    }
    

八、Swagger

学习目标:

  • 了解Swagger的作用和概念
  • 了解前后端分离
  • 在SpringBoot中集成Swagger

一、 Swagger简介

前后端分离时代:

  • 后端:后端控制层,服务层,数据访问层
  • 前端:前端控制层,视图层

Swagger :

  • 号称世界上最流行的API框架;
  • RestFul Api文档在线自动生成工具 => Api文档与Api定义同步更新
  • 直接运行,可以在线测试API接口
  • 支持多种语言:(Java , Php…)

在项目中使用Swagger需要Springbox

  • swagger2
  • ui

二、SpringBoot集成Swagger

  1. 新建一个SpringBoot - web 工程

  2. 导入相关依赖

    
    <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>
    
    
  3. 编写一个Hello工程

  4. 配置Swagger ==> Config

    @Configuration
    @EnableSwagger2 //开启Swagger
    public class SwaggerConfig {
      
    }
    
  5. 测试运行:http://localhost:8080/swagger-ui.html

三、 配置Swagger信息

@Configuration
@EnableSwagger2 //开启Swagger
public class SwaggerConfig {
    //配置了Swagger 的Docket的bean实例
    @Bean
    public Docket docket(){
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
    }
    
    //配置Swagger信息=apiInfo
    public ApiInfo apiInfo(){
        //作者信息
        Contact contact = new Contact("Daniel","https://www.baidu.com","[email protected]");
        return new ApiInfo("Dainel的SwaggerAPI文档",
                "天道酬勤",
                "v1.0",
                "urn:tos",
                contact, "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0",
                new ArrayList());
    }
}

四、 Swagger配置扫描接口

Docket.select()

//配置了Swagger 的Docket的bean实例
@Bean
public Docket docket(){
    return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
        .select()
        //RequestHandlerSelectors,配置要扫描接口的方式
        //basePackage,指定要扫描的包
        //any(): 扫描全部
        .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
        .paths(PathSelectors.ant("/kuang/**"))
        .build();
}

题目:我只希望我的Swagger在生产环境中使用,在发布的时候不使用

  • 判断是不是生产环境 flag = false
  • 注入enable (flag)
//配置了Swagger 的Docket的bean实例
@Bean
public Docket docket(Environment environment){

    //设置要显示的Swagger环境
    Profiles profiles = Profiles.of("dev","test");
    //通过  environment.acceptsProfiles 判断是否处在自己设定的环境中
    boolean flag = environment.acceptsProfiles(profiles);
    ...
}

狂神说java --springboot笔记_第5张图片

配置API文档的分组

.groupName("狂神")
  •  

如何配置多个分组;多个Docket实例即可
狂神说java --springboot笔记_第6张图片

五、 接口注释

狂神说java --springboot笔记_第7张图片
总结:

  1. 我们可以通过Swagger给一些比较难理解的属性或者接口,增加注释信息;
  2. 接口文档实时更新
  3. 可以在线测试

Swagger是一个优秀的工具,几乎所有的大公司都有使用它

【注意点】在正式发布的时候,关闭Swagger!!出于安全考虑,而且节省运行的内存。

九、任务

一、异步任务

  1. 给要实现异步任务加上注解 @Async

    @Service
    public class AsyncService {
        @Async
        public void hello(){
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("数据正在处理...");
        }
    }
    
  2. 在main方法开启异步功能 @EnableAsync

    @EnableAsync // 开启异步注解功能
    @SpringBootApplication
    public class Springboot09TaskApplication {
        public static void main(String[] args) {
            SpringApplication.run(Springboot09TaskApplication.class, args);
        }
    }
    

二、邮件任务

  1. 导入依赖

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-mailartifactId>
    dependency>
    
  2. 配置邮箱和密码

    [email protected]
    spring.mail.password=xxyyzzhhll
    spring.mail.host=smtp.qq.com
    # 开启加密验证
    spring.mail.properties.mail.smtp.ssl.enable=true
    
  3. 测试发送邮件(组合邮件,带附件)

    @SpringBootTest
    class Springboot09TaskApplicationTests {
    
        @Autowired
        JavaMailSenderImpl mailSender;
    
        @Test
        void contextLoads2() throws MessagingException {
    
            //一个复杂的邮件
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            //组装
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            //正文
            helper.setSubject("Test");
            helper.setText("

    这是一封测试邮件

    "
    ,true); //附件 helper.addAttachment("data1",new File("D:\\testdata\\2017-01-01.xls")); helper.setTo("[email protected]"); helper.setFrom("[email protected]"); mailSender.send(mimeMessage); }

三、定时任务

  1. TaskScheduler 任务调度者
  2. TaskExecutor 任务执行者
  3. @EnableScheduling 开启定时功能的注解
  4. @Scheduled 什么时候执行
  5. Cron表达式
  1. 编写定时服务

    @Service
    public class ScheduledService {
    
        //在一个特定的时间执行这个方法
    
        //cron 表达式
        //秒 分 时 日 月 周几
    
        /*
            30 17 17 * * ?  每天10点15分30 执行一次
            30 0/5 10,18 * * ?  每天10点和18点,每隔五分钟执行一次
        */
    
        @Scheduled(cron = "30 17 17 * * ?")
        public void Hello(){
            System.out.println("hello,被执行了!");
        }
    
    }
    
  2. 在启动类开启定时功能

    @EnableAsync // 开启异步注解功能
    @EnableScheduling //开启定时功能的注解
    @SpringBootApplication
    public class Springboot09TaskApplication {
        public static void main(String[] args) {
            SpringApplication.run(Springboot09TaskApplication.class, args);
        }
    }
    

十、整合Redis

单独整理

十一、分布式Dubbo + Zookeeper

zookeeper :注册中心

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

Dubbo:jar包

步骤:

前提:zookeeper服务已启动

  1. 提供者提供服务

    • 导入依赖

    • 配置注册中心的地址,以及服务发现名,和要扫描的包

      狂神说java --springboot笔记_第8张图片

    • 在想要被注册的服务上面,再增加一个注解**@Service**(dubbo包下的)

  2. 消费者如何消费

    • 导入依赖

    • 配置注册中心的地址,配置自己的服务名
      狂神说java --springboot笔记_第9张图片

    • 从远程注入服务 @Reference

回顾总结:三层架构   + MVC

  架构 -->  解耦

    开发框架:

                   Spring:

                        Ioc(控制反转)  + Aop(面向切面编程)[本质:动态代理]

               Ioc(控制反转)

                     以前自己是new 对象,现在交给spring ioc容器统一管理,我们需要什么直接去拿  ioc容器就像是一个对象工厂,把对象交给工厂,工程管理对象的创建以及依赖关系,我们需要的时候直接去工厂中获取   

                    [控制反转,依赖注入]   控制反转:是一种思想,原本自己控制的事情,交给ico控制  ,依赖注入是控制反转的实现方式【对象】无需自行创建或者管理依赖关系,依赖关系将被自动注入到需要他们的对象当中

                    :将对象统一管理  :降低耦合

            Aop(面向切面编程)[本质:动态代理]

                  解决非业务代码抽取的问题,底层是动态代理,在spring内实现依赖是BeanPostProcessor ,在方法前后增加非业务代码

      spring是轻量型的java的开源框架,容器

负载均衡

微服务架构存在的问题:

  • 分布式架构会遇到的四个核心问题
  • 这么多服务,客户端该如何去访问
  • 这么多服务,服务之间如何进行通信
  • 这么多服务,如何管理
  • 服务挂了,该怎么办

==》 解决方案:

​ SpringCloud,是一套生态,就是用来解决以上分布式架构的4个问题。

​ 想使用SpringCloud,必须掌握SpringBoot,因为SpringCloud是基于SpringBoot的

1. API网关,服务路由
2. HTTP,RPC框架,异步调用
3. 服务注册与发现,高可用
4. 熔断机制,服务降级

你可能感兴趣的:(spring,boot,java)