公司项目需要迁移Spring Boot上面,迁移过程中遇到一些问题和解决方案,在此记录下方便其他人查看,Spring Boot介绍官方和网上有很多资料可供学习,本文以Maven为例介绍Spring Boot;另外,项目中涉及配置信息等通过config-toolkit集中管理配置;
1 Spring Boot目录结构
1.1 完整pom.xml内容
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<groupId>com.test</groupId>
<artifactId>spring-boot-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<alibaba.druid.version>1.0.15</alibaba.druid.version>
<config-toolkit.version>3.2.2-RELEASE</config-toolkit.version>
<dubbo.version>2.5.8</dubbo.version>
<zookeeper.version>3.4.6</zookeeper.version>
<zkclient.version>0.1</zkclient.version>
</properties>
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Unit Tests-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>config-toolkit</artifactId>
<version>${config-toolkit.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- spring-boot-starter-jdbc 模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${alibaba.druid.version}</version>
</dependency>
<!--devtools-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--dubbo-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>2.0.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- <configuration>
<excludeDevtools>false</excludeDevtools>
</configuration>-->
</plugin>
</plugins>
</build>
</project>
1.2 启动类Application
注:main
方法所在的这个主要的配置类配置在根包名下,否则启动时无法找到相关依赖;
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Administrator
* @title:
* @package com.test
* @copyright: Copyright (c) 2018
* @date 2018/1/4 0007 12:02
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication注解 包含@Configuration + @EnableAutoConfiguration + @ComponentScan。其中@EnableAutoConfiguration注释,此注释自动载入应用程序所需的所有Bean。日志级别为debug时,会看到~~
1.3 内嵌 Server 配置
Spring Boot 其默认是集成web容器的,启动方式由像普通Java程序一样,main函数入口启动。其内置Tomcat容器或Jetty容器,具体由配置来决定(默认Tomcat)。通过配置文件(application.yml)的方式类修改相关server配置。
2 配置Config Toolkit
Config Toolkit 参考https://github.com/dangdangdotcom/config-toolkit/wiki
2.1 添加maven依赖
...
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>config-toolkit</artifactId>
<version>${config-toolkit.version}</version>
</dependency>
...
2.2 添加配置信息application.yml
config-toolkit:
connect-str: 127.0.0.1:2181 #zk地址
root-node: /config/test
version: 1.0.0
2.3 添加config bean
package com.test.configuration;
import com.dangdang.config.service.ConfigGroup;
import com.dangdang.config.service.zookeeper.ZookeeperConfigGroup;
import com.dangdang.config.service.zookeeper.ZookeeperConfigProfile;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @package com.test.configuration
* @copyright: Copyright (c) 2018
* @date 2018/1/4 0005 18:13
*/
@Configuration
public class ConfigToolkitConfig {
@Bean
public ZookeeperConfigProfile getConfigProfile(@Value("${config-toolkit.connect-str}") String connectStr, @Value("${config-toolkit.root-node}") String rootNode,
@Value("${config-toolkit.version}") String version) {
return new ZookeeperConfigProfile(connectStr, rootNode, version);
}
/**
* 数据源等配置
*
* @param configProfile
* @return
*/
@Bean("jdbcGroup")
public ConfigGroup getApplicationGroup(ZookeeperConfigProfile configProfile) {
return new ZookeeperConfigGroup(configProfile, "jdbc");
}
/**
* redis配置
*
* @param configProfile
* @return
*/
@Bean("redisGroup")
public ConfigGroup getRedisGroup(ZookeeperConfigProfile configProfile) {
return new ZookeeperConfigGroup(configProfile, "redis");
}
/**
* dubbo 配置
* @param configProfile
* @return
*/
@Bean("dubboGroup")
public ConfigGroup getDubboGroup(ZookeeperConfigProfile configProfile) {
return new ZookeeperConfigGroup(configProfile, "dubbo");
}
}
以上ConfigToolkit配置成功,并且相关配置信息,已导入。然后在需要使用的地方直接注入对应的map
@Value("#{publicConfig}")
private Map<String, String> publicConfig;
或者
@Value("#{redisGroup['redis.url']}")
private String host;
3 配置Druid
3.1 添加maven依赖
...
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- spring-boot-starter-jdbc 模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${alibaba.druid.version}</version>
</dependency>
...
3.2 添加config bean
package com.test.configuration;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* @package com.test.configuration
* @copyright: Copyright (c) 2018
* @date 2018/1/4 0006 14:58
*/
@Configuration
public class DruidConfig {
private Logger logger = LoggerFactory.getLogger(DruidConfig.class);
@Value("#{jdbcGroup['jdbc.url']}")
private String dbUrl;
@Value("#{jdbcGroup['jdbc.username']}")
private String username;
@Value("#{jdbcGroup['jdbc.password']}")
private String password;
@Value("#{jdbcGroup['druid.initialSize']}")
private int initialSize;
@Value("#{jdbcGroup['druid.minIdle']}")
private int minIdle;
@Value("#{jdbcGroup['druid.maxActive']}")
private int maxActive;
@Value("#{jdbcGroup['druid.maxWait']}")
private int maxWait;
@Value("#{jdbcGroup['druid.timeBetweenEvictionRunsMillis']}")
private int timeBetweenEvictionRunsMillis;
@Value("#{jdbcGroup['druid.minEvictableIdleTimeMillis']}")
private int minEvictableIdleTimeMillis;
@Value("#{jdbcGroup['druid.validationQuery']}")
private String validationQuery;
@Value("#{jdbcGroup['druid.testWhileIdle']}")
private boolean testWhileIdle;
@Value("#{jdbcGroup['druid.testOnBorrow']}")
private boolean testOnBorrow;
@Value("#{jdbcGroup['druid.testOnReturn']}")
private boolean testOnReturn;
@Value("#{jdbcGroup['druid.filters']}")
private String filters;
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean reg = new ServletRegistrationBean();
reg.setServlet(new StatViewServlet());
reg.addUrlMappings("/druid/*");
reg.addInitParameter("loginUsername", username);
reg.addInitParameter("loginPassword", password);
return reg;
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
filterRegistrationBean.addInitParameter("profileEnable", "true");
return filterRegistrationBean;
}
@Bean
public DataSource druidDataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
logger.error("druid configuration initialization filter", e);
}
return datasource;
}
}
3.3 数据库查询
package com.test.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* @copyright: Copyright (c) 2018
* @date 2017/1/5 0005 15:08
*/
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<Map<String, Object>> findById(String id) {
return jdbcTemplate.queryForList("select id,nick_name from user where id=?", new Object[]{id});
}
}
4 配置dubbo
在Spring Boot中使用Dubbo,不需要使用xml的方式来配置生产者和消费者,本文使用@Bean注解的方式来进行配置。
4.1 添加maven依赖
...
<!--dubbo-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>${zkclient.version}</version>
</dependency>
...
4.2 添加config bean
package com.test.api.configuration;
import com.alibaba.dubbo.config.*;
import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Administrator
* @title: spring-boot-test
* @package com.test.configuration
* @copyright: Copyright (c) 2017
* @date 2017/12/15 0015 11:53
*/
@Configuration
@DubboComponentScan(basePackages = { "com.test.api.controller", "com.test.api.service" })
public class DubboBaseConfig {
@Value("#{dubboGroup['dubbo.registry.address']}")
private String address;
@Value("#{dubboGroup['dubbo.protocol.port']}")
private int dubboPort;
@Value("#{dubboGroup['dubbo.provider.timeout']}")
private int timeout;
@Value("#{dubboGroup['dubbo.provider.retries']}")
private int retries;
@Value("#{dubboGroup['dubbo.provider.loadbalance']}")
private String loadbalance;
@Value("#{dubboGroup['dubbo.application']}")
private String applicationName;
@Bean
public ApplicationConfig application() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName(applicationName);
return applicationConfig;
}
@Bean
public RegistryConfig registry() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress(address);
registryConfig.setProtocol("zookeeper");
registryConfig.setClient("curator");
return registryConfig;
}
@Bean
public ProtocolConfig protocol() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setPort(dubboPort);
protocolConfig.setName("dubbo");
return protocolConfig;
}
/**
* dubbo 监控中心
*/
/*@Bean
public MonitorConfig monitorConfig() {
MonitorConfig mc = new MonitorConfig();
mc.setProtocol("registry");
return mc;
}
@Bean
public ReferenceConfig referenceConfig() {
ReferenceConfig rc = new ReferenceConfig();
rc.setMonitor(monitorConfig());
return rc;
}*/
}
4.3 Dubbo生产者配置,需要继承Dubbo基础配置
@Configuration
public class ExportServiceConfig extends DubboBaseConfig {
@Bean
public ServiceBean<Person> personServiceExport(Person person) {
ServiceBean<Person> serviceBean = new ServiceBean<Person>();
serviceBean.setProxy("javassist");
serviceBean.setVersion("myversion");
serviceBean.setInterface(Person.class.getName());
serviceBean.setRef(person);
serviceBean.setTimeout(5000);
serviceBean.setRetries(3);
return serviceBean;
}
}
4.4 Dubbo消费者配置,需要继承Dubbo基础配置
消费端由于spring 扫描的时候根本无法识别@Reference ,同一方面,dubbo的扫描也无法识别Spring @Controller ,所以增加@DubboComponentScan(basePackages = { "com.test.api.controller", "com.test.api.service" })预防扫dubbo的服务出现空指针。
@Configuration
public class ReferenceConfig extends DubboBaseConfig {
@Bean
public ReferenceBean<Person> person() {
ReferenceBean<Person> ref = new ReferenceBean<>();
ref.setVersion("myversion");
ref.setInterface(Person.class);
ref.setTimeout(5000);
ref.setRetries(3);
ref.setCheck(false);
return ref;
}
}
或者在消费端 通过@Reference注解,注入dubbo服务;
5 配置redis
5.1 添加maven依赖
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
5.2添加config bean
package com.test.api.configuration;
import com.test.service.JedisService;
import com.test.service.impl.JedisServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* @package com.test.configuration
* @copyright: Copyright (c) 2017
* @date 2017/12/6 0006 15:34
*/
@Configuration
public class RedisConfig extends BaseRedisConfig {
@Value("#{redisGroup['redis.url']}")
private String host;
@Value("#{redisGroup['redis.port']}")
private int port;
@Value("#{redisGroup['redis.timeout']}")
private int timeout;
@Value("#{redisGroup['redis.maxTotal']}")
private int maxTotal;
@Value("#{redisGroup['redis.maxIdle']}")
private int maxIdle;
@Value("#{redisGroup['redis.maxWait']}")
private long maxWaitMillis;
@Value("#{redisGroup['redis.passwd']}")
private String password;
private boolean testOnBorrow = true;
@Bean
public JedisPoolConfig getPoolConfig() {
return this.getPoolConfig(maxIdle, maxWaitMillis, testOnBorrow, maxTotal);
}
@Bean
public JedisPool getJedisPool() {
return new JedisPool(getPoolConfig(), host, port, timeout, password);
}
@Bean
public JedisConnectionFactory getJedisConnectionFactory() {
return getJedisConnectionFactory(getPoolConfig(), host, password);
}
/**
* JedisService 本地的redis服务,JedisServiceImpl实现类
* @return
* @throws Exception
*/
@Bean(name = "jedisService")
public JedisService getJedisService() throws Exception {
JedisServiceImpl jd = new JedisServiceImpl();
jd.setJedisPool(getJedisPool());
return jd;
}
}
由于项目中有时会配置多个redis源,需要在ConfigToolkitConfig文件中配置多个reidsAGroup,config redisBean时使用reidsAGroup,同时JedisService需要注入
/**
* JedisService 本地的redis服务,JedisServiceImpl实现类
* @return
* @throws Exception
*/
@Bean(name = "jedisAService")
public JedisService getAJedisService() throws Exception {
JedisServiceImpl jd = new JedisServiceImpl();
jd.setJedisPool(getJedisPool());
return jd;
}
6 Spring Boot添加自定义Filter
6.1编写自己的Filter
package com.test.api.aop;
import com.test.api.log.LogToEmail;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@WebFilter(urlPatterns = "/*", filterName = "timingFilter", initParams = { @WebInitParam(name = "encoding", value = "UTF-8"), @WebInitParam(name = "forceEncoding", value = "true") })
@Order(1)
public class TimingFilter implements Filter {
@Autowired
private LogToEmail logToEmail;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//TODO
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
需要使用@WebFilter注解,其中@Order注解表示执行过滤顺序,值越小,越先执行;另外,war包形式如果自定义Filter如果引用其他服务,@Resource 注入无效,tomcat会识别此注解,so用@Autowired替换;
我们在spring-boot的入口处加上如下注解@ServletComponentScan:
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Administrator
* @title:
* @package com.test
* @copyright: Copyright (c) 2018
* @date 2018/1/4 0007 12:02
*/
@SpringBootApplication
@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
7 注意事项
-
启动类Application所在的这个主要的配置类配置在根包名下,否则启动时无法找到相关依赖;
- springboot war包形式如果自定义Filter如果引用其他服务,@Resource 注入无效,tomcat会识别此注解,用@Autowired替换;
- 消费端由于spring 扫描的时候根本无法识别@Reference ,同一方面,dubbo的扫描也无法识别Spring @Controller ,所以增加@DubboComponentScan(basePackages = { "com.test.api.controller", "com.test.api.service" })预防扫dubbo的服务出现空指针。
-
springboot解决Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 问题jar方式运行,由于springboot默认tomcat 就是将所有的参数都进行编码;例外一种,换容器jetty;
后续会把相关demo包上传
相关推荐
### Spring Boot 学习笔记知识点 #### 1. Spring Boot 简介 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。它使用了特定的方式来配置Spring,使得开发者...
本学习资源包“java maven工程 spring boot 学习源码”提供了一个可以直接运行的示例工程,有助于深入理解Spring Boot和Maven的结合使用。 首先,我们需要了解Spring Boot的核心特性。Spring Boot通过内嵌的Servlet...
Spring Boot学习之Shiro源码【学习狂神说,自己手动书写,可以实现正常所需的功能】 Spring Boot学习之Shiro源码【学习狂神说,自己手动书写,可以实现正常所需的功能】 Spring Boot学习之Shiro源码【学习狂神说,...
**Spring Boot 学习示例** Spring Boot 是一个由 Pivotal 团队开发的 Java 框架,旨在简化初始设置和配置,使开发者能够快速地构建基于 Spring 平台的应用程序。它通过内嵌的 Servlet 容器(如 Tomcat 或 Jetty)...
【Spring Boot学习笔记】 Spring Boot是Java开发领域中一个非常受欢迎的框架,它极大地简化了创建独立、生产级别的基于Spring的应用程序的过程。Spring Boot的核心理念是“约定优于配置”,这使得开发者可以快速...
《Spring Boot 学习Demo深度解析》 Spring Boot 是由 Pivotal 团队开发的框架,它旨在简化 Spring 应用程序的初始搭建以及开发过程。Spring Boot 基于“约定优于配置”的原则,提供了大量的默认配置,使得开发者...
本项目为“基于Java的Spring Boot学习项目设计源码”,包含37个文件,其中包括20个Java源文件、7个XML配置文件、3个YAML配置文件、1个Markdown文档、1个Gitignore忽略配置文件、1个JAR包、1个Properties配置文件、1...
### Spring Boot 学习笔记知识点总结 #### 一、Spring发展史 - **Spring1.x时代**:在Spring1.x的时代,主要通过XML文件来配置Bean。随着项目的规模扩大,XML配置文件的数量也随之增加,这导致开发人员需要频繁地...
在 "Spring Boot 学习系列" 中,我们可以深入理解以下几个核心知识点: 1. **自动配置**:Spring Boot 的一大特色就是其自动配置功能。通过`@EnableAutoConfiguration`注解,Spring Boot 可以根据项目依赖自动配置...
在“Spring Boot学习代码”中,我们可以看到它整合了多个流行的技术组件,这包括: 1. Redis:Redis 是一个开源的、基于键值对的数据存储系统,常被用作数据库、缓存和消息代理。Spring Boot 提供了与 Redis 集成的...
spring boot学习视频,如果看不了,请留言,对于初学springBoot的同学,还是很不错的,简单易懂
Spring Boot资料下载,SpringBoot几套完整的视频教程包含资源,绝对真实,欢迎下载
这个压缩包包含了丰富的Spring Boot学习资料以及实际项目案例,是深入理解和掌握Spring Boot技术的宝贵资源。 首先,让我们从基础开始。Spring Boot的核心理念是“约定优于配置”,它通过默认配置和自动配置,使得...
在学习Spring Boot的过程中,理解其核心组件如Spring MVC、Spring Data JPA、Spring AOP等至关重要。Spring MVC是Spring框架的一个模块,用于处理HTTP请求和响应,而Spring Data JPA则简化了数据库操作,提供了ORM...
spring boot学习指南
《Spring Boot参考指南》是Spring Boot开发者的重要参考资料,它详细阐述了Spring Boot...这份中文翻译版本的出现,无疑为国内的Spring Boot学习者提供了极大的便利,使得开发者能够更好地理解和应用这一强大的框架。