Spring Boot常见企业开发场景应用、自动配置原理结构分析(三)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: Spring Boot常见企业开发场景应用、自动配置原理结构分析

Spring Boot常见企业开发场景应用、自动配置原理结构分析(二)https://developer.aliyun.com/article/1423060


  1. 这里导入了ActiveMQ的起步依赖
  2. 编写DAO
public interface UserRepository extends JpaRepository{
}
1. 编写Service
public interface UserService {
 /**
  * 根据ID获取用户
  * @param i
  * @return
  */
 User get(int id);
 /**
  * 查询所有用户
  * @return
  */
 List findAll();
 /**
  * 新增用户
  * @param user
  */
 void add(User user);
}
@Service
@Transactional
public class UserServiceImpl implements UserService{
 @Autowired
 private UserRepository userRepository;
 @Override
 public User get(int id) {
  return userRepository.findOne(id);
 }
 @Override
 public List findAll() {
  return userRepository.findAll();
 }
 @Override
 public void add(User user) {
  userRepository.save(user);
 }
}
1. 编写Controller
@Controller
@RequestMapping("/user")
public class UserController {
 @Autowired
 private UserService userService;
 @Autowired
 private JmsTemplate jmsTemplate;
 @RequestMapping("/findUserList")
 public String findUserList(Model model) {
  List list = userService.findAll();
  model.addAttribute("list", list);
  return "/index.jsp";
 }
 @RequestMapping("/add")
 public String add(User user) {
  userService.add(user);
  final List userList = userService.findAll();
  jmsTemplate.send("queue_page", new MessageCreator() {
   @Override
   public Message createMessage(Session session) throws JMSException {
    return session.createTextMessage(JSON.toJSONString(userList));
   }
  });
  return "redirect:/user/findUserList";
 }
}
1. 在添加一个用户,往AMQ中发送一条queue消息
2. 编写Listener
@Component
public class PageGeneratorListener {
 @Value("${freemarker.output_path}")
 private String OUTPUT_PATH;
 @Autowired
 private Configuration configuration;
 @JmsListener(destination="queue_page")
 public void genHtml(String userListStr) throws Exception {
  Template template = configuration.getTemplate("user_list.ftl");
  List userList = JSON.parseArray(userListStr, User.class);
  Map map = new HashMap();
  map.put("list", userList);
  template.process(map, new FileWriter(OUTPUT_PATH + "user_list.html"));
 }
}
1. 监听AMQ中queue_page队列的消息,如果接收到消息,使用FreeMarker重新生成一个HTML页面在服务器端
2. 编写入口
@SpringBootApplication
public class Application {
 public static void main(String[] args) {
  SpringApplication.run(Application.class);
 }
 @Bean(name="datasource")
 @Primary
 @ConfigurationProperties(prefix="c3p0")
 public ComboPooledDataSource c3p0DataSource() throws PropertyVetoException {
  ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
  return comboPooledDataSource;
 }
}
1. 编写配置文件
server.port=10086
server.context-path=/
freemarker.output_path=G:/workspace/free_test/t51/src/main/webapp/
spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.user=admin
spring.activemq.password=admin
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///springboot
c3p0.user=root
c3p0.password=000000
  1. 构建基于Spring Security访问控制应用程序
  1. 导入依赖
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.14.RELEASE</version>
 </parent>
 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.6</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
  </dependency>
  <dependency>
   <groupId>org.apache.tomcat.embed</groupId>
   <artifactId>tomcat-embed-jasper</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
  </dependency>
  <dependency>
   <groupId>c3p0</groupId>
   <artifactId>c3p0</artifactId>
   <version>0.9.1</version>
  </dependency>
  <dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-lang3</artifactId>
   <version>3.4</version>
  </dependency>
 </dependencies>
a. 导入了Spring Security的起步依赖spring-boot-starter-security
b. 编写DAO
public interface UserRepository extends JpaRepository<User, Integer>{
 // 根据用户名查询用户
 User findByUsername(String username);
}
  1. 编写Service
public interface UserService {
 /**
  * 根据ID获取用户
  * @param i
  * @return
  */
 User get(int id);
 /**
  * 查询所有用户
  * @return
  */
 List<User> findAll();
 /**
  * 新增用户
  * @param user
  */
 void add(User user);
}
@Service
@Transactional
public class UserServiceImpl implements UserService{
 @Autowired
 private UserRepository userRepository;
 @Override
 public User get(int id) {
  return userRepository.findOne(id);
 }
 @Override
 public List<User> findAll() {
  return userRepository.findAll();
 }
 @Override
 public void add(User user) {
  userRepository.save(user);
 }
}
  1. 编写Spring Security登录验证用户服务
