SpringBoot笔记(狂神说)

SpringBoot部分知识

基础

自动配置原理

pom.xml:

  • spring-boot-dependencies:核心依赖在父工程中
  • 引入SpringBoot依赖时,不需要指定版本,就是因为有这些版本仓库

启动器:

        
            org.springframework.boot
            spring-boot-starter-web
        
  • 就是SpringBoot的启动场景
  • 会自动帮我们导入该模块的所有依赖

启动类:

  • @SpringBootApplication:标注这个类是一个SpringBoot应用
两个核心注解:
@SpringBootConfiguration:SpringBoot的配置
	@Configuration:Spring配置类
		@Component:说明这也是一个Spring的组件
@EnableAutoConfiguration:自动配置
	@AutoConfigurationPackage:自动导入包
		@Import(AutoConfigurationPackages.Registrar.class):导入选择器
			metadata:源数据
     @Import(EnableAutoConfigurationImportSelector.class):自动配置导入选择
     	AutoConfigurationImportSelector:
     				List configurations = getCandidateConfigurations(annotationMetadata,attributes);//获取所有的配置
	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), 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;
	}

​ META-INF/spring.factories:自动配置的核心

SpringBoot笔记(狂神说)_第1张图片

@ConfigurationProperties

/*
@ConfigurationProperties作用:
将配置文件中配置的每一个属性的值,映射到这个组件中;
告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
*/
@Component //注册bean  必须要添加这个注解
@ConfigurationProperties(prefix = "person")
public class Person {
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
}

JSR303数据校验

--示例
@Validated  //数据校验
public class Person {

    @Email(message="邮箱格式错误") //email必须是邮箱格式,message是报错信息
    private String email;
}
--常见参数
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;

空检查
@Null       验证对象是否为null
@NotNull    验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank   检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty   检查约束元素是否为NULL或者是EMPTY.
    
Booelan检查
@AssertTrue     验证 Boolean 对象是否为 true  
@AssertFalse    验证 Boolean 对象是否为 false  
    
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内  
@Length(min=, max=) string is between min and max included.

日期检查
@Past       验证 Date 和 Calendar 对象是否在当前时间之前  
@Future     验证 Date 和 Calendar 对象是否在当前时间之后  
@Pattern    验证 String 对象是否符合正则表达式的规则

