SpringBoot 学习记录(七): Redis

SpringBoot+Redis简单实现文章浏览量记录 现在做的大部分项目都用到了SpringBoot和Redis,不过实际开发中,Redis只存了Token之类的数据,大部分的增删改查还是直接走的MySQL数据库。这2天逛论坛发现其实很多场景其实更需要Redis这样的存在,于是参考网上的代码简单做了个文章浏览量记录的Demo。 首先放出maven依赖: <dependencies> <dependency> <groupId>junit</groupId> <artif 阅读详情

之前写过一篇spring+spring_mvc+redis的博客,这篇我们学习在spring_boot中如何使用redis

对spring_boot有过了解后可以知道,spring_boot本身集成了很多模块,根据需要引入即可,

redis的使用也是,第一步是引入相关依赖包。

一,pom.xml中添加依赖:

	<!-- redis -->
	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
        </dependency>
二,在application.properties中添加redis的配置,

请确保你的本地已安装有redis,我的是装在虚拟机,

有需要的可以回顾博文:常用框架(二) : spring+springMvc+mybatis+maven+redis

#redis
spring.redis.database=0  
spring.redis.host=192.168.230.130
spring.redis.port=6379  
spring.redis.password=  
spring.redis.pool.max-active=8  
spring.redis.pool.max-wait=-1  
spring.redis.pool.max-idle=8  
spring.redis.pool.min-idle=0  
spring.redis.timeout=0

三,定义RedisConfiguration配置类

package com.example.config;

import java.lang.reflect.Method;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
@EnableCaching//启用缓存
public class RedisConfiguration extends CachingConfigurerSupport {

	/**
	 * 自定义缓存key值
	 * 此方法将会根据类名+方法名+所有参数的值生成唯一的一个key
	 */
	@Bean
	public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