@Service
@Transactional
public class AuthUserService implements UserDetailsService {
 @Autowired
 private UserRepository userRepository;
 @Override
 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  if(StringUtils.isNotBlank(username)) {
            // 从数据库中获取用户
   User user = userRepository.findByUsername(username);
   if(user != null) {
                // 创建用户、加载角色
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
   return new org.springframework.security.core.userdetails.User(
    username, user.getPassword(), authorities);
   }
   else {
    throw new UsernameNotFoundException("用户名不存在");
   }
  }
  return null;
 }
}
  1. 编写Controller
@Controller
@RequestMapping("/user")
public class UserController {
 @Autowired
 private UserService userService;
 @RequestMapping("/findUserList")
 public String findUserList(Model model) {
  List<User> list = userService.findAll();
  model.addAttribute("list", list);
  return "/index.jsp";
 }
 @RequestMapping("/add")
 public String add(User user) {
  userService.add(user);
  return "redirect:/user/findUserList";
 }
}
  1. 编写应用入口
@SpringBootApplication
public class Application {
 public static void main(String[] args) {
  SpringApplication.run(Application.class);
 }
 @Bean(name="datasource")
 @Primary
 @ConfigurationProperties(prefix="c3p0")
 public ComboPooledDataSource c3p0DataSource() throws PropertyVetoException {
  ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
  return comboPooledDataSource;
 }
}
  1. 编写配置文件
server.port=10086
 server.context-path=/
 freemarker.output_path=G:/workspace/free_test/t51/src/main/webapp/
 c3p0.driverClass=com.mysql.jdbc.Driver
 c3p0.jdbcUrl=jdbc:mysql:///springboot
 c3p0.user=root
 c3p0.password=000000
  1. 编写页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>JSP测试</title>
 </head>
 <body>
 <table border="1">
 <form action="<%=request.getContextPath()%>/user/add" method="post">
 <tr>
 <td>用户名:<input type="text" name="username"/></td>
 <td>密码:<input type="text" name="password"/></td>
 <td><input type="submit" value="新增"/></td>
 </tr>
 </form>
 </table>
 <table border=1>
 <tr>
 <th>ID</th>
 <th>用户名</th>
 <th>密码</th>
 </tr>
 <c:forEach items="${list}" var="user">
 <tr>
 <td>${user.id}</td>
 <td>${user.username}</td>
 <td>${user.password}</td>
 </tr>
 </c:forEach>
 </table>
 </body>
 </html>
  1. 访问http://localhost:10086/user/findUserList,弹出登录对话框,输入数据库中任意的用户名和密码登录即可。

构建基于Dubbox分布式架构应用程序

启动ZooKeeper

编写服务提供者

  1. 导入依赖
<parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>1.5.14.RELEASE</version>
 </parent>
 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-jpa</artifactId>
 </dependency>
 <dependency>
 <groupId>com.cjoop</groupId>
 <artifactId>spring-boot-starter-dubbox</artifactId>
 <version>0.0.1</version>
 </dependency>
 <dependency>
 <groupId>org.apache.zookeeper</groupId>
 <artifactId>zookeeper</artifactId>
 <version>3.4.7</version>
 </dependency>
 <dependency>
 <groupId>com.github.sgroschupf</groupId>
 <artifactId>zkclient</artifactId>
 <version>0.1</version>
 </dependency>
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.6</version>
 </dependency>
 <dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>jstl</artifactId>
 </dependency>
 <dependency>
 <groupId>org.apache.tomcat.embed</groupId>
 <artifactId>tomcat-embed-jasper</artifactId>
 </dependency>
 <dependency>
 <groupId>c3p0</groupId>
 <artifactId>c3p0</artifactId>
 <version>0.9.1</version>
 </dependency>
 <dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-lang3</artifactId>
 <version>3.4</version>
 </dependency>
 </dependencies>
  1. 这里导入了Dubbox的起步依赖,这样配置起来很方便。
  2. 导入实体类,注意因为要在网络上传输,所以要实现Serializable接口
@Entity
@Table(name="t_user")
public class User implements Serializable{
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Integer id;
 private String username;
 private String password;
 public User() {
 }
 public User(Integer id, String username, String password) {
  this.id = id;
  this.username = username;
  this.password = password;
 }
 public User(String username, String password) {
  this(null, username, password);
 }
 public Integer getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 @Override
 public String toString() {
  return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
 }
}
  1. 编写DAO
