微服务框架——SpringBoot
SpringBoot
1.创建Boot项目的两种方式
1.1通过spring网站创建
- 
选择填写对应配置,打包  
- 
将zip格式的压缩包解压,并导入该项目 
1.2 通过idea集成的springboot创建
其实就是idea帮你做了第一种方法
- 
新建项目时选择spring初始化  
- 
选择对应的配置  
1.3 可能出现的问题
- 项目的配置文件变成了灰色

只是因为项目被idea忽视了,右键点击pom文件,选择不忽视即可

- 
spring-boot-maven-plugin配置爆红  这个问题的解决办法有很多种,但我是用加上版本号的方式解决的,这个解决方式很奇怪,按理说springboot的依赖版本是交由父工程委托的 ++ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.2.RELEASE</version>
- 
启动类的注解、导包爆红 可能是部分包没有导进项目 依旧是右键单击pom选择重新导依赖  
2. 基础的Springboot项目搭建
2.1 yml配置文件
 boot支持properties配置文件的同时,也支持yml/yaml配置文件
 yml的语法比xml更加简洁,一般是用 键+':'+'空格+值来表示,比如:
server.port: 8080
 如果是数组,则可以这样表示:
list: [1,2,3]
list: 
- 1
- 2
 如果是map集合,可以这样表示
map1: {key1: v1,key2: v2}
map2: 
    key1: v1
    key2: v2
 如果是对象,可以这样表示
object: {name: 姬如千泷,age: 20}
 有了yml配置后,我们可以让对象属性赋值变得很简单,之前我们采用的是@value注解直接在原类的属性上注解出值,这样比较麻烦而且动态性比较差,后来是用properties配置文件导入,再一个个注解出来,虽然动态性强了,但还是麻烦,像这样
@PropertySource(value = "classpath:person.properties")
@Component //注册bean
public class Person {
    @Value("${name}")    
    private String name; 
}
 使用yml注入属性需要导入一个依赖
<dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-configuration-processor</artifactId>  <optional>true</optional></dependency>
 之后我们只需要,在实体类上写两个注解就可以自动注入了
@Component //注册bean
@ConfigurationProperties(prefix = "person")
//将配置文件中的person下的属性和类属性一一对应注入
 是不是非常的银杏,而且使用yml注 入的好处是他支持松散绑定和JSR303校验,感兴趣的同志可以自行去了解一下
 不仅如此,yml可以同时在一个配置文件内设置多套环境,用“---”分割并用spring: profiles: name命名即可,用spring: profiles: active: name选择使用哪套环境
 说到环境配置文件,boot内部有四个默认的配置文件扫描路径,优先级从高往低分别是
file:./config/   项目路径下的config包
file:./        
classpath:/config/  资源路径下的config包
classpath:/
2.2 springboot静态资源扫描
boot的静态资源扫描有很多种方式:
- 自定义静态资源扫描路径
#配置项目的访问路径
server.servlet.context-path=/boot
#配置静态资源扫描路径
spring.resources.static-locations=/boot
- 
webjars静态资源配置,访问目录在webjars的子包中,一般很少用到 
- 
最常用的是系统默认の静态资源目录,也就是说在这些路径下的静态资源,可以直接用其名字访问。不用在加路径 
classpath:/static
classpath:/public
classpath:/resources
classpath:/META-INF/resources
2.3 自定义首页
boot项目搭建好之后是可以运行的,去浏览器访问8080端口会报404错误,这是因为boot不会自己生成首页,需要自己在静态资源目录创建一个index.html 名字和格式都是固定的,同样也可以在静态资源目录下创建项目图标,favicon.ico 名字和格式固定

2.4 thymeleaf 模板引擎
当我们想像mvc一样去建很多的跳转控制类的时候,需要将页面放入静态资源目录中,并且在控制类中返回文件的全名,比如"hello.html",但怎么样才能实现像mvc那样只返回hello呢,一种方法是重写自定义视图解析器交给boot,另一种方法是用thymeleaf模板引擎,使用前需要导入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

