Spring学习知识点大全(三)

简介: 教程来源 https://app-aakcgtuh1ywx.appmiaoda.com 本文系统介绍Spring生态核心实践:涵盖单元测试(MockBean+断言)、集成测试(MockMvc+事务回滚)、SpEL表达式(属性注入、集合操作等)、Spring Boot自动配置原理及YAML配置要点,助力高效构建企业级应用。

七、测试支持

7.1 单元测试

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @MockBean
    private UserDao userDao;

    @Test
    public void testCreateUser() {
        User user = new User("张三", 25);

        when(userDao.insert(any(User.class))).thenReturn(1);

        User result = userService.create(user);

        assertNotNull(result);
        assertEquals("张三", result.getUsername());
        verify(userDao, times(1)).insert(any(User.class));
    }

    @Test(expected = BusinessException.class)
    public void testCreateUserWithInvalidAge() {
        User user = new User("李四", -1);
        userService.create(user);
    }

    @Test
    public void testFindUser() {
        User expected = new User(1L, "王五", 30);
        when(userDao.findById(1L)).thenReturn(expected);

        User actual = userService.findById(1L);

        assertEquals(expected.getUsername(), actual.getUsername());
    }
}

7.2 集成测试

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@Transactional
@Rollback
public class UserControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    public void testGetUser() throws Exception {
        mockMvc.perform(get("/api/users/1")
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.id").value(1))
                .andExpect(jsonPath("$.username").value("张三"))
                .andDo(print());
    }

    @Test
    public void testCreateUser() throws Exception {
        User user = new User("李四", 25);

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(user)))
                .andExpect(status().isCreated())
                .andExpect(jsonPath("$.id").exists())
                .andExpect(jsonPath("$.username").value("李四"));
    }

    @Test
    public void testValidationError() throws Exception {
        User user = new User("", -1);

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(user)))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.code").value(400));
    }
}

八、Spring 表达式语言(SpEL)

@Component
public class SpELDemo {

    @Value("#{systemProperties['user.name']}")
    private String userName;

    @Value("#{systemProperties['java.version']}")
    private String javaVersion;

    @Value("#{T(Math).random() * 100.0}")
    private double randomNumber;

    @Value("#{userService.findUser(1)?.username ?: 'Unknown'}")
    private String defaultUsername;

    @Value("#{userService.users.?[age > 25]}")
    private List<User> adults;

    @Value("#{userService.users.![username]}")
    private List<String> usernames;

    public void testSpEL() {
        ExpressionParser parser = new SpelExpressionParser();

        // 字面量
        String hello = parser.parseExpression("'Hello World'").getValue(String.class);

        // 数学运算
        int sum = parser.parseExpression("1 + 2 + 3").getValue(Integer.class);

        // 逻辑运算
        boolean result = parser.parseExpression("2 > 1 && 3 < 5").getValue(Boolean.class);

        // 方法调用
        String upper = parser.parseExpression("'hello'.toUpperCase()").getValue(String.class);

        // 属性访问
        Expression exp = parser.parseExpression("user.username");
        User user = new User("张三", 25);
        String username = exp.getValue(user, String.class);

        // 安全导航
        String email = parser.parseExpression("user?.email ?: 'no-email'")
                           .getValue(user, String.class);

        // 集合选择
        List<User> users = Arrays.asList(
            new User("张三", 30),
            new User("李四", 20),
            new User("王五", 35)
        );

        List<User> adults = parser.parseExpression("#root.?[age >= 25]")
                                  .getValue(users, List.class);

        // 集合投影
        List<String> names = parser.parseExpression("#root.![username]")
                                   .getValue(users, List.class);
    }
}

// 在 XML 中使用 SpEL
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
    <property name="jdbcUrl" value="#{systemProperties['db.url']}"/>
    <property name="username" value="#{systemProperties['db.username']}"/>
    <property name="password" value="#{systemProperties['db.password']}"/>
</bean>

九、Spring 与 Spring Boot

9.1 Spring Boot 简介
Spring Boot 是 Spring 框架的扩展,通过自动配置和起步依赖简化了 Spring 应用的开发。

核心特性:

自动配置:根据类路径中的依赖自动配置 Spring

起步依赖:简化 Maven/Gradle 依赖管理

嵌入式服务器:内置 Tomcat、Jetty 等

生产就绪:提供健康检查、指标监控等

无代码生成和 XML 配置

9.2 Spring Boot 应用

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

// application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: 123456
    hikari:
      maximum-pool-size: 10
      connection-timeout: 30000

  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect

  redis:
    host: localhost
    port: 6379
    timeout: 2000ms

  cache:
    type: redis

  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 100MB

server:
  port: 8080
  servlet:
    context-path: /api
    session:
      timeout: 1800s

logging:
  level:
    com.example: DEBUG
    org.springframework.web: INFO
  file:
    name: logs/application.log

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: always

9.3 Spring Boot 自动配置

// 自定义自动配置
@Configuration
@ConditionalOnClass(RedisTemplate.class)
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
@EnableConfigurationProperties(CacheProperties.class)
public class CustomCacheAutoConfiguration {

    @Autowired
    private CacheProperties properties;

