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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 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实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
1月前
|
安全 Java API
深入解析 Spring Security 配置中的 CSRF 启用与 requestMatchers 报错问题
本文深入解析了Spring Security配置中CSRF启用与`requestMatchers`报错的常见问题。针对CSRF,指出默认已启用,无需调用`enable()`,只需移除`disable()`即可恢复。对于`requestMatchers`多路径匹配报错,分析了Spring Security 6.x中方法签名的变化,并提供了三种解决方案:分次调用、自定义匹配器及降级使用`antMatchers()`。最后提醒开发者关注版本兼容性,确保升级平稳过渡。
116 2
|
2月前
|
缓存 Java API
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
本文介绍了在Spring Boot中配置Swagger2的方法。通过创建一个配置类,添加`@Configuration`和`@EnableSwagger2`注解,使用Docket对象定义API文档的详细信息,包括标题、描述、版本和包路径等。配置完成后,访问`localhost:8080/swagger-ui.html`即可查看接口文档。文中还提示了可能因浏览器缓存导致的问题及解决方法。
90 0
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的配置
|
2月前
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
134 0
|
1月前
|
存储 人工智能 自然语言处理
RAG 调优指南:Spring AI Alibaba 模块化 RAG 原理与使用
通过遵循以上最佳实践,可以构建一个高效、可靠的 RAG 系统,为用户提供准确和专业的回答。这些实践涵盖了从文档处理到系统配置的各个方面,能够帮助开发者构建更好的 RAG 应用。
896 113
|
1月前
|
SQL 前端开发 Java
深入分析 Spring Boot 项目开发中的常见问题与解决方案
本文深入分析了Spring Boot项目开发中的常见问题与解决方案,涵盖视图路径冲突(Circular View Path)、ECharts图表数据异常及SQL唯一约束冲突等典型场景。通过实际案例剖析问题成因,并提供具体解决方法,如优化视图解析器配置、改进数据查询逻辑以及合理使用外键约束。同时复习了Spring MVC视图解析原理与数据库完整性知识,强调细节处理和数据验证的重要性,为开发者提供实用参考。
75 0
|
1月前
|
安全 前端开发 Java
Spring Boot 项目中触发 Circular View Path 错误的原理与解决方案
在Spring Boot开发中,**Circular View Path**错误常因视图解析与Controller路径重名引发。当视图名称(如`login`)与请求路径相同,Spring MVC无法区分,导致无限循环调用。解决方法包括:1) 明确指定视图路径,避免重名;2) 将视图文件移至子目录;3) 确保Spring Security配置与Controller路径一致。通过合理设定视图和路径,可有效避免该问题,确保系统稳定运行。
88 0
|
2月前
|
Java 数据库连接 数据库
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——MyBatis 介绍和配置
本文介绍了Spring Boot集成MyBatis的方法,重点讲解基于注解的方式。首先简述MyBatis作为持久层框架的特点,接着说明集成时的依赖导入,包括`mybatis-spring-boot-starter`和MySQL连接器。随后详细展示了`properties.yml`配置文件的内容,涵盖数据库连接、驼峰命名规范及Mapper文件路径等关键设置,帮助开发者快速上手Spring Boot与MyBatis的整合开发。
137 0
|
2月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot中的全局异常处理——定义返回的统一 json 结构
本课主要讲解Spring Boot中的全局异常处理方法。在项目开发中,各层操作难免会遇到各种异常,若逐一处理将导致代码耦合度高、维护困难。因此,需将异常处理从业务逻辑中分离,实现统一管理与友好反馈。本文通过定义一个简化的JsonResult类(含状态码code和消息msg),结合全局异常拦截器,展示如何封装并返回标准化的JSON响应,从而提升代码质量和用户体验。
60 0
|
2月前
|
缓存 Java 应用服务中间件
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——依赖导入和Thymeleaf相关配置
在Spring Boot中使用Thymeleaf模板,需引入依赖`spring-boot-starter-thymeleaf`,并在HTML页面标签中声明`xmlns:th=&quot;http://www.thymeleaf.org&quot;`。此外,Thymeleaf默认开启页面缓存,开发时建议关闭缓存以实时查看更新效果,配置方式为`spring.thymeleaf.cache: false`。这可避免因缓存导致页面未及时刷新的问题。
62 0
|
12天前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。