通过源码可以看到,通过thymeleaf注入前后缀的路径是在而且在templates文件夹下,而且新建项目时,boot已经为我们创建好了一个templates文件夹
不仅如此,thymeleaf作为一个模板引擎,还支持像jsp一样动态的数据绑定,thymeleaf的具体语法推荐一个博主Thymeleaf的基本语法,使用的时候别忘了向html中引入命名空间
2.5 整合数据库
boot访问数据层的统一接口都是Spring Data
2.5.1 JDBC整合
- 第一种方式是在项目初始化前引入相应模块
- 
其实用第一种方式初始化的项目下来可以观察到,他就是为我们加了jdbc对应的启动器,所以我们也可以手动加入 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
- 
随后在yml里配置数据源(用户名、密码、URl、驱动),配置完数据源后,整个连接就已经交给boot容器了,我们只需要区获取连接就行,boot会默认将配置数据交给HikariDataSource处理,这也是boot默认的数据源 spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/数据库名?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 driver-class-name: com.mysql.cj.jdbc.Driver
- 
之后就可以直接使用boot提供的jdbc模板类去执行sql语句了,在boot测试类new一个模板对象,我这里只是测试,一般需要建实体类orm @SpringBootTest class Practice08ApplicationTests { @Autowired JdbcTemplate jdbcTemplate; @Test void contextLoads() { String sql = "select * from books"; List<Map<String,Object>> list = jdbcTemplate.queryForList(sql); for (Map<String, Object> map : list) { System.out.println(map.toString()); } } }
- 
我这边遇到两个问题,一个是未将配置文件设置为boot项目配置文件,一般idea会默认设置 第二个是url的时区问题,我用的之前mybatis连接时的时区severTimezone=GMT%2B8会报错,更换了新时区就没问题了serverTimezone=Asia/Shanghai  
2.5.2 整合Mybatis
- 
导入MyBatis依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version></dependency>
- 
配置数据库数据(username、password、url...) 
- 
创建实体类 
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
    int bookID;
    String bookName;
    int bookCounts;
    String detail;
}
- 创建Mapper接口,要加component和mapper注解
@Mapper
@Component
interface BookMapper {
    List<Book> getBooks();
}
- 配置Mapper.xml,别忘记在pom中配置静态资源过滤
<?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="mapper接口路径">
    <select id="getBooks" resultType="Book">
       select * from books;
    </select>
</mapper>
- 
测试 @SpringBootTest class Practice08ApplicationTests { @Autowired BookMapper bookMapper; @Test void contextLoads() { List<Book> books = bookMapper.getBooks(); for (Book book : books) { System.out.println(book.toString()); } } }
3.SpringSecurity
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架,侧重于为Java应用程序提供身份验证和授权。
在使用SpringSecurity之前,需要先导入SpringSecurity的启动器
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>
3.1 身份认证
身份验证是服务器用识别用户的凭据,一般是用户名和密码,或者第三方验证结合使用。在boot中集成SpringSecurity身份认证,只需要继承WebSecurityConfigurerAdapter类并重写方法就可以
@EnableWebSecurity // 开启WebSecurity模式
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
   auth.inMemoryAuthentication()
       //定义一个用户以及他的权限等级
    .withUser("amlia").password("123456").roles("权限1","权限2")
      .and()//可以通过and定义多个用户
}
}
需要提一嘴的是,如果要使用SpringSecurity的身份验证,为了安全,他会强制你进行密码加密不然就会报错,以amlia用户举例
 auth.inMemoryAuthentication().passwordEncoder(在这里new一个加密类的对象)
          .withUser("amlia").password(new一个对应的加密对象).roles()