public interface UserRepository extends JpaRepository<User, Integer>{
 User findByUsername(String username);
}
  1. 编写Service(注意:请使用Dubbox中的@Service,否则服务将不会被发布)
public interface UserService {
 /**
  * 根据ID获取用户
  * @param i
  * @return
  */
 User get(int id);
 /**
  * 查询所有用户
  * @return
  */
 List<User> findAll();
 /**
  * 新增用户
  * @param user
  */
 void add(User user);
}
@Service
@Transactional
public class UserServiceImpl implements UserService{
 @Autowired
 private UserRepository userRepository;
 @Override
 public User get(int id) {
  return userRepository.findOne(id);
 }
 @Override
 public List<User> findAll() {
  return userRepository.findAll();
 }
 @Override
 public void add(User user) {
  userRepository.save(user);
 }
}
  1. 编写入口
@SpringBootApplication
public class Application {
 public static void main(String[] args) {
  SpringApplication.run(Application.class);
 }
 @Bean(name="datasource")
 @Primary
 @ConfigurationProperties(prefix="c3p0")
 public ComboPooledDataSource c3p0DataSource() throws PropertyVetoException {
  ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
  return comboPooledDataSource;
 }
}
  1. 编写配置文件
server.port=10086
server.context-path=/
#配置Dubbo包扫描,自动将带有Service注解的类发布为Dubbox服务
dubbo.annotation.package=com.itheima.springboot.service
dubbo.application.name=com.itheima.user.service
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///springboot
c3p0.user=root
c3p0.password=000000
  1. 启动应用,如果服务发布成功,可以在Dubbo Admin上看到已经发布的服务

编写服务消费者

  1. 导入依赖
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.14.RELEASE</version>
 </parent>
 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
  </dependency>
  <dependency>
   <groupId>org.apache.tomcat.embed</groupId>
   <artifactId>tomcat-embed-jasper</artifactId>
  </dependency>
  <dependency>
   <groupId>com.cjoop</groupId>
   <artifactId>spring-boot-starter-dubbox</artifactId>
   <version>0.0.1</version>
  </dependency>
  <dependency>
   <groupId>org.apache.zookeeper</groupId>
   <artifactId>zookeeper</artifactId>
   <version>3.4.7</version>
  </dependency>
  <dependency>
   <groupId>com.github.sgroschupf</groupId>
   <artifactId>zkclient</artifactId>
   <version>0.1</version>
  </dependency>
  <dependency>
   <groupId>org.javassist</groupId>
   <artifactId>javassist</artifactId>
  </dependency>
 </dependencies>
  1. 引入实体类
public class User {
 private Integer id;
 private String username;
 private String password;
 public User() {
 }
 public User(Integer id, String username, String password) {
 this.id = id;
 this.username = username;
 this.password = password;
 }
 public User(String username, String password) {
 this(null, username, password);
 }
 public Integer getId() {
 return id;
 }
 public void setId(Integer id) {
 this.id = id;
 }
 public String getUsername() {
 return username;
 }
 public void setUsername(String username) {
 this.username = username;
 }
 public String getPassword() {
 return password;
 }
 public void setPassword(String password) {
 this.password = password;
 }
 @Override
 public String toString() {
 return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
 }
 }
1. 引入Service接口
public interface UserService {
 /**
  * 根据ID获取用户
  * @param i
  * @return
  */
 User get(int id);
 /**
  * 查询所有用户
  * @return
  */
 List<User> findAll();
 /**
  * 新增用户
  * @param user
  */
 void add(User user);
}
1. 编写Controller
 @Controller
 @RequestMapping("/user")
 public class UserController {
 @Reference
 private UserService userService;
 @RequestMapping("/findUserList")
 public String findUserList(Model model) {
 List<User> list = userService.findAll();
 model.addAttribute("list", list);
 return "/index.jsp";
 }
 @RequestMapping("/add")
 public String add(User user) {
 userService.add(user);
 return "redirect:/user/findUserList";
 }
 }
  1. 编写入口
@SpringBootApplication
 public class Application {
 public static void main(String[] args) {
 SpringApplication.run(Application.class);
 }
 }
  1. 编写配置文件
