SpringBoot实战教程
SpringBoot实战教程
参考笔记https://blog.csdn.net/lijiaming_99/article/details/119393342
Spring Boot 是 Spring 家族中的一个全新的框架,它用来简化 Spring 应用程序的创建和开发过程,也可以说 Spring Boot 能简化我们之前采用 SpringMVC + Spring +MyBatis 框架进行开发的过程。
在以往我们采用 SpringMVC + Spring +MyBatis框架进行开发的时候,搭建和整合三大框架,我们需要做很多工作,比如配置 web.xml,配置 Spring,配置 MyBatis,并将它们整合在 一起等,而 Spring Boot 框架对此开发过程进行了革命性的颠覆,完全抛弃了繁琐的 xml 配置过程,采用大量的默认配置简化我们的开发过程。
所以采用 Spring Boot 可以非常容易和快速地创建基于 Spring 框架的应用程序,它让编码变简单了,配置变简单了,部署变简单了,监控变简单了。正因为 Spring Boot 它化繁为简,让开发变得极其简单和快速,所以在业界备受关注。 Spring Boot 在国内的关注趋势图:http://t.cn/ROQLquP
1、入门案例
1.1、创建一个新的 Module,选择类型为 Spring Initializr
1.2、指定 GAV 及 pom 配置信息
1.3、选择 Spring Boot 版本及依赖
会根据选择的依赖自动添加起步依赖并进行自动配置
snapshot为快照不是稳定版本
release一定是正式版本
1.4、目录结构和pom.xml说明
- .mvn|mvnw|mvnw.cmd:使用脚本操作执行 maven 相关命令,国内使用较少,可删
除 - .gitignore:使用版本控制工具 git 的时候,设置一些忽略提交的内容
- static|templates:后面模板技术中存放文件的目录
- application.properties:SpringBoot 的配置文件,很多集成的配置都可以在该文件中
- 进行配置,例如:Spring、springMVC、Mybatis、Redis 等。目前是空的
- Application.java:SpringBoot 程序执行的入口,执行该程序中的 main 方法,SpringBoot
就启动了
对 POM.xml 文件进行解释
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--当前工程的GAV-->
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>demo</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--springboot框架web项目起步依赖-->
<!--SpringBoot 框架 web 项目起步依赖,通过该依赖自动关联其它依赖,不需要我们一个一个去添加了
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--springboot框架测试起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!--SpringBoot项目编译打包的插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@SpringBootApplication是核心注解,主要用于开启spring的自动配置
1.5、集成并验证Spring MVC
步骤明明和上面一毛一样
创建完成就是集成完毕
验证一下
注意:新创建的类一定要位于 Application 同级目录或者下级目录,否则 SpringBoot 加载不到。
package com.example.demo.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Author: Kopoo
* @Date: 2022/5/1 20:13
*/
@Controller
public class IndexController {
@RequestMapping(value = "/springboot/say")
public @ResponseBody String say() {
return "hello";
}
}
1.6、使用springboot的核心配置文件
a、在application.properties进行配置,项目中只能有一个
修改了端口号,上下文根
b、在application.yml进行配置
yaml一个道理,这个配置文件是有一定格式的,通过制表符来进行格式
c、两种配置文件都同时存在时
同时存在是以properties为标准的
1.7、多个生产环境下的配置文件设置
开发-生成-准备-测试->dev-product-ready-test
由主核心配置文件设置选择哪个配置文件
因此本项目的端口设置为8080 ,环境配置文件为开发环境
注意文件命名规范 一定要application-
开头
1.8、多环境yml配置文件使用
yml配置类似,同样要application-
开头,但是是以.yml为结尾
1.9、springboot自定义配置
注意加个@Value(“${school.name}”)
1.10、自定义配置映射到对象
package com.example.demo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Author: Kopoo
* @Date: 2022/5/3 17:34
*/
//将此类交给spring容器进行管理
@Component
@ConfigurationProperties(prefix = "school")
public class School {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
private String name;
private String website;
}
@Component
来设定此类为配置类,然后进行依赖注入
@ConfigurationProperties
使其读取properties的配置文件
package com.example.demo.web;
import com.example.demo.config.School;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: Kopoo
* @Date: 2022/5/1 20:13
*/
@Controller
public class IndexController {
@Autowired
private School school;
@RequestMapping(value = "/say")
@ResponseBody
public String say() {
return "hello"+school.getName();
}
@RequestMapping(value = "/mapvalue")
public @ResponseBody Map<String, String> mapvalue() {
Map<String, String> retMap = new HashMap<>();
retMap.put("message", "sdhfiusdhifu");
return retMap;
}
}
通过@Autowired对school对象进行依赖注入
中文乱码的处理
1.11、springboot集成jsp
1、新建一个文件夹webapp
2、设置识别webapp
3、设置之后成为web资源文件夹
4、pom.xml依赖配置
(1)在 pom.xml 文件中dependency标签种配置以下依赖项
<!--引入 Spring Boot 内嵌的 Tomcat 对 JSP 的解析包,不加解析不了 jsp 页面-->
<!--如果只是使用 JSP 页面,可以只添加该依赖-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
在 pom.xml 的 build 标签中要配置以下信息
(2)在 pom.xml 的 build 标签中要配置以下信息
SpringBoot 要求 jsp 文件必须编译到指定的 META-INF/resources 目录下才能访问,否则
访问不到。其实官方已经更建议使用模板技术(后面会讲模板技术)
<!--
SpringBoot框架集成jsp,指定jsp文件编译的路径META-INF/resources
-->
<resources>
<resource>
<!--指定源文件路径-->
<directory>src/main/webapp</directory>
<!--指定编译的路径-->
<targetPath>META-INF/resources</targetPath>
<includes>
<!--指定要把哪些文件编译进去,**表示 webapp 目录及子目录,*.*表示所有文件-->
<include>*.*</include>
</includes>
</resource>
</resources>
5、在 application.properties 文件配置 Spring MVC 的视图展示为 jsp,这里相当于 Spring MVC 的配置
6、 在src/main/java/com/example/demo/web 包下创建 IndexController 类,并编写代码
@RequestMapping(value = "/heihei")
public ModelAndView heihei() {
ModelAndView mv = new ModelAndView();
mv.addObject("message", "Hello");
mv.setViewName("heihei");
return mv;
}
注意jsp创建在webapp里面
2、Spring Boot 集成 MyBatis
1、新建一个springboot的module
2、然后在pom.xml里面添加依赖
ctrl+shift+/ 就是在xml文件里面添加注释
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis 集成springboot框架的起步依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
3、使用Mybatis提供的逆向工程生成实体bean,映射文件,DAO接口
方便生成实体bean和映射文件
首先这个逆向工程实际就是个代码生成器,先创建一个mapper和model文件夹
在目录下新建xml文件,然后配置以下GeneratorMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 指定连接数据库的 JDBC 驱动包所在位置,指定到你本机的完整路径 -->
<classPathEntry location="C:\Users\32611\.m2\repository\mysql\mysql-connector-java\5.1.48\mysql-connector-java-5.1.48.jar"/>
<!-- 配置 table 表信息内容体,targetRuntime 指定采用 MyBatis3 的版本 -->
<context id="tables" targetRuntime="MyBatis3">
<!-- 抑制生成注释,由于生成的注释都是英文的,可以不让它生成 -->
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!-- 配置数据库连接信息 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai"
userId="root"
password="123456">
</jdbcConnection>
<!-- 生成 model 类,targetPackage 指定 model 类的包名, targetProject 指定
生成的 model 放在 idea 的哪个工程下面-->
<javaModelGenerator targetPackage="com.example.demo.model"
targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
<property name="trimStrings" value="false"/>
</javaModelGenerator>
<!-- 生成 MyBatis 的 Mapper.xml 文件,targetPackage 指定 mapper.xml 文件的
包名, targetProject 指定生成的 mapper.xml 放在 eclipse 的哪个工程下面 -->
<sqlMapGenerator targetPackage="com.example.demo.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- 生成 MyBatis 的 Mapper 接口类文件,targetPackage 指定 Mapper 接口类的包
名, targetProject 指定生成的 Mapper 接口放在 eclipse 的哪个工程下面 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.example.demo.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>
<!-- 数据库表名及对应的 Java 模型类名 -->
<table tableName="stuinfo" domainObjectName="Student"
enableCountByExample="false"
enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
selectByExampleQueryId="false"/>
</context>
</generatorConfiguration>
好神奇!!!
就全都有了,自动生成代码,生成6个方法
package com.example.demo.mapper;
import com.example.demo.model.Student;
public interface StudentMapper {
int deleteByPrimaryKey(Integer stuid);
int insert(Student record);
int insertSelective(Student record);
Student selectByPrimaryKey(Integer stuid);
int updateByPrimaryKeySelective(Student record);
int updateByPrimaryKey(Student record);
}
如果出现只有insert方法康康这里
mapper.xml文件解释
prefix:在trim标签内sql语句加上前缀。
suffix: 在trim标签内sql语句加上后缀。
suffixOverrides:指定去除多余的后缀内容,如:suffixOverrides=",",去除trim标签内sql语句多余的后缀","。
prefixOverrides: 指定去除多余的前缀内容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bjpowernode.springboot.mapper.StudentMapper">
<resultMap id="BaseResultMap" type="com.bjpowernode.springboot.model.Student">
<!-- id标签只能修改主键-->
<!-- result除了主键以外的字段-->
<!-- column数据库中的字段名称-->
<!-- property映射对象的属性名称-->
<!-- jdbcType列中数据库中字段的类型(可以省略不写)-->
<!-- resultMap作用:
1,当数据库中字段名称与实体类对象的属性名不一致时,可以进行转换
2,当前查询的结果没有对象一个表的时候,可以自定义一个结果集-->
<!-- 数据库表字段名称 实体对象属性名称-->
<!-- user name product_type userName productType-->
<!-- 如果数据库中字段名称由多个单词构成,通过MyBatis逆向工程生成的对象属也会按照驼峰命名法规则生成属性名称-->
<!-- 其中:数据库中字段名称由多个单词构成的时候必须使用_下划线分隔-->
<id column="stuid" jdbcType="INTEGER" property="stuid" />
<result column="stuname" jdbcType="VARCHAR" property="stuname" />
<result column="gender" jdbcType="CHAR" property="gender" />
<result column="borndate" jdbcType="TIMESTAMP" property="borndate" />
</resultMap>
<!-- sql语句片段,将公共的部分抽取出来通过include标签引用sql语句片段-->
<sql id="Base_Column_List">
stuid, stuname, gender, borndate
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from stuinfo
where stuid = #{stuid,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from stuinfo
where stuid = #{stuid,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.example.demo.model.Student">
insert into stuinfo (stuid, stuname, gender,
borndate)
values (#{stuid,jdbcType=INTEGER}, #{stuname,jdbcType=VARCHAR}, #{gender,jdbcType=CHAR},
#{borndate,jdbcType=TIMESTAMP})
</insert>
<!-- suffixOverrides 去除后缀多余的逗号-->
<insert id="insertSelective" parameterType="com.example.demo.model.Student">
insert into stuinfo
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="stuid != null">
stuid,
</if>
<if test="stuname != null">
stuname,
</if>
<if test="gender != null">
gender,
</if>
<if test="borndate != null">
borndate,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="stuid != null">
#{stuid,jdbcType=INTEGER},
</if>
<if test="stuname != null">
#{stuname,jdbcType=VARCHAR},
</if>
<if test="gender != null">
#{gender,jdbcType=CHAR},
</if>
<if test="borndate != null">
#{borndate,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
<!-- set 去除后缀多余的逗号-->
<update id="updateByPrimaryKeySelective" parameterType="com.example.demo.model.Student">
update stuinfo
<set>
<if test="stuname != null">
stuname = #{stuname,jdbcType=VARCHAR},
</if>
<if test="gender != null">
gender = #{gender,jdbcType=CHAR},
</if>
<if test="borndate != null">
borndate = #{borndate,jdbcType=TIMESTAMP},
</if>
</set>
where stuid = #{stuid,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.example.demo.model.Student">
update stuinfo
set stuname = #{stuname,jdbcType=VARCHAR},
gender = #{gender,jdbcType=CHAR},
borndate = #{borndate,jdbcType=TIMESTAMP}
where stuid = #{stuid,jdbcType=INTEGER}
</update>
</mapper>
只能进行单表操作
4、 在 web 包下创建 StudentController 并编写代码
package com.example.demo.web;
import com.example.demo.model.Student;
import com.example.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Author: Kopoo
* @Date: 2022/7/3 20:01
*/
@Controller
public class StudentController {
@Autowired
private StudentService studentService;
@RequestMapping(value = "/student")
public @ResponseBody Object student(Integer id) {
Student student = studentService.queryStudentById(id);
return student;
}
}
5、在service 包下创建 service 接口并编写代码
package com.example.demo.service;
import com.example.demo.model.Student;
import org.springframework.stereotype.Service;
/**
* @Author: Kopoo
* @Date: 2022/7/3 20:05
*/
public interface StudentService {
/**
* 根据学生id查询详情
* @param id
* @return
*/
Student queryStudentById(Integer id);
}
6、在 service.impl 包下创建 service 接口并编写代码
package com.example.demo.service.impl;
import com.example.demo.mapper.StudentMapper;
import com.example.demo.model.Student;
import com.example.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @Author: Kopoo
* @Date: 2022/7/3 20:08
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper studentMapper;
@Override
public Student queryStudentById(Integer id) {
return studentMapper.selectByPrimaryKey(id);
}
}
7、在 Mybatis 反向工程生成的 StudentMapper 接口上加一个 Mapper 注解
package com.example.demo.mapper;
import com.example.demo.model.Student;
import org.apache.ibatis.annotations.Mapper;
@Mapper//扫描dao接口到springboot容器
public interface StudentMapper {
int deleteByPrimaryKey(Integer stuid);
int insert(Student record);
int insertSelective(Student record);
Student selectByPrimaryKey(Integer stuid);
int updateByPrimaryKeySelective(Student record);
int updateByPrimaryKey(Student record);
}
8、别忘了在 Springboot 的核心配置文件 application.properties 中配置数据源
#设置数据库的连接配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
9、在pom.xml文件中指定资源文件夹(这个前题是Studentmapper.xml文件在src/main/java路径下)
默认情况下,Mybatis 的 xml 映射文件不会编译到 target 的 class 目录下,所以我们需要在 pom.xml 文件中配置 resource
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
target依然显示不出来xml,就直接复制一个过去。。(离谱但是很有用)
一般xml放在resource里面更好点,可以直接读取到
10、DAO 其它开发方式(替换7)
在 运 行 的 主 类 上 添 加 注 解 包 扫 描
@MapperScan(“com.abc.springboot.mapper”)
注释掉 StudentMapper 接口上的@Mapper 注解
在运行主类 Application 上加@MapperScan(“com.abc.springboot.mapper”)
11、将接口和映射文件分开
因为 SpringBoot 不能自动编译接口映射的 xml 文件,还需要手动在 pom 文件中指定,
所以有的公司直接将映射文件直接放到 resources 目录下
➢ 在 resources 目录下新建目录 mapper 存放映射文件,将 StudentMapper.xml 文件移
到 resources/mapper 目录下
在 application.properties 配置文件中指定映射文件的位置,这个配置只有接口和映
射文件不在同一个包的情况下,才需要指定
# 指定 Mybatis 映射文件的路径
mybatis.mapper-locations=classpath:mapper/*.xml
无须再配置 resource
关于Mapper映射文件存放的位置的写法有以下两种:
1,将Mapper接口和Mapper映射文件存放到src/main/java同一目录下,还需要在pom文件中手动指定资源文件夹路径resources
2·将Mapper接口和Mapper映射文件分开存放Mapper接口类存放到src/main/java目录下Mapper映射文件存放到resources(类路径)
在springboot核心配置文件中指定mapper映射文件存放到位置
3、Springboot的事务支持
Spring Boot 使用事务非常简单,底层依然采用的是 Spring 本身提供的事务管理
事务只跟sql语句有关,也就是dml语句,增删改查
➢ 在入口类中使用注解 @EnableTransactionManagement 开启事务支持
➢ 在访问数据库的 Service 方法上添加注解 @Transactional 即可
通过 SpringBoot +MyBatis 实现对数据库学生表的更新操作,在 service 层的方法中构建
异常,查看事务是否生效
该项目是在 章节2的基础上添加新增方法,在新增方法中进行案例的演示
1、在 StudentController 中添加更新学生的方法
@RequestMapping(value = "/update")
public @ResponseBody Object update(Integer id,String name) {
int count = 0;
try {
Student student = new Student();
student.setStuid(id);
student.setStuname(name);
count = studentService.updateStudentById(student);
} catch (Exception e) {
e.printStackTrace();
return "fail";
}
return "修改学生编号为"+id+"的姓名修改结果"+count;
}
2、在 StudentService 接口中添加更新学生方法
/**
* 根据学生ID修改学生信息
* @param student
* @return
*/
int updateStudentById(Student student);
3、在 StudentServiceImpl 接口实现类中对更新学生方法进 行实现,并构建一个异常,同时在该方法上加@Transactional 注解
@Override
@Transactional //添加此注解说明该方法添加的事务管理
public int updateStudentById(Student student) {
//修改成功
int i = studentMapper.updateByPrimaryKeySelective(student);
//失败
int a =10/0;//在此构造一个除数为 0 的异常,测试事务是否起作用
return i;
}