Springboot
为什么学习Springboot
随着我们写的项目以及学会的技术越来越多,会发现项目变得越来越大,项目的配置文件变得非常复杂,并且配置文件非常多,jar包依赖也变得非常多,项目越来越臃肿,配置起来也越来越麻烦,而springboot可以简化我们的配置,达到开箱即用的效果
Springboot与Spring、SpringMVC之间有什么区别
Spring
主要用处是ioc用来管理对象,降低应用之间的耦合度
aop主要用来控制事务
SpringMVC
SpringMVC提供了分离的方式让我们简化了web应用的开发,通过DispatcherServlet,ModelAndView等元素让我们开发web应用更加简单,但是无论Spring还是SpringMVC都有一个共同的特性,就是都需要大量的配置才可以使用
Springboot
1、主要用来简化Spring应用程序的初始化以及搭建过程
1.1、将项目需要使用的很多依赖整合到了一起(简化了maven配置)
1.2、提供了很多的默认配置,用户可以不需要进行太多配置,即可启动项目(应用程序提供有自动的配置)
2、嵌入式的tomcat容器,我们不需要使用编译工具去管理tomcat
3、Springboot提供应用的测试以及监控等一条龙服务
创建Springboot的方式
1、搭建普通的maven项目,然后引入Springboot的依赖即可
2、下载官方的demo,然后使用编译工具导入即可(SpringInitializr)
项目结构
Application类
项目的入口,我们需要使用这个类来启动项目
application.properties属性文件
如果我们需要修改springboot的默认配置,需要将修改的配置写在这里
static
存放所有web的静态资源(css、js、img等)
templates
存放我们项目页面的地方
Springboot中的starter是什么
starter是springboot中的启动器,我们可以理解为一组依赖的描述符,里面定义了所有当前启动器相关的依赖以及默认配置,我们只需要下载启动器就能把所有相关依赖下载下来,并且所有的相关依赖版本都是由启动器自动管理,不需要我们操心
Springboot的一些问题
1、为什么我们访问ishangu.controller包下的Hello2Controller不能访问到呢
在项目中我们没有做任何配置,包括扫描路径我们也没有进行配置,访问hello2会出现404,代表这个路径没有被springIOC容器扫描
2、为什么我们访问springboot.controller包下的HelloController能访问到呢
Springboot提供很多默认配置,其中就包括默认配置的扫描路径,而其默认的扫描路径是启动类所在的包以及其所有的子包
3、为什么springboot会默认扫描启动类下面的所有类呢
@SpringBootApplication,用来表示这个类是springboot的启动类,这个启动类我们一般也称之为主配置类,@SpringBootApplication注解是一个组合注解,里面包含有一下注解
@SpringBootConfiguration,用来修饰类,表示这个类是一个配置类(相当于配置文件),作用与spring中的@Configuration一致
@EnableAutoConfiguration,开启自动配置的功能,以前的配置文件中很多内容都需要我们自己去写,而Springboot提供了很多默认配置,而这些配置就是使用这个注解来开启的,使用这个注解之后,会自动加载spring=boot-autoConfiguration依赖里面的默认配置
@ComponentScan( 用处是用于扫面所有spring的相关注解(相当于直接在xml中配置的扫描路径),默认扫描的是当前类所在的包以及所有的子包
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter( 过滤器
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
如何将bean配置到IOC容器中
方式一
@SpringBootConfiguration注解配合@Bean注解来将一个类的对象放入到IOC容器之中
@SpringBootConfiguration //这个类相当于一个xml配置文件
public class BeanConfig {
/**
*
* @Bean 相当于之前xml中的bean标签,会将方法的返回值放入到IOC容器中
*/
@Bean
public Cat getCat(){
return new Cat();
}
}
方式二
使用@import注解导入
@RestController
@Import(Dog.class)
public class HelloController {
@Autowired
Cat cat;
@Autowired
Dog dog;
@RequestMapping("hello")
public String hello(){
System.out.println(cat);
System.out.println(dog);
return "hello";
}
}
方式三
使用@import注解配合importSelector接口
public class ConfigSelector implements ImportSelector {
/**
* 这里面要求返回的是类的实例化对象的全限定名
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {"com.ishangu.springboot.Dog"};
}
@Override
public Predicate<String> getExclusionFilter() {
return null;
}
}
@RestController
@Import(ConfigSelector.class)
public class HelloController {
@Autowired
Cat cat;
@Autowired
Dog dog;
@RequestMapping("hello")
public String hello(){
System.out.println(cat);
System.out.println(dog);
return "hello";
}
}
方式四
使用@import注解配合ImportBeanDefinitionRegistrar接口
public class ConfigDeferredImport implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
// 判断IOC容器中是否有这个类型的bean,如果存在返回ture,如果不存在返回false
boolean b = registry.containsBeanDefinition("com.ishangu.springboot.Dog");
if (!b) { // 进入到if证明IOC容器中没有dog
RootBeanDefinition root = new RootBeanDefinition(Dog.class);
registry.registerBeanDefinition("dog",root);
}
}
}
@RestController
@Import(ConfigDeferredImport.class)
public class HelloController {
@Autowired
Cat cat;
@Autowired
Dog dog;
@RequestMapping("hello")
public String hello(){
System.out.println(cat);
System.out.println(dog);
return "hello";
}
}
方式五
引入xml配置文件中的bean(不推荐使用),像之前一样写application.xml,然后使用注解引入这个配置文件@ImportResource(“application.xml”)
修改Springboot默认配置
在我们Springboot项目中一般都存在一个application.properties或者application.yml的配置文件,名称是绝对不能修改的,修改后Springboot就不会加载这个文件,我们可以在这个文件中修改Springboot提供的默认配置,在Springboot项目中允许properties和yml文件同时存在,并且两个文件都会进行加载,但是需要注意的是,properties的属性文件优先级较高,也就是说当我们在properties和yml同时修改一项内容的时候,Springboot会以properties文件为主
server.port=8888
server:
port: 9999
SpringData-JPA
JPA是ORM持久层的规范,JPA自身只是定义了规范了而已,其实现需要依赖ORM框架来进行实现。
JPA简称Java持久层API,主要通过hibernate来提供实现,因为hibernate是全自动的ORM框架(Mybatis只是半自动的ORM框架,所以没有实现JPA规范)
需要注意的是,当我们引入JAP以来之后,Springboot并不知道我们想使用的数据库是什么,所以需要我们自己引入数据库驱动包,并且Springboot也不知道我们数据源相关内容,所以只能让我们自己来配置
Repository接口
1、Repository接口(祖爷爷)
1.1、我们只需要在接口中写方法名称,只要方法名称写的规范,JPA会自动给我们生成查询的sql语句
1.2、提供了@Query注解让我们可以在注解中写sql语句
2、GRUDRepository接口(爷爷)
2.1、有Repository接口所有功能
2.2、自身提供了很多CRUD的方法
3、PagingAndSortingRepository接口(父亲)
3.1、有GRUDRepository接口的所有功能
3.2、自身提供分页和排序的功能
4、JpaRepository接口(儿子)
4.1、有PagingAndSortingRepository接口的所有功能,并且可以对父接口的返回值进行适配
5、JpaSpecificationExecutor接口(单独的)
5.1、与上面几个完全没有任何关系,是一个自身独立的接口
5.2、主要来实现多条件查询
项目书写顺序
1、pom引入依赖
<?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>
<!--用来统一定义所有Springboot启动器的版本号,之后引入Springboot相关的依赖就不需要定义版本号-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.11</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ishangu</groupId>
<artifactId>SpringBoot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBoot</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--里面提供了springboot项目运行需要的最基本依赖,以及相关的配置文件-->
<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.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!--提供一些像maven一样的命令,比如启动项目、打包项目、管理项目生命周期等命令
启动项目 spring-boot run
打包项目 spring-boot repackage
-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、编写model类
package com.ishangu.springboot.model;
import javax.persistence.*;
/**
* 与数据库对应的model类
* @author 76177
*/
@Entity // 说明这个类是一个与数据库对应的model类
@Table(name = "admin")
public class Admin {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 指定主键生成策略
@Column(name = "id")// 指定对应数据库的列名
private Integer id;
@Column(name = "login_name")// 指定对应数据库的列名
private String loginName;
@Column(name = "login_pwd")// 指定对应数据库的列名
private String loginPwd;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getLoginPwd() {
return loginPwd;
}
public void setLoginPwd(String loginPwd) {
this.loginPwd = loginPwd;
}
@Override
public String toString() {
return "Admin{" +
"id=" + id +
", loginName='" + loginName + '\'' +
", loginPwd='" + loginPwd + '\'' +
'}';
}
}
3、编写dao层接口
package com.ishangu.springboot.repository;
import com.ishangu.springboot.model.Admin;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
/**
* 泛型中存放的是model类的类型以及ID的类型
*
* @author 76177
*/
public interface AdminRepository extends CrudRepository<com.ishangu.springboot.model.Admin, Integer> {
/*@Query("from Admin where loginName=:loginName and loginPwd=:loginPwd")
com.ishangu.springboot.model.Admin login(@Param("loginName") String loginName, @Param("loginPwd") String loginPwd);*/
// 方式二:要求查询时候必须要以find、get、read开头,findAll表示查询多个,findBy属性名表示根据属性来进行查询
Admin findByLoginNameAndLoginPwd(@Param("loginName") String loginName, @Param("loginPwd") String loginPwd);
}
4、编写service以及实现类
package com.ishangu.springboot.service;
import com.ishangu.springboot.model.Admin;
import java.util.List;
public interface AdminService {
void save(com.ishangu.springboot.model.Admin admin);
void update(com.ishangu.springboot.model.Admin admin);
void deleteById(Integer id);
Admin findByLoginNameAndLoginPwd(String loginName, String loginPwd);
Admin findById(Integer id);
List<Admin> findAll();
}
package com.ishangu.springboot.service.impl;
import com.ishangu.springboot.model.Admin;
import com.ishangu.springboot.repository.AdminRepository;
import com.ishangu.springboot.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author 76177
*/
@Service
public class AdminServiceImpl implements AdminService {
@Autowired
AdminRepository repository;
@Override
public void save(com.ishangu.springboot.model.Admin admin) {
repository.save(admin);
}
@Override
public void update(com.ishangu.springboot.model.Admin admin) {
repository.save(admin);
}
@Override
public void deleteById(Integer id) {
repository.deleteById(id);
}
@Override
public Admin findByLoginNameAndLoginPwd(String loginName, String loginPwd) {
return repository.findByLoginNameAndLoginPwd(loginName, loginPwd);
}
@Override
public Admin findById(Integer id) {
return repository.findById(id).get();
}
@Override
public List<com.ishangu.springboot.model.Admin> findAll() {
return (List<Admin>) repository.findAll();
}
}
5、编写Controller
package com.ishangu.springboot.controller;
import com.ishangu.springboot.model.Admin;
import com.ishangu.springboot.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author 76177
*/
@RestController
public class AdminController {
@Autowired
AdminService service;
@RequestMapping("save")
public String save(Admin admin) {
service.save(admin);
return "OK";
}
@RequestMapping("update")
public String update(Admin admin) {
service.update(admin);
return "OK";
}
@RequestMapping("deleteById")
public String deleteById(Integer id) {
service.deleteById(id);
return "OK";
}
@RequestMapping("login")
public Admin login(String loginName, String loginPwd) {
return service.findByLoginNameAndLoginPwd(loginName, loginPwd);
}
@RequestMapping("findById")
public Admin findById(Integer id) {
return service.findById(id);
}
@RequestMapping("findAll")
public List<Admin> findAll() {
return service.findAll();
}
}
6、启动项目进行测试
package com.ishangu;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.ishangu.mapper")
public class MmallApplication {
public static void main(String[] args) {
SpringApplication.run(MmallApplication.class, args);
}
}
分页和排序的用法
package com.ishangu.springboot.controller;
import com.ishangu.springboot.model.Emp;
import com.ishangu.springboot.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmpController {
@Autowired
EmpService service;
@RequestMapping("findAllPage")
public Page<Emp> findAll(int page, int size) {
return service.findAll(PageRequest.of((page - 1) * size, size));
}
@RequestMapping("findAllSort")
public Iterable<Emp> findAll(){
return service.findAll(Sort.by(Sort.Direction.ASC,"id"));
}
}
Springboot集成通用mapper
通用mapper是mybatis的一个插件,与我们的generator类似都是一种插件,但是通用mapper除了可以集成generator以外,还在其基础上提供了更多的操作
通用mapper集成MBG插件生成代码
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.5.11</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ishangu</groupId>
<artifactId>springbootMybatisT</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springbootMybatisT</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<!--配置通用mapper,数据库驱动等信息-->
<configuration>
<configurationFile>${project.basedir}/src/main/resources/generatorConfiguration.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.1.5</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
准备generatorConfiguration.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>
<context id="mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<!--指定插件-->
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
<property name="caseSensitive" value="true"/>
</plugin>
<commentGenerator>
<!--压制所有注释-->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql:///a" password="123456" userId="root"></jdbcConnection>
<javaModelGenerator targetPackage="com.ishangu.model" targetProject="./src/main/java">
<!--是否允许子包-->
<property name="enableSubPackages" value="false"/>
<!--生成的model是否有构造方法-->
<property name="constructorBased" value="true"/>
<!--指定生的model是否不包含set方法-->
<property name="immutable" value="false"/>
</javaModelGenerator>
<sqlMapGenerator targetPackage="mappers" targetProject="./src/main/resources"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.ishangu.dao" targetProject="./src/main/java"/>
<table tableName="admin" domainObjectName="Admin">
<generatedKey column="id" sqlStatement="jdbc"/>
</table>
</context>
</generatorConfiguration>
添加Oracle依赖
mvn install:install-file -Dfile=d:/ojdbc6.jar -Dpackaging=jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.1.0