邮件任务

  1. 导入依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
  1. 在邮箱中开启POP3/SMTP服务

    将授权码作为邮箱密码

  2. 配置邮箱

  mail:
    username: 1558647481@qq.com
    password: hnbikvdksulfjeih  #可以是授权码 也可以是密码
    host: smtp.qq.com
    #开启加密授权验证
    properties:
      mail.smtp.auth: true
  1. 测试
    @Autowired
    JavaMailSenderImpl mailSender;

    @Test
    void contextLoads() {

        //一个简单的邮件
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setFrom("[email protected]");
        mailMessage.setTo("[email protected]");
        mailMessage.setSubject("主题");
        mailMessage.setText("正文");
        mailSender.send(mailMessage);

    }

    @Test
    void  test() throws MessagingException {

        //一个复杂的邮件
        MimeMessage message  = mailSender.createMimeMessage();
        //多文件
        MimeMessageHelper helper = new MimeMessageHelper(message, true);

        helper.setSubject("主题");
        helper.setText("

网页

"
, true); //支持网页 File file1 = new File("/Users/reggie/ttc/C-销售/个人汇总.xlsx"); File file2 = new File("/Users/reggie/ttc/C-销售/明细.xlsx"); //附件 helper.addAttachment("汇总.xlsx", file1); helper.addAttachment("明细.xlsx", file2); mailSender.send(message); }

定时任务

TaskScheduler  任务调度者
TaskExecutor	任务执行者

@EnableScheduling	//开启定时功能的注解(加在启动类上)
@Sheduled	//什么时候执行
@Service
public class TaskService {
    //秒   分   时     日   月   周几
    @Scheduled(cron = "0 48 9 *  * ?")
    public void hello(){
        System.out.println("hello");
    }
}

异步任务

使用异步任务的好处:

​ 我们如果想让用户快速得到反馈,就在后台使用多线程的方式进行处理即可,但是每次都需要自己手动去编写多线程的实现的话,太麻烦了,我们只需要用一个简单的办法,在我们的方法上加一个简单的注解即可,如下:

@EnableAsync //开启异步功能 加在启动类上
@Async  //加在方法上 异步方法
@Service
public class AsyncService {
    //告诉Spring这是一个异步方法
    @Async
    public void hello(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("执行完毕");
    }
}

SpringBoot就会自己开一个线程池,进行调用!

Swagger

  1. 导入依赖
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.9.2</version>
</dependency>

<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.9.2</version>
</dependency>
  1. 编写hello工程
  2. 配置swagger
@Configuration
@EnableSwagger2
public class Swagger2Config {
    @Bean
    public Docket docket() {
       return new Docket(DocumentationType.SWAGGER_2)
           .apiInfo(apiInfo())       
           .select()// 通过.select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口
          .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
          .build();;
    }
    //配置文档信息
    private ApiInfo apiInfo() {
       Contact contact = new Contact("联系人名字", "http://xxx.xxx.com/联系人访问链接", "联系人邮箱");
       return new ApiInfo(
               "Swagger学习", // 标题
               "学习演示如何配置Swagger", // 描述
               "v1.0", // 版本
               "http://terms.service.url/组织链接", // 组织链接
               contact, // 联系人信息
               "Apach 2.0 许可", // 许可
               "许可链接", // 许可连接
               new ArrayList<>()// 扩展
      );
    }
}
  1. 重启项目,访问 http://localhost:8080/swagger-ui.html

问题:如何让swagger在生产环境失效?

利用enable字段
@Bean
public Docket docket(Environment environment) {
   // 设置要显示swagger的环境
   Profiles of = Profiles.of("dev", "test");
   // 判断当前是否处于该环境
   // 通过 enable() 接收此参数判断是否要显示
   boolean b = environment.acceptsProfiles(of);
   
   return new Docket(DocumentationType.SWAGGER_2)
      .apiInfo(apiInfo())
      .enable(b) //配置是否启用Swagger,如果是false,在浏览器将无法访问
      .select()// 通过.select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口
      .apis(RequestHandlerSelectors.basePackage("com.kuang.swagger.controller"))
       // 配置如何通过path过滤,即这里只扫描请求以/kuang开头的接口
      .paths(PathSelectors.ant("/kuang/**"))
      .build();
}

Spring Security

作用:身份验证和权限控制

简介

Spring Security 是Spring项目的安全框架,可以实现强大的Web安全控制。

记住几个类:

  • WebSecurityConfigurerAdapter:自定义Security策略
  • AuthenticationManageBuilder:自定义认证策略
  • @EnableWebSecurity:开启WebSecurity模式

Spring Security的两个主要目标:

  • 认证(Authentication)

  • 授权(Authorization)

配置类:

@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();
//        http.formLogin().loginPage("/toLogin").usernameParameter("user").passwordParameter("pwd").loginProcessingUrl("login"); 定制登录页
        http.csrf().disable();//关闭csrf功能  登录失败可能的原因
        //注销 注销后 跳转到首页
        http.logout().logoutSuccessUrl("/");

        //记住我功能 cookie 默认保存两周
        http.rememberMe();
//        http.rememberMe().rememberMeParameter("remember");  自定义接收前端的参数
    }

    /**
     *密码编码:BCryptPasswordEncoder
     * 认证
     * Spring Security 5.0+新增了很多加密方法
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("ys").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1", "vip2", "vip3");
    }
}

Shiro

简介

  • Apache Shiro是一个Java的安全(权限)框架
  • 可以完成认证、授权、加密、会话管理、Web集成、缓存等

SpringBoot笔记(狂神说)_第2张图片

基础命令
    Subject currentUser = SecurityUtils.getSubject();//获取当前用户
    Session session = currentUser.getSession();//通过当前用户拿到Session

    currentUser.isAuthenticated();//判断当前用户是否被认证
    currentUser.getPrincipal();//当前用户的一个认证
    currentUser.hasRole("test");//当前用户是否拥有某个角色
    currentUser.isPermitted("test");//当前用户是否拥有某个权限
    currentUser.logout();//注销

SpringBoot整合Shiro

1:导入依赖

		
			org.apache.shiro
			shiro-spring
			1.4.1
		

2:配置文件

配置类:
@Configuration
public class ShiroConfig {

    //Shiro
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //关联securityManager
        bean.setSecurityManager(securityManager);

        //添加Shiro的内置过滤器
        /*
            anon:无需认证就可以访问
            authc:必须认证才能访问
            user:必须拥有记住我功能才能使用
            perms:拥有对某个资源的权限才能使用
            role:拥有某个角色权限才能使用
         */
        //登录拦截
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("user/*", "authc");//该接口只有认证后才能访问 如果没有认证,会自动跳转到登录页面
        filterMap.put("user/add", "perms[user:add]");//该接口只有授权后才能访问 如果没有授权,会自动跳转到未授权页面
        bean.setFilterChainDefinitionMap(filterMap);

        //设置登录的请求
        bean.setLoginUrl("/toLogin");
        //未授权页面
        bean.setUnauthorizedUrl("/noauth");

        return  bean;
    }

    //DefaultWebSecurityManager
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联userRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    //创建Realm对象 需要自定义一个类
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

}
UserRealm类:
//自定义的UserRealm
public class UserRealm extends AuthorizingRealm {
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("执行了授权操作");

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        User user = userService.findUserByName(userToken.getUsername());
        if(user == null){ //没有这个用户
            return null;//抛出异常  UnknownAccountException(未知用户)
        }
        //可以加密 MD5盐值加密
        //密码认证 shiro做
        return new SimpleAuthenticationInfo(user, user.getPassword(), "");
    }

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("执行了认证操作");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//        info.addStringPermission("user:add");

        //获取当前对象
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User)subject.getPrincipal();//拿到User对象
        info.addStringPermission(currentUser.getPerms());
        return info;
    }
}
Controller层的登录接口
    @PostMapping("/login")
    public ResponseEntity login(String username, String password){
        //获取当前的用户
        Subject subject = SecurityUtils.getSubject();
        //封装用户的登录数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //执行登录方法 如果没有异常 则说明登录成功
        try {
            subject.login(token);
        }catch (UnknownAccountException e){
            log.info("用户名不存在");
        }catch (IncorrectCredentialsException e){
            log.error("密码错误");
        }catch (LockedAccountException e){
            log.info("账户已锁定");
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
        return ResponseEntity.ok("");
    }

3:快速开始

Dubbo+Zookeeper

  • 本地过程调用:本地的A方法调用本地的B方法

  • RPC:远程过程调用,本地的A方法调用服务器的B方法,两个核心:通讯、序列化(序列化是为了更好的传输数据)

    • RFC的框架:webservice(cxf)、dubbo
  • HTTP:网络传输协议,基于TCP,也可用来远程服务调用。

    • http的实现技术:HttpClient

什么是dubbo?

Apache Dubbo是一款高性能、轻量级的开源Java RPC框架,提供了三大核心能力:面向接口的远程方法调用,只能容错和负载均衡,以及服务自动注册和发现。

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

zookeeper:注册中心(服务注册与发现)。是一个分布式的,开放源码的分布式应用程序协调服务,相当于一个注册中心。是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等 。

服务器注册实战

前提:zookeeper服务已启动

1:提供者提供服务

  • 导入Dubbo和Zookeeper依赖
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.3</version>
        </dependency>
        <!--zookeeper客户端-->
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
        <!-- 引入zookeeper -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
            <!--排除这个slf4j-log4j12 否则会日志冲突-->
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
  • 配置注册中心的地址、发现服务名和要扫描的包
dubbo:
  application:
    name: provider-server
  registry:
    address: zookeeper://127.0.0.1:2181
  scan:
    base-packages: com.ys.providerserver.service
  • 在想要被注册的服务上面,增加一个service注解
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

@Service  //可以被扫描到,在项目中一启动就自动注册到注册中心
@Component  //使用Dubbo后尽量不要用service注解
public class TicketServiceImpl implements TicketService {
    @Override
    public String getTicket() {
        return "狂神说JAVA";
    }
}

2:消费者消费服务

  • 导入依赖
  • 配置注册中心的地址、发现服务名
dubbo:
  application:
    name: provider-server
  registry:
    address: zookeeper://127.0.0.1:2181
  • 从远程注册服务
import com.kuang.provider.service.TicketService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

@Service //注入到容器中
public class UserService {

   @Reference //远程引用指定的服务,Pom坐标或定义路径相同的接口名
   TicketService ticketService;

   public void bugTicket(){
       String ticket = ticketService.getTicket();
       System.out.println("在注册中心买到"+ticket);
  }
}

Redis

SpringBoot操作数据:spring-data jpa jdbc mongodb redis

SpringData也是和SpringBoot齐名的项目!

说明:在SpringBoot2.x之后,原来使用的jedis被替换为了lettuce

jedis:采用的直连,多个线程操作的话,是不安全的。如果要避免不安全,要使用jedis pool连接池,更像BIO。

lettuce:采用Netty,实例可以在多个线程中共享,不存在线程不安全的情况。可以减少线程数据,更像NIO。

源码分析

    @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )	//我们可以自己定义一个redisTemplate来替换这个默认的
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        //默认的redisTemplate没有过多的设置 redis对象是需要序列化的
        //两个泛型都是类型,我们后面使用需要强制转换
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean //由于String是redis中最经常使用的一个类型,所以单独提出来了一个bean
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