    @Bean
    @ConditionalOnMissingBean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(properties.getTtl()))
            .serializeValuesWith(
                RedisSerializationContext.SerializationPair.fromSerializer(
                    new GenericJackson2JsonRedisSerializer()
                )
            );

        return RedisCacheManager.builder(factory)
            .cacheDefaults(config)
            .build();
    }
}

// 配置属性类
@ConfigurationProperties(prefix = "cache")
public class CacheProperties {
    private long ttl = 60;
    private int maxSize = 1000;

    // getter/setter
}

Spring 的世界广阔而精彩,愿本文成为你 Spring 学习之路上的重要指南。持续学习,深入实践,你一定能成为 Spring 专家!
来源:
https://app-aakcgtuh1ywx.appmiaoda.com

相关文章
|
24天前
|
SQL XML Java
MyBatis学习知识点大全(一)
教程来源 https://app-abggx9rbr6dd.appmiaoda.com MyBatis 是轻量级Java持久层框架,简化JDBC开发,支持XML/注解映射、动态SQL、缓存及Spring集成。本文系统梳理其核心概念、架构原理、环境搭建与动态SQL等关键知识点,助力初学者构建完整知识体系,也为开发者提供深度技术参考。
|
24天前
|
IDE 开发工具 Swift
Xcode 26.4 (17E192) 发布 - Apple 平台 IDE
Xcode 26.4 (17E192) 发布 - Apple 平台 IDE
421 1
|
存储 人工智能 Rust
1句话给你的 OpenClaw 装上"长期记忆" — 基于 PolarDB-X 的 mem0 记忆方案
PolarDB Mem0是一款为AI Agent构建专属长效记忆的托管服务,100%兼容开源的Mem0系统。通过在多次交互中高效地抽取、存储与调用记忆,赋予Agent持续学习与积累认知的能力,帮助您打造真正智能和个性化的AI应用。
|
23天前
|
存储 人工智能 弹性计算
2026阿里云活动汇总:最新云服务器抢购、AI焕新季、云产品组合购及优惠券活动
2026年阿里云推出多项优惠活动,涵盖轻量应用服务器与云服务器特价抢购、AI焕新季礼包、云产品组合特惠及优惠券等多重福利。活动面向个人开发者、学生、初创企业及中小企业,提供从入门到高性能计算的全场景云资源需求解决方案。用户可根据需求选择不同配置的云服务器,如38元/年的轻量2核2G服务器、99元/年的经济型e实例等,并享受安全加速、数据分析、建站推广等一站式服务。灵活运用优惠券可进一步降低成本,助力业务创新与增长。
|
24天前
|
SQL 弹性计算 网络协议
通过阿里云的活动选购云服务器ECS之后如何设置安全组?安全组相关知识及设置流程参考
本文介绍了阿里云云服务器ECS安全组的设置流程,包括安全组规则介绍、规则构成、匹配策略及特殊场景规则说明。安全组作为云上虚拟防火墙,通过自定义规则控制ECS实例的出入站流量。配置时,需注意经典网络与VPC规则方向差异,并提供了快速添加安全组规则和手动添加两种方法。同时,介绍了安全组规则诊断工具,可快速定位如ping不通、服务访问失败等常见问题。
|
24天前
|
数据管理 API
ISBN书号查询-ISBN图书查询-ISBN书号解析API接口介绍
ISBN是国际标准书号,13位唯一标识符,相当于图书“身份证”。含前缀、国家区号、出版社码、书序号及校验码。用于版本区分、全球流通、出版准入与数据管理。支持API查询书名、作者、出版社等全量元数据。
654 0
|
24天前
|
人工智能
告别单打独斗:Qoder 开启 AI 编程的“多 Agent 团队作战”时代
3月26日14:00-17:20,阿里巴巴数字生态创新园7号楼321暮雪阁,聚焦AI编程实战:Qoder团队协作开发、Spec/Harness/Agent进阶、CLI构建AI-Native应用及ROI提升经验分享。新手与高手皆宜,速报名!
187 0
|
Java 数据库连接 测试技术
SpringBoot集成mybatis-plus及分页实现
SpringBoot集成mybatis-plus及分页实现
667 0
|
开发框架 前端开发 Java
【Spring】Spring框架介绍,功能模块,容器知识和有关Spring的生态圈的详细讲解
【Spring】Spring框架介绍,功能模块,容器知识和有关Spring的生态圈的详细讲解
704 0
|
存储 算法 Java
Stream很好,Map很酷,但答应我别滥用toMap()!
【8月更文挑战第27天】在Java的世界里,Stream API和Map数据结构无疑是现代编程中的两大瑰宝。Stream API以其函数式编程的优雅和强大的数据处理能力,让集合操作变得简洁而高效;而Map则以其键值对的存储方式,为数据的快速检索和更新提供了便利。然而,当这两者相遇,特别是当我们试图通过Stream的toMap()方法将流中的元素转换为Map时,一些潜在的问题和陷阱便悄然浮现。今天,我们就来深入探讨一下这个话题,并探讨如何更加安全、高效地利用这些强大的工具。
301 0

热门文章

最新文章

下一篇
开通oss服务