server.port=10087
 server.context-path=/
 dubbo.annotation.package=com.itheima.springboot.controller
 dubbo.application.name=com.itheima.user.web
  1. 编写页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>JSP测试</title>
 </head>
 <body>
 <table border="1">
 <form action="<%=request.getContextPath()%>/user/add" method="post">
 <tr>
 <td>用户名:<input type="text" name="username"/></td>
 <td>密码:<input type="text" name="password"/></td>
 <td><input type="submit" value="新增"/></td>
 </tr>
 </form>
 </table>
 <table border=1>
 <tr>
 <th>ID</th>
 <th>用户名</th>
 <th>密码</th>
 </tr>
 <c:forEach items="${list}" var="user">
 <tr>
 <td>${user.id}</td>
 <td>${user.username}</td>
 <td>${user.password}</td>
 </tr>
 </c:forEach>
 </table>
 </body>
 </html>
  1. 访问http://localhost:10087/user/findUserList

Spring Boot自动配置原理结构分析

通过实践,可以隐约感觉到。Spring Boot相当于基于Maven和Spring做了一个开发平台,使用这个平台可以减少配置、快速开发。那么Spring Boot到底是如何做到的呢?

回想,我们开发的第一个案例。我们只是往pom.xml中进行简单配置,就可以开始进行Spring开发了。

然后,更新项目可以看到,在Maven的依赖中,导入了很多的JAR包。

这两段配置怎么这么神奇,它到底做了什么?先来看看这个spring-boot-starter-parent的pom文件。

先是定义了很多的常量

里面还定义了一些依赖的版本锁定、插件的版本锁定。但没有导入具体的JAR包。

这个spring-boot-starter-parent从spring-boot-dependencies中继承,这个pom文件中定义了大量的版本号、以及版本锁定。

这些版本应该都是做过兼容性测试的,一般不要去修改否则出现不兼容问题是比较麻烦的。

再看看spring-boot-starter这个依赖

这个starter起步依赖中包含了导入了spring-boot依赖,spring-boot依赖导入了spring framework的核心依赖。

spring-boot-autoconfigure依赖,spring-boot-starter-logging会自动日志相关的依赖。

这个spring-boot-autoconfigure里面包含了很多玄机。

我猜想,Spring Boot是通过自动配置,来帮助我们自动创建了很多bean在IOC容器中。

所以接下来要回答两个问题:

1、Spring创建了哪些Bean?

2、因为我们之前都是通过编写很多的配置文件来创建和配置bean的,那Spring是如何读取配置来创建这些bean的?

接着猜:

以前的配置信息肯定还有,Spring不应该是把之前假设的平台全部推倒,而是把常用的配置整合起来了,就省去了我们自己来手动配置的过程。那么,我猜:每一个Starter都会有其对应的配置信息。我们来找一找spring-boot-starter的配置信息。

这个autoconfigure里面有大量的包,而且命名方式是以技术组件来命名的

要知道Spring Boot创建了哪些bean,直接去看自动配置包中,以Configuration结尾的类就可以了。要想看看具体application.properties中应该配置哪些属性,直接去看以properties文件结尾的类就可以了。

来看一段自动配置的源代码,下面这段代码是从JmsAutoConfiguration中截取出来的。

@Configuration
@ConditionalOnClass({ Message.class, JmsTemplate.class })
@ConditionalOnBean(ConnectionFactory.class)
@EnableConfigurationProperties(JmsProperties.class)
@Import(JmsAnnotationDrivenConfiguration.class)
public class JmsAutoConfiguration {
 @Configuration
 protected static class JmsTemplateConfiguration {
  private final JmsProperties properties;
  private final ObjectProvider<DestinationResolver> destinationResolver;
  private final ObjectProvider<MessageConverter> messageConverter;
  public JmsTemplateConfiguration(JmsProperties properties,
    ObjectProvider<DestinationResolver> destinationResolver,
    ObjectProvider<MessageConverter> messageConverter) {
   this.properties = properties;
   this.destinationResolver = destinationResolver;
   this.messageConverter = messageConverter;
  }
  @Bean
  @ConditionalOnMissingBean
  @ConditionalOnSingleCandidate(ConnectionFactory.class)
  public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
   JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
   jmsTemplate.setPubSubDomain(this.properties.isPubSubDomain());
   DestinationResolver destinationResolver = this.destinationResolver
     .getIfUnique();
   if (destinationResolver != null) {
    jmsTemplate.setDestinationResolver(destinationResolver);
   }
   MessageConverter messageConverter = this.messageConverter.getIfUnique();
   if (messageConverter != null) {
    jmsTemplate.setMessageConverter(messageConverter);
   }
   JmsProperties.Template template = this.properties.getTemplate();
   if (template.getDefaultDestination() != null) {
    jmsTemplate.setDefaultDestinationName(template.getDefaultDestination());
   }
   if (template.getDeliveryDelay() != null) {
    jmsTemplate.setDeliveryDelay(template.getDeliveryDelay());
   }
   jmsTemplate.setExplicitQosEnabled(template.determineQosEnabled());
   if (template.getDeliveryMode() != null) {
    jmsTemplate.setDeliveryMode(template.getDeliveryMode().getValue());
   }
   if (template.getPriority() != null) {
    jmsTemplate.setPriority(template.getPriority());
   }
   if (template.getTimeToLive() != null) {
    jmsTemplate.setTimeToLive(template.getTimeToLive());
   }
   if (template.getReceiveTimeout() != null) {
    jmsTemplate.setReceiveTimeout(template.getReceiveTimeout());
   }
   return jmsTemplate;
  }
 }

