佳林L

博客园 首页 新随笔 联系 订阅 管理

 

SpringBoot

1:Spring Boot简介

简化Spring应用开发的一个框架。

整个Spring技术栈的一个大整合。

JavaEE开发的一站式解决方案。

2:微服务

2014,martin fowler

微服务:架构风格(服务微化)

一个应用应该是一组小型服务;可以通过Http的方式进行互通。

每一个功能元素最终都是一个可独立替换和独立升级的软件单元。

3:YAML语法

一,基本语法

K:V:表示一对键值对(空格必须有)

以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的。

server:
port: 8081
path: /hello

属性和值大小写敏感的。

 

二,值的写法

● 字面量:普通的值(数字,字符串,布尔)

k:v:字面直接来写;

字符串默认不用加上单引号或者双引号;

"":双引号;不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思。

name:"zhangsan \n lisi":输出:zhangsan 换行 lisi

'':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据。

name:"zhangsan \n lisi":输出:zhangsan \n lisi

 

● 对象:Map(属性和值)(键值对)

k:v:在下一行来写对象的属性和值的关系;注意缩进

friends:
lastname:zhangsan
age:20

行内写法:

friends:{lastname:zhangsan,age:20}

 

● 数组:(List,Set)

用 - 值表示数组中的一个元素

pets:
- cat
- dog
- pig

行内写法:

pets:[cat,dog,pig]

 

三,配置文件值注入

配置文件:

persen:
  lastname: zhangsan
  age: 18
  boss: false
  birth: 2017/12/12
  maps: {k1: v1,k2: v2}
  list:
    - list
    - zhaoliu
  dog:
    name: xiaogou
    age: 20

javaBean:

/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties:告诉SpringBoot将本类中所有属性和配置文件中相关的配置进行绑定
* (prefix = "persen"):配置文件中那个下面的所有属性进行一一映射
* 只有这个组件是容器中的组件,才能使用容器提供的功能@ConfigurationProperties
*/
@ConfigurationProperties(prefix = "persen")
@Component
public class Persen {
   private String lastname;
   private Integer age;
   private boolean boss;
   private Date birth;

   private Map<String,Object> maps;
   private List<Object> list;
   private Dog dog;

 

我们可以导入配置文件处理器,以后编写配置就有提示了:

        <!-- 导入配置文件处理器,配置文件进行绑定就会有提示-->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-configuration-processor</artifactId>
           <optional>true</optional>
       </dependency>

1:@value获取值和@ConfigurationProperties获取值比较:

 @ConfigurationProperties@value
功能 批量注入配置文件中的属性 一个个指定
松散绑定(松散语法) 支持 不支持
SpEl 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持

配置文件yml和properties他们都能获取到值;

如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@value;

如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;

 

2:@PropertySource和@ImportResource:

@PropertySource:加载指定的配置文件。

@PropertySource(value = {"classpath:persen.properties"})
@ConfigurationProperties(prefix = "persen")
@Component
public class Persen {

   private String lastname;
   private Integer age;
   private boolean boss;
   private Date birth;

   private Map<String,Object> maps;
   private List<Object> list;
   private Dog dog;

@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效。

Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件也不能自动识别。

想让Spring的配置文件有效,加载进来;把他@ImportResource标致在配置类上。

@ImportResource(locations = {"classpath:beans.xml"})
导入Spring的配置文件让其生效

 

Spring Boot推荐给容器添加组件的方式:推荐使用全注解的方式;

● 使用@Bean给容器中添加组件:

/**
* @Configuration:指明当前类是一个配置类,就是来替代之前的Spring配置文件。
* 在配置文件中用<bean></bean>标签添加组件
*/
@Configuration
public class MyappConfig {

   /**
    *将方法的返回值添加到容器中,容器中这个组件默认的id就是方法名
    */
   @Bean
   public HelloService helloService(){
       return new HelloService();
  }

4:整合SpringData JPA(java持久层API)

1),编写一个实体类(bean)和数据表进行映射,并且配置好映射关系。

/**
* 使用JPA注解配置映射关系
*/
@Entity //告诉JPA这是一个实体类(和数据表映射的类)
@Table(name="u_user") //@Table来指定和那个数据表对应;如果省略,默认表名就是user
public class User {

   @Id //这是一个主键
   @GeneratedValue(strategy= GenerationType.IDENTITY) //自增主键
   private Integer id;

   @Column(name="name",length = 50) //这是和数据表对应的一个列
   private String name;

   @Column //省略默认列名就是属性名
   private String email;
}

2),编写一个Dao接口来操作实体类对应的数据表(Repository);

//继承JpaRepository来完成对数据库的操作
public interface RepositoryDao extends JpaRepository<User, Integer> {
}

3),基本的配置;