简单使用:

  1. 导入依赖
        
            org.springframework.boot
            spring-boot-starter-data-redis
        
  1. 配置连接
spring:
  redis:
    host: 127.0.0.1
    port: 6379
  1. 简单测试
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        //redisTemplate 操作不同的数据类型
        //opsForValue  操作字符串 类似String
        //opsForList 操作List
        //opsForSet
        //opsForHash
        //opsForGeo  操作地理位置

        //获取redis的连接对象
//        RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
//        connection.flushDb();
//        connection.flushAll();

        redisTemplate.opsForValue().set("key", "this is a key");
        System.out.println(redisTemplate.opsForValue().get("key"));
    }

自定义RedisTemplate

public class RedisConfig {

    //编写我们自己的redisTemplate
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        //为了开发方便 一般使用
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);

        //Json序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //String的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        //value的序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hash的value序列化方式采用jackson
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }

}

RedisUtils工具类编写

/**
 * Redis工具类,使用之前请确保RedisTemplate成功注入
 *
 * @author ye17186
 * @version 2019/2/22 10:48
 */
public class RedisUtils {
 
    private RedisUtils() {
    }
 
    @SuppressWarnings("unchecked")
    private static RedisTemplate<String, Object> redisTemplate = SpringUtils
        .getBean("redisTemplate", RedisTemplate.class);
 