3.2 权限控制
3.1上面对每个角色赋予的某种角色/权限,如何让这些权限生效呢,最典型的就是控制他们对某些页面的访问权限
@Override
protected void configure(HttpSecurity http) throws Exception {
   // 定制请求的授权规则
    
   // 首页所有人可以访问
  http.authorizeRequests().antMatchers("/").permitAll()
      //可以.出多条权限控制
  .antMatchers("页面路径").hasRole("权限1")
  .antMatchers("").hasRole("");
}
那么如果要在前端进行权限控制,比如某些没有该页面权限的用户直接就不显示他的交互链接或者不显示一些页面该怎么做呢,thymeleaf提供了security的集成,导入依赖和命名空间
<dependency>
   <groupId>org.thymeleaf.extras</groupId>
   <artifactId>thymeleaf-extras-springsecurity5</artifactId>
   <version>3.0.4.RELEASE</version>
</dependency>
这时候我们只需要在对应的块元素中加入这样一个属性,就可以轻松实现
<div class="column" sec:authorize="hasRole('权限名')">
</div>
3.3 注销功能
在权限控制的重写函数里加上 http.logout();就可以实现
当然前端要有对应的链接或者按钮指向/logout ,这是boot默认的注销接口,比如
<a class="item" th:href="@{/logout}">
   <i class="address card icon"></i> 注销
</a>
3.4 记住我功能
同样一句http.rememberMe();搞定
3.5 定制登录页面
之前所有的登录页面都是security替我们做的,美得丑的更版本都不一样,如何自定义登录页面呢
首先需要将自己的登录页交给controller,即为他定制一个接口,比如/MyLogin ,然后加一句配置http.formLogin().loginPage("/MyLogin");就可以了,之后所有走向/MyLogin的服务都会被接管
需要注意的是,ssecurity默认的登录处理是/login,所以表单提交的目标地址也是/login,并且要保证用户名密码的name和security里的对应,即name="username";name="password"
能不能自定义呢,当然可以
//配置登录处理路径
.loginProcessingUrl("/authentication/form")
//配置自定义用户名密码name
  .formLogin()
  .usernameParameter("username")
  .passwordParameter("password")
除此之外,自定义登录页还有个记住我的功能对接,我们设置记住我单选框的name值,并通过配置name达到对接
http.rememberMe().rememberMeParameter("remember");
4.整合Swagger
swagger是一个前后端分离的Api框架,它实现了实时api跟踪,在线测试api等功能。同样需要导入依赖
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>2.9.2</version>
</dependency>
<dependency>
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger-ui</artifactId>
   <version>2.9.2</version>
</dependency>
要使用swagger的话,需要一个swagger的配置类
@Configuration //配置类
@EnableSwagger2// 开启Swagger2的自动配置
public class SwaggerConfig {  
}
到此,就可以访问boot项目对应的swagger页面了,路径是项目路径+swagger-ui.html
可以发现,swagger里有一个模块选择界面,这里面每一个选项都是一个Bean实例

在swagger里称作Docket,docket默认的配置页面是这样的
@Bean //配置docket以配置Swagger具体参数
public Docket docket() {
   return new Docket(DocumentationType.SWAGGER_2);
}
后面还可以点出很多的配置,比如一个ApiInfo对象,.apiInfo(ApiInfo对象);
new ApiInfo(//大多是swagger的一些自定义描述信息
           "", // 标题
           "", // 描述
           "", // 版本
           "http://terms.service.url/组织链接", // 组织链接
           Contact实例, // 联系人信息
           "Apach 2.0 许可", // 许可
           "许可链接", // 许可连接
           new ArrayList<>()// 扩展
  );
  
new Contact(
          "联系人名字", 
          "http://xxx.xxx.com/联系人访问链接", 
          "联系人邮箱");
再比如通过.select方法去指定扫描的接口,我们需要用build去构造对应的方法:比如
.select()// 通过.select()方法,去配置扫描接口
.apis(RequestHandlerSelectors.basePackage("包路径"))
//.paths配置跳过扫描哪些包
再比如通过.groupName设置分组名,就是模块选择那块的名字




 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号