spring:
jpa:
  hibernate:
     #更新或者创建数据表结构
    ddl-auto: update
     #在控制台显示sql
  show-sql: true

Hibernate:

1),是一个全自动的ORM,与数据库无关,面向对象的。SpringDateJPA --->封装了Hibernate --->JDKAPI

hibernate 对象有三个状态:

1,瞬时状态 ---> 刚创建出来的Hibernate无任何关联与数据库无任何关联。

2,持久化状态 ---> 被hibernate管理,并且session没有关闭,内存中存在数据库中也存在,如果内存中的数据发送变化会去同步数据库的数据。

3,游离状态 ---> session关闭了,数据库中可能存在。

ORM关系对象映射中:

1),OneToOne。

2),OneToMany(默认使用懒加载)。

3),ManyToOne(默认使用急加载)。

4),ManyToMany(两个oneTomany)。

 


5:Spring-boot启动流程;

几个重要的事件回调机制:

配置在META-INF/spring.factories

ApplicationContextInitializer

ApplicationRunListener

只需要放在ioc容器中

ApplicationRunner

CommandLineRunner

1),创建SpringApplication对象。

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
    //调用此方法创建SpringApplication对象
   public SpringApplication(Object... sources) {
           initialize(sources);
      }

private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
           //保存主配置类
this.sources.addAll(Arrays.asList(sources));
}
       //判断当前是否是web应用
this.webEnvironment = deduceWebEnvironment();
       //从类路径下找到META-INF/Spring.factories配置的所有ApplicationContextInitializer;然后保存起来;
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInit.class));
       //从类路径下找到META-INF/Spring.factories配置的所有ApplicationLtener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
       //从多个配置类中找到有main方法的主配置类
this.mainApplicationClass = deduceMainApplicationClass();
}

2),运行run方法。

    public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
       
       //获取SpringApplicationRunListenners;从类路径下META-INF/spring.factories
SpringApplicationRunListeners listeners = getRunListeners(args);
       //回调所有获取的SpringApplicationRunListenner.starting方法
listeners.starting();
try {
           //封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
           //准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
           //创建环境完成后回调SpringApplicationRunListenners.environmentPrepared()表示环境准备完成
           
Banner printedBanner = printBanner(environment);
//创建ApplicationContext;决定创建web的ioc还是普通的ioc容器。
           context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
         
           
           //准备上下文环境;将environment保存在ioc中;而且applyInitializers();
           //applyInitializers():回调之前保存的所有ApplicationContextInitializer的initialize()方法
           //回调之前保存好的所有SpringApplicationRunListenner的contextPrepared()方法;
           //preparedContext运行完成以后回调所有的SpringApplicationRunListenner的contextLoaded()方法;
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
           
           //刷新容器,ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat);
refreshContext(context);
           
           //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调;
           //ApplicationRunner先回调
afterRefresh(context, applicationArguments);

           //所有的SpringApplicationRunListener回调fineshed()方法;
           listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
           //整个Spring-boot启动完成之后返回启动的ioc容器
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}

6:Spring-Boot高级-消息

1),消息队列主要有两种形式的目的地:

①:队列(queue):点对点消息通信。

点对点式:消息发送者发送消息,消息代理将其放在一个队列中,消息接受者从队列中获取消息内容,消息读取后被移除。

②:主题(topic):发布(publish)/订阅(subscribe)消息通信。

发布订阅式:发布者发送消息到主题,多个订阅者订阅这个主题,那么就会在消息到达时同时收到消息。

2),JMS(Java Message Service)Java消息服务:

基于JVM消息代理的规范。ActiveMQ,HornetMQ是JMS实现。

3),AMQP(Advanced Message Queuing Protocol)高级消息队列协议:

RabbitMQ是AMQP的实现。

JMS和AMQP的区别:

JMS是java的api,不支持跨语言,跨平台,提供了2种消息模型:点对点和发布与订阅。它支持消息类型:文本消息,集合消息,对象消息。

AMQP是网络线级协议,它是支持跨语言,跨平台的,提供了5种消息模型:direct,fanout,topic,headers,system。它只支持二进制消息类型。

Message(消息):

它由消息头和消息体组成的。消息体是不透明的,消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键),priority(相对于其他消息的优先权),delivery-mode(指出该消息可能需要持久性存储)等。

Exchange(交换器):

四种类型:

1),direct:它是根据消息中的路由键派发给指定的一个消息队列,它是完全匹配,单播的模式。

2),Fanout:每个发到fanout交换器的消息都会分到所有绑定的队列上去。