这里面有几个很重要的注解

  1. @ConditionalOnClass
    这个注解表示,如果检测到当前的JVM中加载了Message.class, JmsTemplate.class,就加载该Java Config配置。
  2. @ConditionalOnMissingBean
    这个注解表示,如果IOC容器中没有检测到这个类型的Bean,就创建一个。如果检测到了,那么就不创建了。所以,如果我们自己配置了JmsTemplate这个Bean,那这个自动配置就失效了
  3. @ConditionalOnBean
    这个注解表示,如果IOC容器中有指定类型的Bean,才加载Java Config配置。例如:这里如果检测到容器中有ConnectionFactory类型的Bean,才会创建JmsTemplate。
  4. @EnableConfigurationProperties
    这个注解表示将以Properties结尾的配置类,加载到当前的自动配置类中。一般的Starter中的Properties类都可以从application.properties中的指定前缀的属性加载。从而让我们可以轻松的自定义里面的配置。
  5. @Import
    导入其他的Java Config配置,相当于之前XML配置中的import。

结尾

大家应该有一个直接的体会,Spring Boot真的让我们的工作更加轻松了。以前要写的很多配置、导很多的依赖,现在只需要短短几行代码就可以解决问题。而且,不再需要我们去考虑版本之间的兼容问题了。相信,很快大家编写的应用都会切换到Spring Boot。它将让我们将更多的精力放在编写、设计结构、算法上。

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
14天前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
95 26
|
2月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
180 73
|
27天前
|
Dart 前端开发 JavaScript
springboot自动配置原理
Spring Boot 自动配置原理:通过 `@EnableAutoConfiguration` 开启自动配置,扫描 `META-INF/spring.factories` 下的配置类,省去手动编写配置文件。使用 `@ConditionalXXX` 注解判断配置类是否生效,导入对应的 starter 后自动配置生效。通过 `@EnableConfigurationProperties` 加载配置属性,默认值与配置文件中的值结合使用。总结来说,Spring Boot 通过这些机制简化了开发配置流程,提升了开发效率。
59 17
springboot自动配置原理
|
21天前
|
监控 Java 应用服务中间件
SpringBoot是如何简化Spring开发的,以及SpringBoot的特性以及源码分析
Spring Boot 通过简化配置、自动配置和嵌入式服务器等特性,大大简化了 Spring 应用的开发过程。它通过提供一系列 `starter` 依赖和开箱即用的默认配置,使开发者能够更专注于业务逻辑而非繁琐的配置。Spring Boot 的自动配置机制和强大的 Actuator 功能进一步提升了开发效率和应用的可维护性。通过对其源码的分析,可以更深入地理解其内部工作机制,从而更好地利用其特性进行开发。
42 6
|
27天前
|
监控 Java 数据库连接
Spring c3p0配置详解
在Spring项目中配置C3P0数据源,可以显著提高数据库连接的效率和应用程序的性能。通过合理的配置和优化,可以充分发挥C3P0的优势,满足不同应用场景的需求。希望本文的详解和示例代码能为开发者提供清晰的指导,帮助实现高效的数据库连接管理。
43 10
|
28天前
|
Java 应用服务中间件 API
【潜意识Java】javaee中的SpringBoot在Java 开发中的应用与详细分析
本文介绍了 Spring Boot 的核心概念和使用场景,并通过一个实战项目演示了如何构建一个简单的 RESTful API。
38 5
|
1月前
|
人工智能 Java API
阿里云工程师跟通义灵码结伴编程, 用Spring AI Alibaba来开发 AI 答疑助手
本次分享的主题是阿里云工程师跟通义灵码结伴编程, 用Spring AI Alibaba来开发 AI 答疑助手,由阿里云两位工程师分享。
阿里云工程师跟通义灵码结伴编程, 用Spring AI Alibaba来开发 AI 答疑助手
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
2月前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
27天前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
201 17
Spring Boot 两种部署到服务器的方式