SpringBoot项目练习问题记录

理论和实践总是有差距的,spring boot实战开始

一、前提:根据网址http://www.ityouknow.com/springboot/2016/01/06/spring-boot-quick-start.html 开启springboot的练习

二、问题记录:

1、打开https://start.spring.io,不做更改,简单下载了一个demo项目框架,解压,用intellij idea打开后,重写了实例中的HelloController,结果按照http://localhost:8080/hello 访问发现有问题如下:

SpringBoot项目练习问题记录_第1张图片

 对应问题,当前项目结构如下

SpringBoot项目练习问题记录_第2张图片

 解决:根据问题搜索,发现问题原因:

https://www.cnblogs.com/lilinzhiyu/p/7921890.html

于是将hellocontroller.java文件移动到了和DemoApplication相同的包,访问结果ok,因此,特别注意文中所说的结构问题:

即自己创建的包必须作为子包放在启动目录包下。

于是最新的结构为:

SpringBoot项目练习问题记录_第3张图片

 

注:因为spring jpa的自动映射功能,数据库连接时,只需要在mysql数据库中创建一个数据库,即可。不需要手动创建表,

当你通过entity实体类创建完实体,通过对实体类(bean)添加@Entity 注解和@Table(name = "数据库中欲创建的表名”) 注解,

正常运行spring boot项目,则数据库中会自动创建相应的表。

相关关键类和配置如下(注:因为该博客是在完成一定量的基础上记录的,后面会尽可能按照当初的步骤记录):

SpringBoot项目练习问题记录_第4张图片

如上左侧为当前状态,正常刚开始的时候,只有一个启动类和pom文件部分内容:



	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.2.4.RELEASE
		 
	
	com.example
	demo
	0.0.1-SNAPSHOT
	demo
	Demo project for Spring Boot

	
		1.8
	

	
		
			org.springframework.boot
			spring-boot-starter
		
		
			org.springframework.boot
			spring-boot-starter-web
			RELEASE
			compile
		
		
			junit
			junit
			4.12
			test
		

		
		
			org.springframework.boot
			spring-boot-devtools
		
		
			mysql
			mysql-connector-java
		
		
			org.springframework.boot
			spring-boot-starter-data-jpa
		
		
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	


 创建一个controller的包,在其中创建一个HelloController类,即可完成初步的spring boot的hello world意思的功能

package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping("/welcome") //
    public String index(){
        return "Spring boot welcome to you !";
   }

}

 此时已经可以试验,通过直接启动运行,在浏览器中输入如下地址即可http://localhost:8080/welcome

效果即:

SpringBoot项目练习问题记录_第5张图片

到此第一个helloworld类型的测试就ok了

三、接下来验证一般的java web项目的创建基本环境添加配置如下:

application.properties 

#通用数据源配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver //mysql不同版本驱动类型有别
spring.datasource.url=jdbc:mysql://localhost:3306/sbootmysql?useUnicode=true&characterEncoding=utf8&serverTimezone=CST //注意serverTimezone的配置
spring.datasource.username=root
spring.datasource.password=youpassword
        
#http编码设置
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true 
spring.http.encoding.force=true
#thymeleaf 视图解析配置
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.mode=HTML5

# JPA 相关配置
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=update
#是否打印sql语句
spring.jpa.show-sql= true

类的内容如下:

基本的实体bean类,注意,在此创建了一个特殊的父类MappedSupperClass类型的父类,用于统一管理id,你也可以不创建,

该种方式为当前通用的一种简化写代码操作的方式,这样在子类中可以共享一些属性而无需自定义。

package com.example.demo.bean;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

@MappedSuperclass //注意BaseBean添加该注解,
public class BaseBean {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)//配置的ID自增策略
    private Long id;
}
package com.example.demo.bean;

import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable;

@Entity
@Table(name = "user")//此处报错,则说明是数据库未连接成功,请查看数据源的连接和配置
public class User extends BaseBean implements Serializable {

    private String name;
    private int age;
    private String info;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

 Dao层很简单,对的,就是这么简单,这里的通用的commonDao 需要注意,此处是因为使用了spring JPA

package com.example.demo.dao;
import com.example.demo.bean.BaseBean;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CommonDao extends JpaRepository {

}
package com.example.demo.dao;

import com.example.demo.bean.User;
import org.springframework.stereotype.Repository;


@Repository
public interface UserDao extends CommonDao {

}