	/**
	 * 缓存管理器
	 * @param redisTemplate
	 * @return
	 */
    @Bean
    public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        //设置缓存过期时间
        rcm.setDefaultExpiration(300);//秒
        return rcm;
    }
    
    /**
     * RedisTemplate缓存操作类,类似于jdbcTemplate的一个类;
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        //key序列化方式
        Jackson2JsonRedisSerializer<Object> redisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        redisSerializer.setObjectMapper(om);
        template.setValueSerializer(redisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

四,测试

首先请确保开启你的redis服务:


新建测试类RedisController:

这里我们使用RedisTemplate的api进行存储数据,如下:


一般是自己定义一个RedisService工具类,方便使用,本例就不说明了,有兴趣的可以查看之前的博客。

package com.example.controller;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RedisController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
	
    @Resource
    private RedisTemplate<String,String> redisTemplate;
	
	
    @RequestMapping("/redis/set")  
    public String setKeyAndValue(){
		String key = "name";
		String value = "wendy";
        logger.info("访问set:key={},value={}",key,value);
        ValueOperations<String,String> valOpsStr = redisTemplate.opsForValue();
        valOpsStr.set(key, value);  
        return "Set Ok";  
    }  
      
    @RequestMapping("redis/get")  
    public String getKey(){
    	String key = "name";
        logger.info("访问get:key={}",key);
        ValueOperations<String,String> valOpsStr = redisTemplate.opsForValue();
        return valOpsStr.get(key);  
    } 
}
启动服务测试: http://localhost:8088/spring-boot/redis/set ===== 返回结果:Set Ok

如果测试redis连接失败,clean project 之后重启再试,如果还有问题,请确保你的redis服务是否开启,配置是否正确等

启动服务测试:http://localhost:8088/spring-boot/redis/get ====== 返回结果:wendy
==================================================================================================

上面定义RedisConfiguration配置类时,我们定义了一个自动生成key的方法,

也就是说不用定义一个唯一key,也能根据自动生成的key存取value值,下面我们来学习如何使用注解的方式

前面学习jap的时候我们定义了UserInfoRepository,在controller层也是直接使用的dao层,

这里我们加上service,使代码规范化

package com.example.service;

import com.example.entity.UserInfo;

public interface UserService {
	
	UserInfo findById(long id);
	
	void deleteFromCache(long id);
}
package com.example.service.impl;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.example.entity.UserInfo;
import com.example.repository.UserInfoRepository;
import com.example.service.UserService;

@Service
public class UserServiceImpl implements UserService {

	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Resource
	private UserInfoRepository userRepository;
	
	@Override
	public UserInfo findById(long id) {
		logger.info("从数据库查询数据");
		return userRepository.findById(id);
	}

	@Override
	public void deleteFromCache(long id) {
		logger.info("从缓存中删除数据");
	}
	
	
}
五,在RedisController中添加测试方法:
package com.example.controller;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.base.ReturnResult;
import com.example.entity.UserInfo;
import com.example.service.UserService;

@RestController
public class RedisController {
	
    @Resource
    private UserService userService;
	    
    @RequestMapping("redis/get/user")
    @Cacheable(value="userInfo")//注解直接缓存查询结果
    public UserInfo getUserById(long id){
    	UserInfo user = userService.findById(id);
    	return user;
    }
    
    @RequestMapping("redis/del/user")
    @CacheEvict(value="userInfo",allEntries=true)//注解从缓存删除结果
    public String delUserById(long id){
    	userService.deleteFromCache(id);
    	return "del from cache";
    }
}

这里说明一下spring cache的注解使用:

Cacheable 支持如下几个参数:
value:缓存位置名称,不能为空,如果使用EHCache,就是ehcache.xml中声明的cache的name
key:缓存的key,默认为空则表示使用方法的参数类型及参数值作为key,可以自定义key的生成规则
condition:触发条件,只有满足条件的情况才会加入缓存,默认为空示全部都加入缓存

@CacheEvict 支持如下几个参数:
value:缓存位置名称,不能为空,同上
key:缓存的key,默认为空,同上
condition:触发条件,只有满足条件的情况才会清除缓存,默认为空
allEntries:true表示清除value中的全部缓存,默认为false

================ 注解用在service层是一样的,看个人业务需求使用


启动测试:第一次查询用户信息是从数据库查询,控制台应该会打印日志

访问测试:http://localhost:8088/spring-boot/redis/get/user?id=1

返回结果:

{
  "id": 1,
  "name": "initname",
  "gender": "F",
  "status": null
}
查看控制台:
2017-04-11 14:58:40.609 DEBUG 6308 --- [nio-8088-exec-2] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/spring-boot/redis/get/user]
2017-04-11 14:58:40.610 DEBUG 6308 --- [nio-8088-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /redis/get/user
2017-04-11 14:58:40.610 DEBUG 6308 --- [nio-8088-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public com.example.entity.UserInfo com.example.controller.RedisController.getUserById(long)]
2017-04-11 14:58:40.610 DEBUG 6308 --- [nio-8088-exec-2] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/spring-boot/redis/get/user] is: -1
2017-04-11 14:58:40.619  INFO 6308 --- [nio-8088-exec-2] com.example.aop.LogAop                   : LogAop.doBefore()
2017-04-11 14:58:40.619  INFO 6308 --- [nio-8088-exec-2] com.example.aop.LogAop                   : URL : http://localhost:8088/spring-boot/redis/get/user
2017-04-11 14:58:40.619  INFO 6308 --- [nio-8088-exec-2] com.example.aop.LogAop                   : HTTP_METHOD : GET
2017-04-11 14:58:40.619  INFO 6308 --- [nio-8088-exec-2] com.example.aop.LogAop                   : IP : 0:0:0:0:0:0:0:1
2017-04-11 14:58:40.622  INFO 6308 --- [nio-8088-exec-2] com.example.aop.LogAop                   : CLASS_METHOD : com.example.controller.RedisController.getUserById
2017-04-11 14:58:40.623  INFO 6308 --- [nio-8088-exec-2] com.example.aop.LogAop                   : ARGS : [1]
id: 1
2017-04-11 14:58:40.724  INFO 6308 --- [nio-8088-exec-2] c.example.service.impl.UserServiceImpl   : 从数据库查询数据
Hibernate: select userinfo0_.id as id1_0_, userinfo0_.gender as gender2_0_, userinfo0_.name as name3_0_ from user_info userinfo0_ where userinfo0_.id=?
2017-04-11 14:58:40.900  INFO 6308 --- [nio-8088-exec-2] com.example.aop.LogAop                   : LogAop.doAfter()
2017-04-11 14:58:40.900  INFO 6308 --- [nio-8088-exec-2] com.example.aop.LogAop                   : LogAop.doAfterReturning()
2017-04-11 14:58:40.900  INFO 6308 --- [nio-8088-exec-2] com.example.aop.LogAop                   : 耗时(毫秒) : 281
2017-04-11 14:58:40.909 DEBUG 6308 --- [nio-8088-exec-2] m.m.a.RequestResponseBodyMethodProcessor : Written [com.example.entity.UserInfo@4f696c3f] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@403a7b03]
2017-04-11 14:58:40.910 DEBUG 6308 --- [nio-8088-exec-2] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2017-04-11 14:58:40.911 DEBUG 6308 --- [nio-8088-exec-2] o.s.web.servlet.DispatcherServlet        : Successfully completed request

再次访问,此时应该是从缓存获取数据,控制台不会打印出“从数据库查询数据”这条日志

且注意查看耗时时间,会比查询数据库要短

清除控制台再次访问查看:

2017-04-11 15:19:11.792 DEBUG 6260 --- [nio-8088-exec-3] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/spring-boot/redis/get/user]
2017-04-11 15:19:11.793 DEBUG 6260 --- [nio-8088-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /redis/get/user
2017-04-11 15:19:11.794 DEBUG 6260 --- [nio-8088-exec-3] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public com.example.entity.UserInfo com.example.controller.RedisController.getUserById(long)]
2017-04-11 15:19:11.794 DEBUG 6260 --- [nio-8088-exec-3] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/spring-boot/redis/get/user] is: -1
2017-04-11 15:19:11.795  INFO 6260 --- [nio-8088-exec-3] com.example.aop.LogAop                   : LogAop.doBefore()
2017-04-11 15:19:11.795  INFO 6260 --- [nio-8088-exec-3] com.example.aop.LogAop                   : URL : http://localhost:8088/spring-boot/redis/get/user
2017-04-11 15:19:11.795  INFO 6260 --- [nio-8088-exec-3] com.example.aop.LogAop                   : HTTP_METHOD : GET
2017-04-11 15:19:11.796  INFO 6260 --- [nio-8088-exec-3] com.example.aop.LogAop                   : IP : 0:0:0:0:0:0:0:1
2017-04-11 15:19:11.796  INFO 6260 --- [nio-8088-exec-3] com.example.aop.LogAop                   : CLASS_METHOD : com.example.controller.RedisController.getUserById
2017-04-11 15:19:11.796  INFO 6260 --- [nio-8088-exec-3] com.example.aop.LogAop                   : ARGS : [1]
id: 1
2017-04-11 15:19:11.797  INFO 6260 --- [nio-8088-exec-3] com.example.aop.LogAop                   : LogAop.doAfter()
2017-04-11 15:19:11.797  INFO 6260 --- [nio-8088-exec-3] com.example.aop.LogAop                   : LogAop.doAfterReturning()
2017-04-11 15:19:11.797  INFO 6260 --- [nio-8088-exec-3] com.example.aop.LogAop                   : 耗时(毫秒) : 2
2017-04-11 15:19:11.803 DEBUG 6260 --- [nio-8088-exec-3] m.m.a.RequestResponseBodyMethodProcessor : Written [com.example.entity.UserInfo@9e8e466] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@345a0792]
2017-04-11 15:19:11.803 DEBUG 6260 --- [nio-8088-exec-3] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2017-04-11 15:19:11.803 DEBUG 6260 --- [nio-8088-exec-3] o.s.web.servlet.DispatcherServlet        : Successfully completed request
============= 说明测试缓存成功

下面我们测试删除缓存方法:http://localhost:8088/spring-boot/redis/del/user?id=1

返回结果:del from cache

再次测试查询方法:http://localhost:8088/spring-boot/redis/get/user?id=1

可以看到这里又打印了日志:“从数据库查询数据”,删除缓存成功

2017-04-11 21:20:07.644 DEBUG 8460 --- [nio-8088-exec-9] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/spring-boot/redis/del/user]
2017-04-11 21:20:07.645 DEBUG 8460 --- [nio-8088-exec-9] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /redis/del/user
2017-04-11 21:20:07.645 DEBUG 8460 --- [nio-8088-exec-9] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public java.lang.String com.example.controller.RedisController.delUserById(long)]
2017-04-11 21:20:07.646 DEBUG 8460 --- [nio-8088-exec-9] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/spring-boot/redis/del/user] is: -1
2017-04-11 21:20:07.647  INFO 8460 --- [nio-8088-exec-9] com.example.aop.LogAop                   : LogAop.doBefore()
2017-04-11 21:20:07.647  INFO 8460 --- [nio-8088-exec-9] com.example.aop.LogAop                   : URL : http://localhost:8088/spring-boot/redis/del/user
2017-04-11 21:20:07.647  INFO 8460 --- [nio-8088-exec-9] com.example.aop.LogAop                   : HTTP_METHOD : GET
2017-04-11 21:20:07.648  INFO 8460 --- [nio-8088-exec-9] com.example.aop.LogAop                   : IP : 0:0:0:0:0:0:0:1
2017-04-11 21:20:07.648  INFO 8460 --- [nio-8088-exec-9] com.example.aop.LogAop                   : CLASS_METHOD : com.example.controller.RedisController.delUserById
2017-04-11 21:20:07.648  INFO 8460 --- [nio-8088-exec-9] com.example.aop.LogAop                   : ARGS : [1]
id: 1
2017-04-11 21:20:07.648  INFO 8460 --- [nio-8088-exec-9] c.example.service.impl.UserServiceImpl   : 从缓存中删除数据
2017-04-11 21:20:07.651  INFO 8460 --- [nio-8088-exec-9] com.example.aop.LogAop                   : LogAop.doAfter()
2017-04-11 21:20:07.651  INFO 8460 --- [nio-8088-exec-9] com.example.aop.LogAop                   : LogAop.doAfterReturning()
2017-04-11 21:20:07.651  INFO 8460 --- [nio-8088-exec-9] com.example.aop.LogAop                   : 耗时(毫秒) : 4
2017-04-11 21:20:07.653 DEBUG 8460 --- [nio-8088-exec-9] m.m.a.RequestResponseBodyMethodProcessor : Written [del from cache] as "text/plain;charset=UTF-8" using [org.springframework.http.converter.StringHttpMessageConverter@3badefd6]
2017-04-11 21:20:07.653 DEBUG 8460 --- [nio-8088-exec-9] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2017-04-11 21:20:07.654 DEBUG 8460 --- [nio-8088-exec-9] o.s.web.servlet.DispatcherServlet        : Successfully completed request
2017-04-11 21:20:10.258 DEBUG 8460 --- [io-8088-exec-10] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/spring-boot/redis/get/user]
2017-04-11 21:20:10.259 DEBUG 8460 --- [io-8088-exec-10] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /redis/get/user
2017-04-11 21:20:10.259 DEBUG 8460 --- [io-8088-exec-10] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public com.example.entity.UserInfo com.example.controller.RedisController.getUserById(long)]
2017-04-11 21:20:10.259 DEBUG 8460 --- [io-8088-exec-10] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/spring-boot/redis/get/user] is: -1
2017-04-11 21:20:10.263  INFO 8460 --- [io-8088-exec-10] com.example.aop.LogAop                   : LogAop.doBefore()
2017-04-11 21:20:10.263  INFO 8460 --- [io-8088-exec-10] com.example.aop.LogAop                   : URL : http://localhost:8088/spring-boot/redis/get/user
2017-04-11 21:20:10.263  INFO 8460 --- [io-8088-exec-10] com.example.aop.LogAop                   : HTTP_METHOD : GET
2017-04-11 21:20:10.263  INFO 8460 --- [io-8088-exec-10] com.example.aop.LogAop                   : IP : 0:0:0:0:0:0:0:1
2017-04-11 21:20:10.263  INFO 8460 --- [io-8088-exec-10] com.example.aop.LogAop                   : CLASS_METHOD : com.example.controller.RedisController.getUserById
2017-04-11 21:20:10.263  INFO 8460 --- [io-8088-exec-10] com.example.aop.LogAop                   : ARGS : [1]
id: 1
2017-04-11 21:20:10.265  INFO 8460 --- [io-8088-exec-10] c.example.service.impl.UserServiceImpl   : 从数据库查询数据
Hibernate: select userinfo0_.id as id1_0_, userinfo0_.gender as gender2_0_, userinfo0_.name as name3_0_ from user_info userinfo0_ where userinfo0_.id=?
2017-04-11 21:20:10.269  INFO 8460 --- [io-8088-exec-10] com.example.aop.LogAop                   : LogAop.doAfter()
2017-04-11 21:20:10.270  INFO 8460 --- [io-8088-exec-10] com.example.aop.LogAop                   : LogAop.doAfterReturning()
2017-04-11 21:20:10.270  INFO 8460 --- [io-8088-exec-10] com.example.aop.LogAop                   : 耗时(毫秒) : 7
2017-04-11 21:20:10.274 DEBUG 8460 --- [io-8088-exec-10] m.m.a.RequestResponseBodyMethodProcessor : Written [com.example.entity.UserInfo@1e076014] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@51e330c]
2017-04-11 21:20:10.274 DEBUG 8460 --- [io-8088-exec-10] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2017-04-11 21:20:10.275 DEBUG 8460 --- [io-8088-exec-10] o.s.web.servlet.DispatcherServlet        : Successfully completed request

============================================================================

接下来我们学习如何在redis中存储session,在做负载均衡的时候多应用共享session

一,添加依赖:

<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session-data-redis</artifactId>
</dependency>

二,定义配置类SessionConfiguration

package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60*60*2)
public class SessionConfiguration {

}

接下来就可以部署测试了,这里不做演示

到此redis的学习就暂时告一段落,下篇我们将学习,SpringBoot 学习记录(八): properties 属性自定义



SpringBoot+MyBatis+Redis整合(记录) 整合分为两步:1、整合MyBatis;2、整合Redis。 一、整合MyBatis。 1、创建SpringBoot项目。 2、在resources下的application.properties配置里添加如下代码: server.port=8090 ## 数据库设置 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/db 阅读详情

相关推荐

SpringBoot Redis工具类封装

SpringBoot整合Redis的博客很多,但是很多都不是我想要的结果。因为我只需要整合完成后,可以操作Redis就可以了,并不需要配合缓存相关的注解使用(如@Cacheable)。看了很多博客后,我成功的整合了,并写了个Redis操作工具类。特意在此记录一下,方便后续查阅。 一、Maven依赖 1、本文所采用的SpringBoot的版本如下 <parent> &lt...

专注基础架构领域 8445

springboot三层架构解决报错信息:o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet

javaweb程序报错Servlet.service() for servlet [dispatcherServlet] in的解决方案

qq_51950796的博客 9459

基于SpringBoot的个人学习记录平台的设计

Java Web开发一直被人诟病的一点就是臃肿、麻烦。其中最主要的原因就是复杂的配置和混乱的依赖管理。学习Spring的第一件事情就是学习它的配置文件的编写,整个Spring的运行都是建立在那些繁多的配置文件之上的,开发者通过修改配置而对Spring的底层进行影响。而配置文件就是一个麻烦的代名词,它使得开发者不仅要学习Spring的编程技巧,还要学习其对应的配置文件的编写,让开发者的思维跳转与业务逻辑和配置编写之间,很影响编程效率。

来自一名程序猿的案例文档分享 987

ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() --调试发现HttpSession session无法读取数据

最后实在是不行了 ,但是从一步一步的调试也大概知道问题是出在了,map无法取出页面上输入的第二个值。所以就开始比对自己所配置的login.html文件,发现此处的loginApi所注入的方式不同。、如果存在取值问题,取不到session中的值,可能是存值的地方和取值的地方引入的HttpServletRequest不一致。就是存了两个数据,但是读出的只有一个数据。发现两次的session地址和存值都是正确的,但是map读取时,只读出了一个值。还是关键:解决问题的操作并不重要,解决问题的这个思路才是最重要的。

weixin_42409390的博客 3万+

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

2020-04-27 22:15:44.892 ERROR 13764 --- [nio-8081-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause java.lang.Nul

在线迭代RLHF实战:从原理到实现,复现超越官方指令模型的工作流

大语言模型(LLM)的对齐技术是提升其与人类意图一致性的关键。其中,基于人类反馈的强化学习(RLHF)通过引入人类偏好信号,指导模型优化生成策略,是实现模型“有用”与“无害”的核心方法。其技术价值在于将抽象的“对齐”目标转化为可优化的奖励信号,从而显著提升模型在对话、推理等任务中的表现。然而,传统的离线RLHF存在数据分布偏移和奖励黑客等瓶颈。在线迭代RLHF通过构建“生成-评估-学习”的动态数据循环,让模型能够利用自身最新生成的数据进行持续优化,有效克服了上述问题,成为当前提升指令模型性能的前沿方向。本文

weixin_28725037的博客 368

栈溢出错误解决方案

之前做项目时在使用lombok插件启动项目时报错,在此记录一下 ,希望能帮到大家。 问题描述 ERROR o.a.c.c.C.[.[.[.【dispatcherServlet】 Servlet.service() for servlet 【dispatcherServlet】 in context with path 【】 threw exception 【Handler processing failed; nested exception is java.lang.StackOverflowError

氵胡少的博客 3268

FPGA DMA IP核使用指南

数据传输:支持从源地址到目标地址的数据传输。中断管理:提供中断信号,便于CPU处理传输完成事件。传输控制:支持传输大小、方向和暂停/恢复控制。

weixin_66634995的博客 2428

数据大屏项目采坑01 (已解决)

数据大屏项目采坑01 (已解决) 2022-03-02 13:12:53.530 ERROR 71824 — [nio-8090-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is ja

HRX98的博客 1949

突破NER性能瓶颈:BERT与LLM协同的混合架构实践

性能卓越:在多个测试集上,F1分数比单一模型提升5-15%成本可控:相比纯LLM方案,成本降低60%以上易于落地:架构清晰,便于调试和优化这种"专才+通才"的组合思路可以扩展到其他NLP任务中,如关系抽取、事件提取、文本分类等。更精细的流水线优化多模型投票机制在线学习与自适应调整不追求单一模型的万能,而是通过精心设计的组合,让每个组件发挥其独特优势,最终实现系统性能的最优化。欢迎在评论区分享你在NER任务中的实践经验,或者对这个混合架构的改进建议!

Ven%的博客 1022

java modbus通讯协议_Modbus通 讯 协 议

电磁流量计Modbus通 讯 协 议(版本号:9000-K V9.1.1)2020年01月01日通讯协议针对KFD电磁流量计工业应用设计,版本:9000-K V9.1.1,该版本主要用于实时数据采集、流量测量、流量累计控制及部分参数的修改。一、主机系统通讯部件要求1.国际标准RS-485通讯接口部件,不小于11Bytes 的通信缓冲区(FIFO),支持1200、2400、4800、96...

weixin_39956612的博客 1011

Redis学习记录------SpringBoot整合Redis(七)-未完待续

需创建RedisTemplate类,测试时自动注入该模板类即可使用,与JDBCTemplate差不多。配置文件:application.properties。

cz_chen_zhuo的博客 172

Android WIFI体系:深入解析WifiLock与MulticastLock的底层实现与性能优化

本文深入解析Android WIFI体系中WifiLock与MulticastLock的底层实现机制与性能优化策略。WifiLock通过阻止Wi-Fi休眠提升网络性能,尤其WIFI_MODE_FULL_HIGH_PERF模式可显著降低延迟;MulticastLock则控制组播数据接收,但会增加功耗。文章详细探讨了其与wpa_supplicant、HAL层的交互,并提供高性能场景下的优化实践与功耗平衡方案。

php55的博客 1079

【六】springboot整合redis

springboot整合redis

weixin_56995925的博客 2万+

开心消消乐

1)当点击一个1时,该1变被反转为0,同时相邻的上、下、左、右,以及左上、左下、右上、右下8个方向的1(如果存在1)均会自动反转为0;2)进一步地,一个位置上的1被反转为0时,与其相邻的8个方向的1(如果存在1)均会自动反转为0;上述样例中,四个角上的1均在中间的1的相邻8个方向上,因此只需要点击一次即可。给定一个N行M列的二维矩阵,矩阵中每个位置的数字取值为0或1。在上述4 * 4的矩阵中,只需要点击2次,即可将所有的1进行消除。接下来N行表示矩阵的初始值,每行均为M个数,取值范围[0,1]

面试高手的博客 2729

【四足机器人项目实战】四足机器人运动学、动力学模型

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言一、四足机器人实际模型的物理难点二、四足机器人运动学模型1.方法一:DH法建立运动学模型(1)运动学建模构型方法(2)运动学模型描述方法1、基于DH法四足机器人单腿运动学模型公式推导(0)DH法科普1)原理2)实现过程3)评价(1)四足机器人的建模规则、坐标系定义及实物参数确定1)标准Denavit-Hartenberg法建模规则2)单腿运动学模型坐标系定义示意图及简化模型3)

qq_35635374的博客 1万+

SpringBoot整合Redis(项目实战篇)

写在前面: 从2018年底开始学习SpringBoot,也用SpringBoot写过一些项目。现在想对学习Springboot的一些知识总结记录一下。如果你也在学习SpringBoot,可以关注我,一起学习,一起进步。相关文章:Redis数据类型及基本使用。 文章目录Redis1、Redis简介2、Redis特点搭建项目1、项目结构2、新建Springboot项目3、配置链接信息测试链接1、测...

小马同学 2万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

SpringBoot集成Redis和配置Redis做缓存

Redis介绍 Redis是一个开源的、高性能的、基于键值对的缓存与存储系统,通过提供多种键值数据类型来适应不同场景下的缓存与存储需求,直观的存储结构使得通过程序交互十分简单。 Redis数据库中所有数据都存储在内存中,由于内存的读写速度远快于硬盘,因此Redis在性能上对比其他基于硬盘存储的数据库有非常明显的优势,而且Redis提供了对持久化的支持,即可以将内存中的数据异步写入到硬盘中,且不影...

打破沉默的博客 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

日常记录-SpringBoot整合SpringSecurity(前后分离)+JWT+Redis

SpringBoot整合SpringSecurity一、搭建项目1、构建springboot项目2、导入依赖3、配置yml4、启动项目二、建立相关用户角色权限表1、创建数据库的字符集和排序规则2、用户表结构3、权限表结构4、用户与权限关联表结构5、插入测试数据三、创建实体类和Mapper1、SysUser2、SysPermission3、SysUserPermissionRelation4、配置@MapperScan四、Redis配置1、RedisConfig2、RedisUtil五、统一全局返回格式与处理

会走的鱼 4308

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

SpringBoot使用Redis

在SpringBoot中使用Redis缓存数据

老秦博客 2539

SpringBoot集成Redis---这是一篇自我学习与记录问题。

文章目录前言一、如何集成Redis1.添加Redis起步依赖2. 编写测试程序配置连接信息ControllerServiceStudentServiceStudentServiceImpl结果的实现二.总结问题1. 避免忘记启动本地,Redis2. 我在确保代码都无问题时,报的错3. 还有一点注解问题总结 前言 此篇将会记录,SpringBoot项目中如何集成Redis,并且记录自己所遇到的问题。 一、如何集成Redis 在这呢,什么是Redis,Redis的安装,如何创建SpringBoot-web.

Dimples1014的博客 572

学习记录-统计记录场景下的Redis写请求合并优化实践

学习记录场景下的Redis写请求合并优化实践在高频学习进度统计场景中,前端每15秒上报播放进度,直接写入数据库面临性能挑战。频繁的插入与更新操作涉及多表联动(如学习记录表、课程章节表等),导致数据库负载激增,并发场景下易出现响应延迟甚至服务雪崩。 优化方案采用Redis作为写缓冲层实现请求合并:写缓存:将进度更新暂存至Redis哈希结构,以lessonId+sectionId为键,聚合短时间内的多次更新,仅保留最新进度; 延迟落库:通过延迟队列(如JDK DelayQueue)触发合并任务,20

sjsjsbbsbsn的博客 1370

全局记录SpringBoot Redis的请求和响应日志

同前文,有时需要跟踪Redis的命令、参数,以及Redis的返回数据情况,如何开启Redis的全局日志呢? 首先当然是在网上找了一些资料,发现要么是通过Redis第三方工具监控Redis通信, 要么是通过代理RedisTemplate,拦截RedisTemplate类的方法,而RedisTemplate类集成了9个opsForXxx方法,还有expire或delete方法又是独立的,而且相关命令基本都长得跟Redis不太一样,不熟悉的话,需要看一下源码,才知道是哪个Redis命令。 调研了一下Redis操作

北亮的专栏 4205

springboot redis 学习记录

springboot+redis学习记录

qq_43541976的博客 482

【SpringBoot】使用Redis

在拦截器中使用RedisTemplate记录访问的次数。@Component/*Spring Data Redis 提供的一个模板类,用于简化与 Redis 数据库的交互类似于map类型,可以存储和检索各种类型的数据,包括字符串、对象、集合等。但是,它提供了一些额外的功能,如键的过期时间、哈希表操作、列表操作等。*/@Autowired/*** 在请求处理之后,视图渲染之前执行,用于进行资源清理*/@Override//输出接收的请求。

BlackPudding_的博客 1215
上一篇: SpringBoot 学习记录(六): Exception
下一篇: SpringBoot 学习记录(八): properties 属性自定义
小小小爬虫
博客等级 码龄10年 16粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值