    /**
     * 设置有效时间
     *
     * @param key Redis键
     * @param timeout 超时时间
     * @return true=设置成功;false=设置失败
     */
    public static boolean expire(final String key, final long timeout) {
 
        return expire(key, timeout, TimeUnit.SECONDS);
    }
 
    /**
     * 设置有效时间
     *
     * @param key Redis键
     * @param timeout 超时时间
     * @param unit 时间单位
     * @return true=设置成功;false=设置失败
     */
    public static boolean expire(final String key, final long timeout, final TimeUnit unit) {
 
        Boolean ret = redisTemplate.expire(key, timeout, unit);
        return ret != null && ret;
    }
 
    /**
     * 删除单个key
     *
     * @param key 键
     * @return true=删除成功;false=删除失败
     */
    public static boolean del(final String key) {
 
        Boolean ret = redisTemplate.delete(key);
        return ret != null && ret;
    }
 
    /**
     * 删除多个key
     *
     * @param keys 键集合
     * @return 成功删除的个数
     */
    public static long del(final Collection<String> keys) {
 
        Long ret = redisTemplate.delete(keys);
        return ret == null ? 0 : ret;
    }
 
    /**
     * 存入普通对象
     *
     * @param key Redis键
     * @param value 值
     */
    public static void set(final String key, final Object value) {
 
        redisTemplate.opsForValue().set(key, value, 1, TimeUnit.MINUTES);
    }
 