 开始创建服务层相关类:

package com.example.demo.service;

import com.example.demo.bean.User;

import java.util.List;

public interface UserService {
    /**
     * 保存用户对象
     * @param user
     */
    void save(User user);
    /**
     * 查询所有用户信息
     * */
    List getUserList();
}

 

package com.example.demo.serviceimpl;

import com.example.demo.bean.User;
import com.example.demo.dao.UserDao;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Override
    public void save(User user) {
        userDao.save(user);
    }

    @Override
    public List getUserList() {
        return userDao.findAll();
    }
}

 如下是提供给前端页面访问的controller层:

package com.example.demo.controller;

import com.example.demo.bean.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/hello")
    @ResponseBody
    public String hello(){
        return "hello world ,you happy";
    }

    @RequestMapping("/index")
    public String index(Model model) {
        model.addAttribute("name", "jack");
        model.addAttribute("age", 20);
        model.addAttribute("info", "我是一个爱学习的好青年");
        return "index";
    }
    @RequestMapping("/save")
    @ResponseBody
    public String save(User user) {
        userService.save(user);
        return "save success !";
    }

    @RequestMapping("/userList")
    public String userList(Model model) {
        List userList = userService.getUserList();
        model.addAttribute("userList", userList);
        return "list";
    }
}

 前端使用了 thymeleaf,注意这里的thymeleaf类似于传统的jsp  freemarker等模板。注意,这里的如下文件名和你controller层中方法的返回值的名称一样,比如接口返回index,则这里的文件名定义为index.html。注意接口的返回值和文件名相差一个.html。

并且,接口所在的controller层,上方标注需要的注解是普通的@Controller,不能是@RestController,否则只会返回index, 而不是当前期望的html页面。使用thymeleaf注意用在maven中引入。




    
    Index


姓名:
年龄:
简介:

 如上,基本的定义就好了,可以正常启动项目,进行接口访问。

特别注意,因为该项目使用了spring的 JPA,可以自动完成实体类与数据库表的自动映射,不需要手动创建表,但是要首先在mysql中创建一个数据库,完成如上方mysql的application.properties中关于数据源的相关定义。并且成功连接数据库,否则会出现各种问题,后面会附加一些个人在运行中遇到的一些问题及解决方案。

 四、问题附加:

1、@Table(name = "user")爆红,提示 can't resolve table ,经搜索资料得知,mysql 数据库未成功连接上,

SpringBoot项目练习问题记录_第6张图片

于是配置idea与mysql的连接,操作为:View——》Tool windows——》Database,然后选择+号,添加数据源,因为我的是mysql,根据界面提示,我idea中没有mysql驱动mysql-coonector-8.0.15-jar  于是点击Download,完成了mysql的驱动安装,之后根据提示,填写如下界面信息,最终效果如下图:

SpringBoot项目练习问题记录_第7张图片

 初始如下配置时,测试TestConnection,结果显示:

Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' prope

于是查询资料,配置application.properties文件如下:

#通用数据源配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/sbootmysql?useUnicode=true&characterEncoding=utf8&serverTimezone=CST
spring.datasource.username=root
spring.datasource.password=youpassword
# Hikari 数据源专用配置
# JPA 相关配置
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create

》如果 @Table(name = "user")还报错,请根据Assign datasouce 此处是否配置有问题,正常应该是有值,如果没有则说明数据库连接有问题:

SpringBoot项目练习问题记录_第8张图片

点击如上下拉三角,应该有可选项,选择正确连接的数据源即可

SpringBoot项目练习问题记录_第9张图片

点击确定按钮,界面会自动刷新,user下的红色波浪线会消失,否则请继续检查。

至此,配置成功。

后补:在进行jpa的多数据源配置过程中,发现通@Table(name = “user”) 类似的爆红问题,发现@Column(name = "id")爆红,

提示原因同上,因为之前的经验,确定是因为在idea连接mysql的配置过程中配置项少一项,serverTimezone未设置,当出现msyql数据库连接成功时,会在下图3的位置出现一个绿色的小对号,同时该问题被解决