3),Topic:根据路由键的规则模糊匹配有选择性的绑定的队列上去,它同样也会识别两个通配符:“#”和“*”。# 匹配0个或多个单词, * 匹配一个单词。

7:thymeleaf模板

1),后缀是html,也就是可以直接打开,也就是前端人员可以直接参与开发。

2),最终都是后台输出的完整的HTML。

3),后台会替换HTML中的占位符,保留HTML标签,CSS样式,JS代码。

8:配置虚拟路径加拦截器加Swagger2


// 配置虚拟路径
@Configuration
public class WebConfig implements WebMvcConfigurer {

   @Autowired
   private Myinterceptor myinterceptor;


   /**
    * 放行静态资源 或 映射虚拟路径
    */
   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry) {
       
       // Swagger2
       registry.addResourceHandler("/swagger-ui.html")
              .addResourceLocations("classpath:/META-INF/resources/")
              .setCacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic());
       registry.addResourceHandler("/webjars/**")
              .addResourceLocations("classpath:/META-INF/resources/webjars/")
              .setCacheControl(CacheControl.maxAge(1, TimeUnit.HOURS).cachePublic());
       
       // 配置图片虚拟路径
       registry.addResourceHandler("/t/**")
              .addResourceLocations("file:D:/iderUtil/Imgproject_Save/");

       // 放行 static下所有静态资源
       registry.addResourceHandler("/static/**")
              .addResourceLocations("classpath:static/");
  }

   /**
    * 拦截器
    */
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       List<String> list=new ArrayList<>();
       list.add("/static/**");
       list.add("/webjars/**");
       list.add("/swagger-ui.html");
       list.add("/**/swagger-resources/**");
       list.add("/csrf");

           registry.addInterceptor(myinterceptor)
                  .addPathPatterns("/**").excludePathPatterns(list);
  }
}

拦截器类:

@Component
public class Myinterceptor implements HandlerInterceptor {

   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       System.out.println("进入拦截器");
       return false;
  }

   @Override
   public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
       System.out.println("123");
  }

   @Override
   public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
       System.out.println("456");
  }
}

Swagger2类:

@Configuration
@EnableSwagger2
public class Swagger2Config {

   @Bean
   public Docket createRestApi() {
       return new Docket(DocumentationType.SWAGGER_2)
              .apiInfo(apiInfo())
              .select()
               //为当前包路径
              .apis(RequestHandlerSelectors.basePackage("com.djl.springboot"))
              .paths(PathSelectors.any())
              .build();
  }
   //构建 api文档的详细信息函数,注意这里的注解引用的是哪个
   private ApiInfo apiInfo() {
       return new ApiInfoBuilder()
               //页面标题
              .title("面试题查询系统")
               //创建人
              .contact(new Contact("admin","www.rockguide.com","403783154@qq.com"))
               //版本号
              .version("1.0")
               //描述
              .description("面试题查询")
              .build();
  }
}

9:异常处理

@Component
public class MyException implements HandlerExceptionResolver {
   @Override
   public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {

       HandlerMethod handler = (HandlerMethod)o;
       String s = handler.getBean().toString();  // 报错的类名
       String method = handler.getMethod().getName(); //报错的方法名
       System.out.println(s);
       System.out.println(method);
       return new ModelAndView("error.html");
  }
}

10:Cors跨域

    /**
    * 跨域配置
    * @param registry
    */
   @Override
   public void addCorsMappings(CorsRegistry registry) {
       registry.addMapping("//*")
      .allowedMethods("*") //请求方式
      .allowedHeaders("*") //请求头
      .allowedOrigins("*"); // 请求域名
  }

11:JWT加密


public class JWT_Use {
   // 超时时常
   public static final long TIME_OUT = 1000*60*30;
   // 私密令牌
   public static final String SECRET_TOKEN = "djl";

   // 获取Token的值
   public static String getToken(){
       String token = "";
       //过期时间
       Date date = new Date(System.currentTimeMillis() + TIME_OUT);
       //私钥及加密算法
       Algorithm algorithm = Algorithm.HMAC256(SECRET_TOKEN);
       // 设置头的信息
       Map<String,Object> header = new HashMap<>();
       header.put("typ", "JWT_Use");
       header.put("alg", "HS256");

       token = JWT.create().withClaim("Login_UserName","djl")
                          .withClaim("Login_PassWord","111666")
                          .withExpiresAt(date).sign(algorithm);
       return token;
  }

   public static void main(String[] args) {
       String token = JWT_Use.getToken();
       System.out.println(token);
  }

}

 

 

posted on 2020-09-18 13:51  佳林L  阅读(139)  评论(0编辑  收藏  举报