    // 存储普通对象操作
 
    /**
     * 存入普通对象
     *
     * @param key 键
     * @param value 值
     * @param timeout 有效期,单位秒
     */
    public static void set(final String key, final Object value, final long timeout) {
 
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }
 
    /**
     * 获取普通对象
     *
     * @param key 键
     * @return 对象
     */
    public static Object get(final String key) {
 
        return redisTemplate.opsForValue().get(key);
    }
 
    // 存储Hash操作
 
    /**
     * 往Hash中存入数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @param value 值
     */
    public static void hPut(final String key, final String hKey, final Object value) {
 
        redisTemplate.opsForHash().put(key, hKey, value);
    }
 
    /**
     * 往Hash中存入多个数据
     *
     * @param key Redis键
     * @param values Hash键值对
     */
    public static void hPutAll(final String key, final Map<String, Object> values) {
 
        redisTemplate.opsForHash().putAll(key, values);
    }
 
    /**
     * 获取Hash中的数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @return Hash中的对象
     */
    public static Object hGet(final String key, final String hKey) {
 
        return redisTemplate.opsForHash().get(key, hKey);
    }
 
    /**
     * 获取多个Hash中的数据
     *
     * @param key Redis键
     * @param hKeys Hash键集合
     * @return Hash对象集合
     */
    public static List<Object> hMultiGet(final String key, final Collection<Object> hKeys) {
 
        return redisTemplate.opsForHash().multiGet(key, hKeys);
    }
 
    // 存储Set相关操作
 
    /**
     * 往Set中存入数据
     *
     * @param key Redis键
     * @param values 值
     * @return 存入的个数
     */
    public static long sSet(final String key, final Object... values) {
        Long count = redisTemplate.opsForSet().add(key, values);
        return count == null ? 0 : count;
    }
 
    /**
     * 删除Set中的数据
     *
     * @param key Redis键
     * @param values 值
     * @return 移除的个数
     */
    public static long sDel(final String key, final Object... values) {
        Long count = redisTemplate.opsForSet().remove(key, values);
        return count == null ? 0 : count;
    }
 
    // 存储List相关操作
 
    /**
     * 往List中存入数据
     *
     * @param key Redis键
     * @param value 数据
     * @return 存入的个数
     */
    public static long lPush(final String key, final Object value) {
        Long count = redisTemplate.opsForList().rightPush(key, value);
        return count == null ? 0 : count;
    }
 
    /**
     * 往List中存入多个数据
     *
     * @param key Redis键
     * @param values 多个数据
     * @return 存入的个数
     */
    public static long lPushAll(final String key, final Collection<Object> values) {
        Long count = redisTemplate.opsForList().rightPushAll(key, values);
        return count == null ? 0 : count;
    }
 
    /**
     * 往List中存入多个数据
     *
     * @param key Redis键
     * @param values 多个数据
     * @return 存入的个数
     */
    public static long lPushAll(final String key, final Object... values) {
        Long count = redisTemplate.opsForList().rightPushAll(key, values);
        return count == null ? 0 : count;
    }
 
    /**
     * 从List中获取begin到end之间的元素
     *
     * @param key Redis键
     * @param start 开始位置
     * @param end 结束位置(start=0,end=-1表示获取全部元素)
     * @return List对象
     */
    public static List<Object> lGet(final String key, final int start, final int end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

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