SpringBoot项目练习问题记录_第10张图片

五、与Junit相关的测试配置:

1、测试需要添加的相关配置,因为是Junit5,因为开始时删除了一些不知道的东西,后来出了很多错,发现这几个配置要注意加上


			org.springframework.boot
			spring-boot-starter-test
		
		
			
			org.junit.platform
			junit-platform-launcher
			test
		
		
			junit
			junit
			4.12
			test
		

 测试类如下:

package com.example.demo.controller;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {
    private MockMvc mockMvc;
    @Autowired
    private WebApplicationContext wac;

    @Before
    public void setup(){
        //1.初始化
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
    }
    @Test
    public void userList() throws Exception {

        MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/userList").accept(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(status().isOk()).andReturn();
        int status = mvcResult.getResponse().getStatus();
        //ModelMap map = (ModelMap) mvcResult.getModelAndView().getModel();
        //打印出状态码,200就是成功
        //  log.info("状态码="+status);
        Assert.assertEquals(200, status);
       // Assert.assertEquals(3, map);
    }
}

其中遇到错误时查看的相关文档有:

https://bbs.csdn.net/topics/395053502

 

2、在进行spring boot jpa 与 Redis的结合单元测试时,

参考了http://www.ityouknow.com/springboot/2016/03/06/spring-boot-redis.html

redis连接配置环境如下:

application.properties 中配置如下:

# Redis数据库索引(默认为0)
spring.redis.database=0  
# Redis服务器地址
spring.redis.host=自己redis服务器在的地址,如果是本地,则为127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379  
# Redis服务器连接密码(默认为空)
spring.redis.password=123456
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0

在src ——main——和bean包相同等级处创建了一个用于管理各种配置的config包,在其中存放各个模块的配置类。

为Redis创建了一个RedisConfig类,内容如下:

package com.example.demo.config;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public KeyGenerator keyGenerator() {
        return (target, method, 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();
        };
    }
}

 

又创建了一个测试类,如下:

package com.example.demo.service;

import com.example.demo.bean.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.concurrent.TimeUnit;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class RedisTest {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void test() throws Exception {
        stringRedisTemplate.opsForValue().set("aaa", "111");
        Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa"));
    }

    @Test
    public void testObj() throws Exception {
        User user=new User();
        user.setName("cesssssss");
        user.setAge(88);
        user.setInfo("我想要去上班");
        ValueOperations operations=redisTemplate.opsForValue();
        operations.set("com.neox", user);
        operations.set("com.neo.f", user,1, TimeUnit.SECONDS);
        Thread.sleep(1000);
        //redisTemplate.delete("com.neo.f");
        boolean exists=redisTemplate.hasKey("com.neo.f");
        if(exists){
            System.out.println("exists is true");
        }else{
            System.out.println("exists is false");
        }
         //Assert.assertEquals("aa", operations.get("com.neo.f").getUserName());
    }
}

但是在此过程中出现了几个问题,参考的相关文档如下:

问题3:一个方法测试通过,另一个错误:

SpringBoot项目练习问题记录_第11张图片

org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.example.demo.bean.User]

	at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:96)
	at org.springframework.data.redis.core.AbstractOperations.rawValue(AbstractOperations.java:127)
	at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:235)
	at com.example.demo.service.RedisTest.testObj(RedisTest.java:37)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
	at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.example.demo.bean.User]
	at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:68)
	at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:35)
	at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:94)
	... 33 more
Caused by: java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.example.demo.bean.User]
	at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:43)
	at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:63)
	... 35 more

解决方案参考了文章:https://www.cnblogs.com/han-1034683568/p/7994322.html

原因是,我的实体bean当时没有继承序列化接口:让 User类实现Serialiazeable 序列化接口即可。

4、问题是:

SpringBoot项目练习问题记录_第12张图片


