目录
spring boot简单介绍
学习主流框架最快速有效的方法,阅读官方文档
我们打开官方文档 spring boot
我们来解释下我们上来看见的介绍
我们从官方介绍知道,springboot项目完全不需要xml配置,想当初我们写SSM框架的时候,我们一个项目至少需要3个XML配置文件,但是我们知道SSM项目在项目启动时,会自动加载web.xml
文件,从而加载各种配置文件,使用tomcat默认的servlet从而运行程序,但是spring boot连web.xml 都没有如何启动的呢,其实springboot是通过main方法运行的,当然不可能是一个单独的main方法,最主要的是main方法中的一行代码SpringApplication.run(Application.class, args);
,下面我们通过从零到springboot项目的搭建。
搭建一个简单的springboot应用程序
我用的是IDEA,那个IDE无所谓,能用就行。
一、搭建一个简单的web项目
首先,我们搭建我们项目的开发环境
首先,我们要配置环境,也就是jar包环境,有官方文档我们可知
我们要在pom文件中配置一个<parent></parent>
如下
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
我们发现,官方文档中注释很详细,也就是说,我们在这配置的<parent></parent>
,我们在配置下面的spring boot时,我们可以不写version,因为我们默认继承<parent></parent>
的版本
<!--每个启动器背后都是一堆的依赖,这些依赖不会出现冲突问题,因为spring官方已整理好了这些依赖-->
<!--springboot web项目的启动器-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
现在我们就可以写一个简单的web程序了
我们新建一个controller,HelloController,因为我们从浏览器访问web application 一般都是访问controller层,所以代码如下:
//RestController,该注解相当于@ResponseBody和@Controller的结合,配置该注解说明我们这个Controller
//中所有的方法都是返回json数据
@RestController
@RequestMapping("hello")
public class HelloController {
//该注解相当于 @RequestMapping(value = "show",method = RequestMethod.GET)
@GetMapping("show")
public String test(){
return "hello world 1 !";
}
}
但是我们想要运行程序如何运行,我们需要启动程序,与以前的spring框架不同的是,springboot不需要通过web.xml配置,而是通过main函数来执行程序,但是一个简单的main函数并不能将我们的项目启动起来,我们需要将他给配置起来,我们知道springboot是基于注解开发的,所以当前controller类改造如下
@RestController
@RequestMapping("hello")
@EnableAutoConfiguration //启用springboot的自动化配置
public class HelloController {
@GetMapping("show")
public String test(){
return "hello world 1 !";
}
public static void main(String[] args) {
SpringApplication.run(HelloController.class,args);
}
}
运行结果:
就是这么简单,就是这么easy,从无到有,只需要创建工程,写一个controller类,配置注解,写main方法,就可以搭建一个轻量级的web application 。
虽然说我们上面搭建了一个项目,但是那个面方法只在当前类生效,如果我们有两个Controller类,那么我们需要写两个main函数,但是由上面的图我们发现默认端口为localhost:8080,所以我们如果再写一个main函数,那么我们将无法运行,因为端口已经被占用了,所以我们需要将main方法抽取出来,放在最外层。
如下图:
这样我们就能通过注解@ComponentScan让这个类扫描该类下的所有包及其子包
我们抽取出来的类如下:
@ComponentScan //扫描该类下的所有包及其子包
@EnableAutoConfiguration //启用springboot的自动化配置
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class);
}
}
二、连接数据库
作为一个web项目,数据库是必不可少的,下面我们来讲一下springboot如何连接数据库,连接数据库,我们首先要创建数据库连接池,本文我们将采用德鲁伊的数据库连接池。
下面我们将导入德鲁伊的pom文件
<!--德鲁伊相关依赖-->
<dependency>
<groupId>com.github.drtrang</groupId>
<artifactId>druid-spring-boot2-starter</artifactId>
<version>1.1.10</version>
</dependency>
接下俩我们来进行配置,为了方便起见,我们先手动创建一个properties文件,用来存放数据库相关配置
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmoa?useUnicode=true&characterEncoding=utf8
jdbc.username=
jdbc.password=
一般我们将数据写入properties文件我们想把文件加载到类中我们一般会先到的方法如下所示:
@Configuration //声明一个类是一个Java配置类,相当于一个xml文件
public class JdbcConfiguration {
@Bean //将该方法的返回值注入到spring容器中
public DataSource dataSource() {
Properties properties = new Properties();
InputStream is = JdbcConfiguration.class.getClassLoader().getResourceAsStream("db.properties");
try {
properties.load(is);
} catch (IOException e) {
e.printStackTrace();
}
/**
* 我们知道在配置文件时代,我们想要将datasource注入到spring容器中时,
* 我们也需要进行一系列的配置,如我们需要引入c3p0的的数据库连接池,
* 我们需要导入c3p0相应的jar包,所以我们在类中也同样要进行相应的操作,
* 这次,我们将使用德鲁伊的数据库连接池,此时我们需要在pom.xml中配置
* 德鲁伊相关的依赖。
*/
DruidDataSource dataSource = new DruidDataSource();
//连接池驱动类
dataSource.setDriverClassName((String) properties.get("jdbc.driverClassName"));
//连接url
dataSource.setUrl((String) properties.get("jdbc.url"));
//数据库用户名
dataSource.setUsername((String) properties.get("jdbc.username"));
//数据库密码
dataSource.setPassword((String) properties.get("jdbc.password"));
return dataSource;
}
}
或者是
@Configuration
//将配置文件加载到该类中
@PropertySource("classpath:db.properties")
public class JdbcConfiguration2 {
/**
* 我们已经将配置文件加载到该类中了,
* 我们需要对配置文件中的数据进行接收
*/
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
//把方法的返回值注入到spring容器
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
虽然我们将datasource注入到容器中了,但是我们还是需要手动加载文件,其实在springboot项目中,当项目开始,系统会自动加载一个配置文件,但是文件名是固定的一般为application.properties或者是application.yml,在idea中当我们创建了application.properties文件,文件的标志和普通的properties文件不同:
当我们添加了该配置文件之后,我们的代码可以写为:
/**在spring官网,也就是 https://spring.io/projects/spring-boot 我们了解到
* springboot项目是没有xml配置文件的,但是有一些配置我们还是要配置,所以spring官方
* 就将springboot的配置文件命名为 application.properties 我们一般会将所有的配置项
* 以 key=value 形式写到该文件中,springboot会将一些这写key=value形式的数据自动加载,
* ConditionalOnProperty 注解就是加载application.properties 文件,并取出我们需要的配置
* 但是,我们在这个配置文件中不可能只写一点的配置项,所以我们需要让系统认出我们需要那些值
* 我们我们加上前缀,等到程序在application.properties时只取前缀一样的配置项,比如,系统加载该注解时,就会在配置文件
* 会只取出以jdbc为前缀的配置项。
* /
@ConfigurationProperties(prefix = "jdbc") //加载application.properties文件,获取前缀为"jdbc"的属性值
public class JdbcProperties {
/**
* 我们需要注意的是,虽然我们不用写value注解,但是我们在此类中的属性名要和
* 配置文件中 jdbc.driverClassName 的后缀一样,比如我们定义了一个
* example.username = loltoulan
* 我们在@ConditionalOnProperty(prefix = "example")注解中写的前缀是
* 那么我们对应的属性名就必须为 username ,不可以为 name ,也不可以为 user,等其他的,
* 否则系统无法识别并进行注入操作,且我们需要对属性名添加getter setter 方法,因为系统会自动调用
* set方法,并进行赋值操作
*/
private String driverClassName;
private String url;
private String username;
private String password;
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
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;
}
}
//加载JdbcProperties.class文件
@EnableConfigurationProperties(JdbcProperties.class)
@Configuration
public class JdbcConfiguration3 {
//我们需要将我们的配置类注入到这里
//方法一
@Autowired
private JdbcProperties jdbcProperties;
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(this.jdbcProperties.getDriverClassName());
dataSource.setUrl(this.jdbcProperties.getUrl());
dataSource.setUsername(this.jdbcProperties.getUsername());
dataSource.setPassword(this.jdbcProperties.getPassword());
return dataSource;
}
//方法二
/*private JdbcProperties jdbcProperties;
public JdbcConfiguration3(JdbcProperties jdbcProperties) {
this.jdbcProperties = jdbcProperties;
}
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(this.jdbcProperties.getDriverClassName());
dataSource.setUrl(this.jdbcProperties.getUrl());
dataSource.setUsername(this.jdbcProperties.getUsername());
dataSource.setPassword(this.jdbcProperties.getPassword());
return dataSource;
}
*/
//方法三
/*@Bean
public DataSource dataSource(JdbcProperties jdbcProperties) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(jdbcProperties.getDriverClassName());
dataSource.setUrl(jdbcProperties.getUrl());
dataSource.setUsername(jdbcProperties.getUsername());
dataSource.setPassword(jdbcProperties.getPassword());
return dataSource;
}*/
//方法四
/* @Bean
@ConfigurationProperties(prefix = "jdbc")
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
return dataSource;
}
*/
}
我们通过Debug方式启动,我们发现,数据库连接池的四大属性已经自动加载到datasource中了,
SpringBoot的静态资源放在什么地方
想要了解我们的springboot项目的静态资源放在什么地方,首先,我们需要在jar包中找到项目人家已经给定好的目录,首先我们找到在那里定义的静态资源管理,我们知道这些都是spring boot自动配置的所哟我们首先到springboot下的
然后,因为我们是一个web项目,所以找到web文件夹下的
我们发现,在该class文件中,
我们找到了我们想要找到的静态资源默认的location,一共有四个,但是我们常用的是第三个,也就是"classpath:/static/",classpath路径也就是我们系的类最后编译成功后的那个路径
由上图我们知道,resources文件目录下的文件最终会被加载在classpath路径下。
所以我们的static目录应该创建在resources目录下,如下图
访问也很简单,因为spring boot项目自动加载的是resources目录下的static文件夹所以我们访问时,只需要在端口下加入我们的文件名即可,当然我们自己创建文件夹哈市要写上路径名字的,例如
将来我要访问毕业快乐.jpg这张图片,就需要这样写路径http://localhost:8080/img/毕业快乐.jpg
,虽然我们这里的路径是这样,但是我们还是要知道,中文在浏览器中传输说是要转码的,该请求真正向服务器发送的请求是:http://localhost:8080/img/%E6%AF%95%E4%B8%9A%E5%BF%AB%E4%B9%90.jpg
。
如何修改端口号
原理有点绕,简单记,在配置文件中,添加
server.port=8888
然后项目启动之后,我们直接访问8888端口就可以了,再也不需要在tomcat中修改端口了,妈妈再也不用担心我秃头了,开心,奥里给。
如何配置拦截器
因为我们知道在spring boot中没有各种配置文件,所以我们需要新建一个类,该类实现HandlerInterceptor接口,并将其注入到springIOC容器中,代码如下
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("前置拦截器");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("后置置拦截器");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("完成时拦截器");
}
}
但是这样还不行,因为我们需要将其加载到项目中,就像我们将拦截器写到spring-mvc.xml中一样,这时我们就需要将我们拦截器配置在框架中,共分两步
- 将该类声明为一个配置类
- 实现WebMvcConfigurer接口
//声明该类是一个配置类
@Configuration
public class WebmvcConfiguration implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor);
}
}
我们发现不仅我们的拦截器起作用了,而且我们的端口修改也起作用了
如何添加日志
在我们springboot框架中,其实框架已经集成好了,我们只需要在application.properties文件中添加相关的配置项即可
logging.level.org.springframework=DEBUG
springboot如何整合数据源
首先我们需要导入JDBC,然后我们需要导入MySQL相关的jar,接下来我们就可以直接在配置文件中配置连接数据库的四大参数了,为了能让框架认识我们配置的东西,我们配置的属性名,不能改变.
<!--jdbc相关依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--mysql相关依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
spring.datasource.url=jdbc:/// 数据库名
#spring.datasource.url=jdbc://localhost:3306/
spring.datasource.username= mysql用户名
spring.datasource.password= mysql密码
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
既然我们已经可以连接上数据库了,那么我们就想要操作数据库,那么我们可以整合一下mybatis
<!--mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
按照正常逻辑,我们已经可以进行书写了,特别是我们已经可以写mapper.xml 文件了,但是现在我们牛了,厉害了,我们可以通过通用mapper,我们自己写一个mapper接口,然后实现通用mapper的接口就可以实现一些方法了。
<!-- 通用mapper ,减少原生mybatis使用麻烦的痛点-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
注:关于通用mapper的讲解,我会抽出时间再写一篇博客,这里就不细讲
我们mapper接口的写法:
//注:Mapper<User>中mapper导入的jar包是:import tk.mybatis.mapper.common.Mapper;
@org.apache.ibatis.annotations.Mapper
public interface UserMapper extends Mapper<User> {
}
然后我们就在service中写出我们想要实现的接口,例如我们想实现查找所有的方法和查找某一个的方法,我们可以通过使用restful风格的url进行编写,service层和controller层如下
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User queryUserById(long id) {
return userMapper.selectByPrimaryKey(id);
}
@Override
@Transactional
public int deleteUserById(long id) {
return userMapper.deleteByPrimaryKey(id);
}
@Override
public List<User> findAll() {
return userMapper.selectAll();
}
@Override
public User queryUserByUserName(String userName) {
return userMapper.selectOneByExample(userName);
}
}
public interface UserService {
User queryUserById(long id);
int deleteUserById(long id);
List<User> findAll();
User queryUserByUserName(String userName);
}
@Controller
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("show")
@ResponseBody
public String test(){
return "hello world 1 !";
}
@GetMapping("find")
@ResponseBody
public List<User> findAll(){
return userService.findAll();
}
@GetMapping("find/{id}")
@ResponseBody
public User queryById(@PathVariable("id")Long id){
return userService.queryUserById(id);
}
}
查找一个
查找所有
springboot中的页面模板
像SSM可以使用jsp一样,springboot的页面模板是thymeleaf,该页面模板拥有和jsp一样的功能,却比jsp更加强大。
首先我们知道,jsp无法直接在浏览器打开,或者说在浏览器打开之后没有任何的页面展示效果,也就是说浏览器无法直接解析jsp文件,但是却可以直接解析thymeleaf页面模板文件,究其原因,是因为thymeleaf页面模板还是html文件,但jsp却是需要经过tomcat容器解析之后才能访问,jsp本质就是一个servlet,tomcat也是一个servlet容器 ,jsp必须经过tomcat容器解析之后才能响应给用户,但thymeleaf却可以直接在浏览器中打开,当然,thymeleaf模板也需要经过模板引擎解析之后才能相应给用户。
有一些简单的语法以及说明如下:
${}
:这个类似与el表达式,但其实是ognl的语法,比el表达式更加强大th-
指令:th-
是利用了Html5中的自定义属性来实现的。如果不支持H5,可以用data-th-
来代替th:each
:类似于c:foreach
遍历集合,但是语法更加简洁th:text
:声明标签中的文本- 例如
<td th-text='${user.id}'>1</td>
,如果user.id有值,会覆盖默认的1 - 如果没有值,则会显示td中默认的1。这正是thymeleaf能够动静结合的原因,模板解析失败不影响页面的显示效果,因为会显示默认值!
- 例如
thymeleaf模板示例:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<style type="text/css">
table {border-collapse: collapse; font-size: 14px; width: 80%; margin: auto}
table, th, td {border: 1px solid darkslategray;padding: 10px}
</style>
</head>
<body>
<div style="text-align: center">
<span style="color: darkslategray; font-size: 30px">欢迎光临!</span>
<hr/>
<table class="list">
<tr>
<th>id</th>
<th>姓名</th>
<th>用户名</th>
<th>年龄</th>
<th>性别</th>
<th>生日</th>
</tr>
<tr th:each="user : ${users}">
<td th:text="${user.id}">1</td>
<td th:text="${user.name}">张三</td>
<td th:text="${user.userName}">zhangsan</td>
<td th:text="${user.age}">20</td>
<td th:text="${user.sex}">男</td>
<td th:text="${user.birthday}">1980-02-30</td>
</tr>
</table>
</div>
</body>
</html>
controller层查找所有代码如下
@GetMapping("find")
public String findAll(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "users";
}
页面展示效果如下:
重点:当然,和css,js等一些其他静态文件一样,我们的thymeleaf模板文件也需要一个规定的文件夹,名为templates,当然也是在resources目录下,原因
我们知道,静态资源的自动配置在
下,所以我们知道,thymeleaf该模板的的配置器应该也在该包下,果不其然,我们在该包下发现了
我们发现了该模板的配置类,因为我们知道在SSM框架中,我们想要解析jsp文件,就需要在spring-mvc.xml中配置视图解析器,所以我们在该类下找该模板的视图解析器,果不其然
然后我们跟踪properties
,我们得到
然后,继续跟踪该类,我们终于发现
我们发现了默认的前缀,后缀,以及编码,所以一般我们会将html文件放在resources下的templates文件夹下。