本文己参与[新人创作礼]活动,一起开启掘金创作之路
读者应具备:
- Spring SpringMVC服务器端开发基础
- Maven基础
本篇主要介绍Spring Boot在企业开发中常见场景的使用、以及Spring Boot的基本原理结构。
以下为本篇设计的技术应用场景:
- 构建Spring Java程序
- 构建JUnit测试用例
- 构建Spring JDBC Template应用程序操作数据库
- 构建Servlet、JSP程序
- 构建SSH应用(Spring、Spring MVC、Hibernate)
- 构建SSM应用(Spring、Spring MVC、MyBatis)
- 构建SSJPA应用(Spring、Spring MVC、Spring Data JPA)
- 构建FreeMarker应用程序
- 构建基于Redis缓存应用程序
- 构建基于ActiveMQ消息队列应用程序
- 构建基于Spring Security访问控制应用程序
- 构建基于Dubbox分布式架构应用程序
介绍完应用场景后,再来了解下Spring Boot的基本原理结构。
引言
如果读者写过稍微复杂一些的Spring程序,那么你一定曾经编写过那铺天盖地的各类配置文件。例如:
- applicationContext-dao.xml(针对DAO的配置——数据源、持久层框架与spring整合bean)
- applicationContext-tx.xml(针对事务的配置)
- applicationContext-amq.xml(针对ActiveMQ的配置)
- applicationContext-webservice.xml(针对WebService发布的配置)
- applicationContext-redis.xml(针对操作Redis的配置)
- applicationContext-security.xml(针对Spring Security的配置)
- applicationContext-freemarker.xml(针对FreeMarker模板引擎的相关配置)
- springmvc.xml(Spring MVC的配置)
- ...
除此之外,我们还要维护大量的依赖。最坑的是,不同的版本框架之间可能会存在不兼容的问题。或许,我们早已习惯了这些配置,但我们今天要学习是以一种崭新的开发方式来开发Spring应用程序。它将掀起一场推翻Spring过去统治的轻量级JavaEE企业应用世界的技术革命。
而这一场技术革命原动力就是我今天要呈现给大家的——Spring Boot。
本篇目标
- 介绍如何使用Spring Boot开发基于各类技术框架的应用程序
- 了解Spring Boot自动配置原理、结构
目录
Spring Boot常见企业开发场景应用、自动配置原理结构分析引言本篇目标目录环境准备Spring Java配置Spring Boot基本编程模型导入依赖导入配置编码常见企业开发场景应用构建Spring Java应用程序构建Junit测试用例构建Spring JDBC Template应用程序操作数据库构建Servlet、JSP程序构建SSH应用程序(Spring、Spring MVC、Hibernate)构建SSM应用(Spring、Spring MVC、MyBatis)构建SSJPA应用(Spring、Spring MVC、Spring Data JPA)构建FreeMarker应用程序构建基于Redis缓存应用程序构建基于ActiveMQ消息队列应用程序构建基于Dubbox分布式架构应用程序启动ZooKeeper编写服务提供者编写服务消费者Spring Boot自动配置原理结构分析结尾
环境准备
编译环境:1.7+
构建工具:Maven
数据库:Mysql 5.x
开发环境:推荐使用IDEA或者STS
- 在mysql中创建一个名字为springboot的数据库
- 使用如下脚本创建表结构
create table `t_user` (
`id` int (11),
`username` varchar (765),
`password` varchar (300)
);
insert into `t_user` (`id`, `username`, `password`) values('2','zhangsan','000');
insert into `t_user` (`id`, `username`, `password`) values('3','lisi','000');
insert into `t_user` (`id`, `username`, `password`) values('4','wangwu','000');
insert into `t_user` (`id`, `username`, `password`) values('5','zhaoliu','000');
insert into `t_user` (`id`, `username`, `password`) values('6','张北','110');
insert into `t_user` (`id`, `username`, `password`) values('7','江南','000000');
insert into `t_user` (`id`, `username`, `password`) values('8','江北','123123');
Spring Java配置
SPring Java配置是Spring 3.0所推荐的配置方式。因为,XML的可读性确实不怎么样,我们一边要编写Java代码,一边要编写XML配置文件。所以,从Spring 3.0开始,推荐使用Java配置+注解方式来编写Spring程序。
接下来,我给大家演示一个比较简单的案例——从数据库中更新一条用户数据、查询一条用户数据。为了简单起见,使用Spring JDBC Template来操作数据库。
- 首先创建一个Maven工程,往pom.xml中导入Spring、MySql相关依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
- 创建Java实体类,
/**
* 用户表
*/
public class User {
private Integer id;
private String username;// 用户名
private String password;// 密码
public User() {
}
public User(int id, String username, String password) {
this.id = id;
this.username = username;
this.password = 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 + "]";
}
}
- 写到这,如果大家比较熟悉Spring开发的话,肯定是要开始编写spring配置文件了,并且在配置文件中,创建需要用于操作数据库的Bean。但这儿,我们要使用Java配置来创建Bean。以前在XML文件中创建Bean的配置,现在都写在Java代码中了。以下为Java配置:
/**
* @Configuration注解表示这是一个配置类
* @author FengZhou
*
*/
@Configuration
public class Conf {
/**
* 创建一个C3P0数据源
* @return
* @throws PropertyVetoException
*/
@Bean
public ComboPooledDataSource c3p0DataSource() throws PropertyVetoException {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setDriverClass("com.mysql.jdbc.Driver");
comboPooledDataSource.setJdbcUrl("jdbc:mysql:///springboot");
comboPooledDataSource.setUser("root");
comboPooledDataSource.setPassword("000000");
return comboPooledDataSource;
}
/**
* 创建一个用于操作数据库的JdbcTemplate
* @return
* @throws PropertyVetoException
*/
@Bean
public JdbcTemplate jdbcTempalte() throws PropertyVetoException {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(c3p0DataSource());
return jdbcTemplate;
}
}
@Configuration
这个注解标识,当前修饰的类就是一个配置类。你可以把它认为被@Configuration修饰的类就是一个配置文件。
@Bean
这个注解表示Spring会自动执行被它修饰的方法,并且将此方法的返回对象放入到Spring IOC容器中。
上述代码创建了两个Bean,分别是C3P0的数据源和用于操作数据的JdbcTemplate。
- 编写测试用例
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=Conf.class)// 加载Java配置
public class JdbcTemplateTest01 {
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void test01() {
// 执行一条更新语句
jdbcTemplate.execute("update t_user t set t.username='zhaosi' where t.id = 1");
}
@Test
public void test02() {
// 查询一条数据
jdbcTemplate.query("select * from t_user where id = 2", BeanPropertyRowMapper.newInstance(User.class));
}
}
本次的测试用例,不再有applicationContext.xml配置文件,而是使用一个Java配置类代替了这个配置文件。
Spring Boot基本编程模型
接下来,我们要开始使用Spring Boot开发应用程序。Spring Boot的基本开发模型如下:
导入依赖
1、添加起步依赖(这个起步依赖不是具体的JAR包,而是你要开发什么样的功能,就使用什么样的起步依赖)——注意:可以把起步依赖看成一个Spring Boot封装过的特殊依赖,这个依赖也是具备有传递性特征的
2、导入其他关联依赖(数据库驱动、JSTL等)
导入配置
1、配置application.properties或者application.yml
2、编写Java自定义配置
编码
1、编写Main入口,并加载SpringBoot自动配置
2、编写业务代码
a) 获取Spring Boot自动配置生成的BEAN Template
b) 使用BEAN Template来执行业务操作
大家可以先不用了解Spring Boot开发的具体细节,只需要重点记住这几个重点:
- 导入依赖
- 导入配置
- 编写代码
这个过程其实和我们之前的Spring开发并没有太大区别。
常见企业开发场景应用
构建Spring Java应用程序
第一个应用不涉及到数据库的操作。我们的目标是使用Spring Boot来编写一个简单的Java程序。这个Java程序只是通过Spring Boot来创建一个Spring IOC容器,并从调用容器中Bean的方法。
-
导入Spring Boot依赖
还记得前面的代码吗?我们在创建Maven项目后,需要往pom.xml中导入很多的以来。而使用了Spring Boot之后呢?
<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</artifactId> </dependency> </dependencies>
yup. 你没看错,就只有这么几行。这个以
spring-boot-starter
开头的依赖称作起步依赖
。可以把它看成是Spring Boot应用程序必须要导入的依赖。它里面封装了很多的其他的依赖。这里,我们需要开发Spring应用程序,只需要导入一个spring-boot-starter
即可。 -
编写DAO接口和实现
public interface UserDao { /** * 根据ID获取用户 * @param id * @return */ User get(int id); }
为了简单,这里就先不从数据中查询数据,直接构建一些User对象来操作(User实体类之前已经给出)
@Repository public class UserDaoImpl implements UserDao{ private ArrayList<User> userList = new ArrayList<User>(); public UserDaoImpl() { // 往数组中添加一些模拟测试数据 userList.add(new User(1, "zhangsan", "000")); userList.add(new User(2, "lisi", "000")); userList.add(new User(3, "wangwu", "000")); userList.add(new User(4, "zhaoliu", "000")); } @Override public User get(int id) { for (User user : userList) { if(user.getId().equals(id)) { return user; } } return null; } }
-
编写服务接口和实现类
public interface UserService { /** * 根据ID获取用户 * @param i * @return */ User get(int id); }
@Service public class UserServiceImpl implements UserService{ @Autowired private UserDao userDao; @Override public User get(int id) { return userDao.get(id); } }
-
编写Spring Boot应用程序入口
@SpringBootApplication public class Application { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(Application.class); UserService userService = context.getBean(UserService.class); User user = userService.get(1); System.out.println(user); } }
注意:
要在main所在的Applcation类上添加
@SpringBootApplication
注解,这个注解会启动Spring Boot的自动配置。然后使用SpringApplication.run可以创建一个Spring IOC工厂,它的返回值就是我们熟知的ApplicationContext。然后,我们就可以获取IOC工厂的Bean了。
构建Junit测试用例
要构建基于Spring Boot的测试用例,还需要额外引入另一个起步依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
编写测试用例如下:
@RunWith(SpringRunner.class)
@SpringBootTest(classes=Application.class)
public class UserServiceImplTest {
@Autowired
private UserService userService;
@Test
public void testGet() {
User user = userService.get(2);
System.out.println(user);
}
}
使用@SpringBootTest替代之前的@ContextConfiguration,直接加载Spring Boot的入口类即可。
构建Spring JDBC Template应用程序操作数据库
接下来,我将使用Spring Boot来使用JDBC Template操作数据库。
导入起步依赖
<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</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
因为,这里需要使用到mysql驱动以及c3p0连接池,所以多导入了两个依赖
重新编写DAO
public interface UserDao {
/**
* 根据ID获取用户
* @param id
* @return
*/
User get(int id);
}
@Repository
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public User get(int id) {
return jdbcTemplate.queryForObject("select * from t_user t where t.id = ?",BeanPropertyRowMapper.newInstance(User.class),id);
}
}
编写Service
public interface UserService {
/**
* 根据ID获取用户
* @param i
* @return
*/
User get(int id);
}
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
@Override
public User get(int id) {
return userDao.get(id);
}
}
编写配置文件application.properties
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///springboot
c3p0.user=root
c3p0.password=000000
注意:这个配置文件中以c3p0开头的,其实是自定义的配置。一会我们需要指定这个前缀来进行加载
编写启动类
@SpringBootApplication
public class Application {
@Bean(name="datasource")
@Primary
@ConfigurationProperties(prefix="c3p0")
public ComboPooledDataSource c3p0DataSource() throws PropertyVetoException {
return new ComboPooledDataSource();
}
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class);
UserService userService = context.getBean(UserService.class);
User user = userService.get(2);
System.out.println(user);
}
}
注意@ConfigurationProperties(prefix="c3p0")
这个注解,这个注解表示,将application.properties配置文件中的以c3p0开头的配置信息注入到ComboPooledDataSource这个对象上面。而在application.properties中的配置c3p0.driverClass=com.mysql.jdbc.Driver
,相当于就是在进行属性注入。这里指的是:将com.mysql.jdbc.Driver注入到ComboPooledDataSource Bean的driverClass属性。
这种加载配置的方法,真的是不服不行。要比之前简单了很多。
构建Servlet、JSP程序
接下来我们要来使用Spring Boot来做最简单的Web开发(虽然我们开发不一定会用到,但我们还是来体验体验,毕竟这是我们的曾经啊...)
- 导入Spring Boot起步依赖
<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-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
注意:使用Spring Boot开发JSP应用程序,一定要加载下面的依赖
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
-
编写DAO
public interface UserDao { /** * 根据ID获取用户 * @param id * @return */ User get(int id); } @Repository public class UserDaoImpl implements UserDao{ @Autowired private JdbcTemplate jdbcTemplate; @Override public User get(int id) { return jdbcTemplate.queryForObject("select * from t_user t where t.id = ?",BeanPropertyRowMapper.newInstance(User.class),id); } }
-
编写Service
public interface UserService { /** * 根据ID获取用户 * @param i * @return */ User get(int id); /** * 查询所有用户 * @return */ List<User> findAll(); } @Service @Transactional public class UserServiceImpl implements UserService{ @Autowired private UserDao userDao; @Override public User get(int id) { return userDao.get(id); } }
-
编写Servlet | 这里使用的是注解方式定义Servlet,这种方式更加容易与Spring进行整合。
@WebServlet(name="UserServlet", urlPatterns="/user/findUserList") public class UserServlet extends HttpServlet{ @Autowired private UserService userService; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { List<User> users = userService.findAll(); req.setAttribute("list", users); req.getRequestDispatcher("/index.jsp").forward(req, resp); } }
urlPatterns
配置了这个Servlet被访问的URL -
编写JSP页面
<%@ 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> <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>
-
编写入口
@SpringBootApplication @ServletComponentScan public class Application { @Bean(name="datasource") @ConfigurationProperties(prefix="c3p0") public ComboPooledDataSource c3p0DataSource() throws PropertyVetoException { return new ComboPooledDataSource(); } public static void main(String[] args) { SpringApplication.run(Application.class); } }
注意:一定要在Application类上加上
@ServletComponentScan
注解,否则Servlet是不会被加载的。 -
编写配置文件
server.port=10086 server.context-path=/ c3p0.driverClass=com.mysql.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql:///springboot c3p0.user=root c3p0.password=000000
server.port
配置的是web应用访问的端口号,server.context-path=/是应用访问的根路径 -
访问http://localhost:10086/user/findUserList测试应用。如果应用执行成功应该可以看到用户数据
构建SSH应用程序(Spring、Spring MVC、Hibernate)
-
导入依赖
<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-jdbc</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>javassist</groupId> <artifactId>javassist</artifactId> <version>3.11.0.GA</version> </dependency> </dependencies>
-
使用JPA注解修饰User实体类
@Entity @Table(name="t_user") public class User { @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 + "]"; } }
-
编写DAO
public interface UserDao { User get(int id); List<User> findAll(); void add(User user); } @Repository public class UserDaoImpl extends HibernateDaoSupport implements UserDao{ // 注入SessionFactory @Autowired public void autoWiredFactory(SessionFactory sessionFactory) { super.setSessionFactory(sessionFactory); } @Override public User get(int id) { return getHibernateTemplate().get(User.class, id); } @Override public List<User> findAll() { return getHibernateTemplate().findByExample(new User()); } @Override public void add(User user) { getHibernateTemplate().save(user); } }
-
编写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 UserDao userDao; @Override public User get(int id) { return userDao.get(id); } @Override public List<User> findAll() { return userDao.findAll(); } @Override public void add(User user) { userDao.add(user); } }
-
编写Controller/Handler
@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"; } }
-
JSP页面参见Servlet/JSP案例
-
编写Spring Boot入口
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class); } @Bean @ConfigurationProperties(prefix="c3p0") public ComboPooledDataSource c3p0DataSource() throws PropertyVetoException { return new ComboPooledDataSource(); } @Bean @ConfigurationProperties(prefix="hibernate") public LocalSessionFactoryBean sessionFactory() throws PropertyVetoException { LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean(); sessionFactoryBean.setDataSource(c3p0DataSource()); return sessionFactoryBean; } @Bean public HibernateTransactionManager transactionManager() throws PropertyVetoException { HibernateTransactionManager tx = new HibernateTransactionManager(); tx.setSessionFactory(sessionFactory().getObject()); return tx; } }
注意:此处因为Hibernate没有Starter起步依赖,所以我使用了Java配置来整合Hibernate。第一个Bean是C3P0数据源,第二个Bean是SessionFactory,第三个Bean是事务管理器。
-
编写配置文件
server.port=10086 server.context-path=/ c3p0.driverClass=com.mysql.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql:///springboot c3p0.user=root c3p0.password=000000 hibernate.packagesToScan=com.itheima.springboot.entity
构建SSM应用(Spring、Spring MVC、MyBatis)
为了简单起见,这里使用逆向工程生成实体类、Mapper接口、Mapper映射文件。因为查询实体、映射文件的代码比较长,这里就不把代码贴上来了,大家自己使用逆向工程生成下就OK。
-
导入依赖
<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-jdbc</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </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> </dependencies>
-
Service代码
public interface UserService { /** * 根据ID获取用户 * @param i * @return */ TUser get(int id); /** * 查询所有用户 * @return */ List<TUser> findAll(); /** * 新增用户 * @param user */ void add(TUser user); } @Service @Transactional public class UserServiceImpl implements UserService{ @Autowired private TUserMapper userMapper; @Override public TUser get(int id) { return userMapper.selectByPrimaryKey(id); } @Override public List<TUser> findAll() { return userMapper.selectByExample(null); } @Override public void add(TUser user) { userMapper.insert(user); } }
-
Controller代码
@Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @RequestMapping("/findUserList") public String findUserList(Model model) { List<TUser> list = userService.findAll(); model.addAttribute("list", list); return "/index.jsp"; } }
-
Spring Boot入口应用
@SpringBootApplication @MapperScan(basePackages="com.itheima.springboot.mapper") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class); } }
注意:Spring Boot整合MyBatis需要在Application类上添加@MapperScan,否则不会为Mapper创建代理对象,执行程序失败。
-
配置文件
server.port=10086 server.context-path=/ #数据库配置 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql:///springboot spring.datasource.username=root spring.datasource.password=000000
这里使用默认的数据源,如果想要使用其他的数据源参照之前的配置即可
构建SSJPA应用(Spring、Spring MVC、Spring Data JPA)
-
导入Maven依赖
<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>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1</version> </dependency> </dependencies>
注意:导入了
spring-boot-starter-data-jpa
依赖 -
编写Java实体类,参考SSH整合JPA实体类
-
编写DAO
public interface UserRepository extends JpaRepository<User, Integer>{ }
(这个代码是真的喜欢)
-
编写Service
public interface UserService { /** * 根据ID获取用户 * @param i * @return */ User get(int id); /** * 查询所有用户 * @return */ List<User> findAll(); /** * 新增用户 * @param user */ void add(User user); }
-
编写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"; } }
-
编写入口
@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 { return new ComboPooledDataSource(); } }
-
配置文件
server.port=10086 server.context-path=/ c3p0.driverClass=com.mysql.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql:///springboot c3p0.user=root c3p0.password=000000
构建FreeMarker应用程序
-
导入依赖
<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>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> </dependencies>
多导入了
spring-boot-starter-freemarker
起步依赖 -
编写DAO
public interface UserRepository extends JpaRepository<User, Integer>{ }
-
编写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); } }
-
编写Controller
@Controller @RequestMapping("/user") public class UserController { // 静态页面输出到的目录 @Value("${freemarker.output_path}") private String OUTPUT_PATH; @Autowired private UserService userService; // 获取FreeMarker配置类 @Autowired private Configuration configuration; @RequestMapping("/genPage") @ResponseBody public Map genPage() throws Exception { List<User> list = userService.findAll(); Map model = new HashMap<String, Object>(); model.put("list", list); Template template = configuration.getTemplate("user_list.ftl"); template.process(model, new FileWriter(OUTPUT_PATH + "userList.html")); Map result = new HashMap<String, Object>(); result.put("success", true); result.put("message", "生成页面成功!"); return result; } }
-
编写入口
@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 { return new ComboPooledDataSource(); } }
-
编写配置文件
server.port=10086 server.context-path=/ # FreeMarker静态页面输出目录 freemarker.output_path=G:/workspace/free_test/t49/src/main/webapp/ c3p0.driverClass=com.mysql.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql:///springboot c3p0.user=root c3p0.password=000000
-
编写FreeMarker模板,此模板默认放在classpath下的template/user_list.ftl中
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP测试</title> </head> <body> <table border=1> <tr> <th>ID</th> <th>用户名</th> <th>密码</th> </tr> <#list list as user> <tr> <td>${user.id}</td> <td>${user.username}</td> <td>${user.password}</td> </tr> </#list> </table> </body> </html>
构建基于Redis缓存应用程序
-
导入依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.14.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> </properties> <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>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> </dependencies>
要开发导入Redis起步依赖
spring-boot-starter-data-redis
-
编写DAO
public interface UserRepository extends JpaRepository<User, Integer>{ }
-
编写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; @Autowired private RedisTemplate redisTemplate; @Override public User get(int id) { return userRepository.findOne(id); } @Override public List<User> findAll() { Long size = redisTemplate.boundListOps("userList").size(); List<User> userList = redisTemplate.boundListOps("userList").range(0, size); if(userList == null || size == 0) { System.out.println("从数据库中获取数据..."); userList = userRepository.findAll(); System.out.println("将数据放入缓存..."); redisTemplate.boundListOps("userList").rightPushAll(userList.toArray(new User[0])); return userList; } else { System.out.println("从缓存中获取数据..."); return userList; } } @Override public void add(User user) { userRepository.save(user); } }
-
编写Controller
@Controller @RequestMapping("/user") public class UserController { @Value("${freemarker.output_path}") private String OUTPUT_PATH; @Autowired private UserService userService; @RequestMapping("/findUserList") public String findUserList(Model model) { List<User> list = userService.findAll(); model.addAttribute("list", list); return "/index.jsp"; } }
-
编写Spring Boot入口
@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; } }
-
编写配置文件
server.port=10086 server.context-path=/ c3p0.driverClass=com.mysql.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql:///springboot c3p0.user=root c3p0.password=000000
-
启动Redis
构建基于ActiveMQ消息队列应用程序
-
导入依赖
<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>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.28</version> </dependency> </dependencies>
这里导入了ActiveMQ的起步依赖
-
编写DAO
public interface UserRepository extends JpaRepository<User, Integer>{ }
-
编写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); } }
-
编写Controller
@Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @Autowired private JmsTemplate jmsTemplate; @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); final List<User> 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"; } }
在添加一个用户,往AMQ中发送一条queue消息
-
编写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<User> userList = JSON.parseArray(userListStr, User.class); Map map = new HashMap<String, Object>(); map.put("list", userList); template.process(map, new FileWriter(OUTPUT_PATH + "user_list.html")); } }
监听AMQ中queue_page队列的消息,如果接收到消息,使用FreeMarker重新生成一个HTML页面在服务器端
-
编写入口
@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; } }
-
编写配置文件
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
构建基于Spring Security访问控制应用程序
-
导入依赖
<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>
导入了Spring Security的起步依赖
spring-boot-starter-security
-
编写DAO
public interface UserRepository extends JpaRepository<User, Integer>{ // 根据用户名查询用户 User findByUsername(String username); }
-
编写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); } }
-
编写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; } }
-
编写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"; } }
-
编写应用入口
@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; } }
-
编写配置文件
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
-
编写页面
<%@ 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>
-
访问http://localhost:10086/user/findUserList,弹出登录对话框,输入数据库中任意的用户名和密码登录即可。
-
构建基于Dubbox分布式架构应用程序
启动ZooKeeper
编写服务提供者
-
导入依赖
<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>
这里导入了Dubbox的起步依赖,这样配置起来很方便。
-
导入实体类,注意因为要在网络上传输,所以要实现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 + "]"; } }
-
编写DAO
public interface UserRepository extends JpaRepository<User, Integer>{ User findByUsername(String username); }
-
编写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); } }
-
编写入口
@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; } }
-
编写配置文件
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
-
启动应用,如果服务发布成功,可以在Dubbo Admin上看到已经发布的服务
编写服务消费者
-
导入依赖
<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>
-
引入实体类
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 + "]"; } }
-
引入Service接口
public interface UserService { /** * 根据ID获取用户 * @param i * @return */ User get(int id); /** * 查询所有用户 * @return */ List<User> findAll(); /** * 新增用户 * @param user */ void add(User user); }
-
编写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"; } }
-
编写入口
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class); } }
-
编写配置文件
server.port=10087 server.context-path=/ dubbo.annotation.package=com.itheima.springboot.controller dubbo.application.name=com.itheima.user.web
-
编写页面
<%@ 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>
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;
}
}
这里面有几个很重要的注解
-
@ConditionalOnClass
这个注解表示,如果检测到当前的JVM中加载了Message.class, JmsTemplate.class,就加载该Java Config配置。
-
@ConditionalOnMissingBean
这个注解表示,如果IOC容器中没有检测到这个类型的Bean,就创建一个。如果检测到了,那么就不创建了。所以,如果我们自己配置了JmsTemplate这个Bean,那这个自动配置就失效了
-
@ConditionalOnBean
这个注解表示,如果IOC容器中有指定类型的Bean,才加载Java Config配置。例如:这里如果检测到容器中有ConnectionFactory类型的Bean,才会创建JmsTemplate。
-
@EnableConfigurationProperties
这个注解表示将以Properties结尾的配置类,加载到当前的自动配置类中。一般的Starter中的Properties类都可以从application.properties中的指定前缀的属性加载。从而让我们可以轻松的自定义里面的配置。
-
@Import
导入其他的Java Config配置,相当于之前XML配置中的import。
结尾
大家应该有一个直接的体会,Spring Boot真的让我们的工作更加轻松了。以前要写的很多配置、导很多的依赖,现在只需要短短几行代码就可以解决问题。而且,不再需要我们去考虑版本之间的兼容问题了。相信,很快大家编写的应用都会切换到Spring Boot。它将让我们将更多的精力放在编写、设计结构、算法上。