java.lang.Exception: No runnable methods

	at org.junit.runners.BlockJUnit4ClassRunner.validateInstanceMethods(BlockJUnit4ClassRunner.java:191)
	at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:128)
	at org.junit.runners.ParentRunner.validate(ParentRunner.java:416)
	at org.junit.runners.ParentRunner.(ParentRunner.java:84)
	at org.junit.runners.BlockJUnit4ClassRunner.(BlockJUnit4ClassRunner.java:65)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.(SpringJUnit4ClassRunner.java:137)
	at org.springframework.test.context.junit4.SpringRunner.(SpringRunner.java:49)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
	at org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder$DefensiveAnnotatedBuilder.buildRunner(DefensiveAllDefaultPossibilitiesBuilder.java:113)
	at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
	at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
	at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
	at org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder.runnerForClass(DefensiveAllDefaultPossibilitiesBuilder.java:56)
	at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
	at org.junit.vintage.engine.discovery.ClassSelectorResolver.resolveTestClass(ClassSelectorResolver.java:66)
	at org.junit.vintage.engine.discovery.ClassSelectorResolver.resolve(ClassSelectorResolver.java:47)
	at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.lambda$resolve$2(EngineDiscoveryRequestResolution.java:129)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1631)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:543)
	at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:174)
	at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:120)
	at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveCompletely(EngineDiscoveryRequestResolution.java:87)
	at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.run(EngineDiscoveryRequestResolution.java:80)
	at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver.resolve(EngineDiscoveryRequestResolver.java:112)
	at org.junit.vintage.engine.discovery.VintageDiscoverer.discover(VintageDiscoverer.java:42)
	at org.junit.vintage.engine.VintageTestEngine.discover(VintageTestEngine.java:62)
	at org.junit.platform.launcher.core.DefaultLauncher.discoverEngineRoot(DefaultLauncher.java:177)
	at org.junit.platform.launcher.core.DefaultLauncher.discoverRoot(DefaultLauncher.java:164)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

正常运行完毕,会显示绿色,查看redis数据库,通过 keys * 可以看到数据库中增加了内容:

xxx.xx.xx.xxx:6379>  Keys *
1) "\xac\xed\x00\x05t\x00\bcom.neox"
2) "username"
3) "aaa"
xxx.xx.xx.xxx:6379> 

如上为手动为redis设置缓存,redis自动有缓存。我重新创建了一个RedisController,然后添加了方法,之后直接启动运行,访问浏览器,随后查看redis数据库内容进行验证:

package com.example.demo.controller;

import com.example.demo.bean.User;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RedisController {

    @RequestMapping("/getUser")
    @Cacheable(value="user-key")
    public User getUser() {
        User user=new User();
        user.setInfo("爱我中华,抗疫必胜");
        user.setAge(11);
        user.setName("小雪");
        System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功");
        return user;
    }
}

 SpringBoot项目练习问题记录_第13张图片

xxx.xx.xx.xxx:6379>  keys *
1) "\xac\xed\x00\x05t\x00\bcom.neox"
2) "username"
3) "user-key::com.example.demo.controller.RedisControllergetUser"
4) "aaa"
xxx.xx.xx.xxx:6379> 

3、更改redis的配置,如失效时间等,此处需要引入相关依赖包:


			org.springframework.session
			spring-session-data-redis
		

创建一个redis的java配置文件

package com.example.demo.config;

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

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
}

测试接口:

@RequestMapping("/uid")
    String uid(HttpSession session) {
        UUID uid = (UUID) session.getAttribute("uid");
        if (uid == null) {
            uid = UUID.randomUUID();
        }
        session.setAttribute("uid", uid);
        return session.getId();
    }

SpringBoot项目练习问题记录_第14张图片

登录 Redis 输入 keys '*sessions*' 

xxx.xx.xx.xxx:6379>  keys '*sessions*'
1) "spring:session:sessions:expires:6517e1d7-24e7-470b-88bb-903299321058"
2) "spring:session:sessions:6517e1d7-24e7-470b-88bb-903299321058"
xxx.xx.xx.xxx:6379> 

其中 1472976480000 为失效时间,意思是这个时间后 Session 失效,db031986-8ecc-48d6-b471-b137a3ed6bc4 为 sessionId,登录 http://localhost:8080/uid 发现会一致,就说明 Session 已经在 Redis 里面进行有效的管理了。

解决方案参考了文档:

https://blog.csdn.net/lansexiuzhifu/article/details/81413477

原因是 ,导错了包:

1.导错了包:@Test时import的是@org.testng.annotations.Test    所以会报错

 

 

 

你可能感兴趣的:(java,EE,java,web,springboot)