zoukankan      html  css  js  c++  java
  • SpringBoot 进阶

    SpringBoot配置文件

    YML

    YAML (YAML Ain't a Markup Language)YAML不是一种标记语言,通常以.yml为后缀的文件,是一种直观的能够被电脑识别的数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持YAML库的不同的编程语言程序导入,一种专门用来写配置文件的语言。

    YML是代替XML的最优解决方案,语法简洁,清晰易读,跨平台性和扩展性良好好,可以表达复杂的数据结构;

    基本语法:

    1.数据以key: value键值对的形式存储

    需要强调的是冒号后面必须有一个空格

    name: jerry
    

    2.不区分数据类型

    name: jerry
    age: 18
    

    3.使用缩进来表示作用域,相同缩进的键值对处于同一个级别

    student:
    	name: jerry
    	age: 18
    

    4.[]表示数组或集合

    numbser: [1,2,3,4]
    

    5.{}可以在同一行书写map/对象

    maps: {key1: value1,key2: value2}
    

    6.数组和字典中的元素也可以使用 - 来分隔到多行

    #字符数组/list:
    hobby:
      - game
      - music
    #存储map/对象的 数组/list:
      dogs:
        - name: 阿花
        	age: 1
        - name: 啊丑
        	age: 2
        - {name: 啊啊,age: 3}
    

    7.日期

    birthday: 2020/12/12 10:10:10
    

    8.文档块,可在同一个文件中编写两份不同的配置

    server:
      port: 8081
    spring:
      profiles:
        active: prod #激活对应的文档块
    
    ---
    server:
      port: 8083
    spring:
      profiles: dev #指定属于哪个环境
    
    ---
    server:
      port: 8084
    spring:
      profiles: prod  #指定属于哪个环境
    

    案例:

    java类:

    public class Person {
        private String name;
        private int age;
        private String[] hobby;
        private HashSet<String> gfs;
        private Map<String,String> maps;
        private Dog dog;
        private List<Dog> dogs;
        private Date birth;
        public Date getBirth() {
            return birth;
        }
    }
    class Dog {
        private String name;
    }
    

    yml:

    person:
      name: jerry
      age: 18
      hobby: #[game,music]
        - game
        - music
      gfs: [a,b,c]
      maps: {key1: value1,key2: value2}
      #maps:
       # key1: value1
        #key2: value2
      dog:
        name: 大黄
      dogs:
        - name: 阿花
          age: 18
        - name: 啊丑
          age: 20
      birth: 2020/12/12 23:56:10
    

    获取配置信息

    1.当容器中的bean需要使用配置文件中的内容时,可以使用@Value注解:当然要保证该类的Bean以及加入容器

    @Value("${myname}")
    private String myname;
    

    2.当有很多属性都要注入到Bean中时可以采用@ConfigurationProperties注解,SpringBoot会按照属性名称进行注入,注意:必须提供set方法

    @Component
    //perfix指定要映射的key名称  与配置文件中对应
    @ConfigurationProperties(prefix = "person")
    public class Person {
    
        private String name;
        private int age;
    	  public String getName() {return name;}
        public void setName(String name) {this.name = name;}
        public int getAge() {return age;}
        public void setAge(int age) {this.age = age;}
    }
    

    切换配置文件

    在项目开发过程中我们为了不影响线上数据,通常会使用一套专门用于开发阶段的配置,在编写完成后再切换到线上配置比如redis,zookeeper,数据库等等,SpringBoot可以帮助我们轻松实现配置文件的切换;

    配置文件的命名:

    根据不同使用场景,创建格式为application-环境标识.yml(/properties)的配置文件,例如:

    application-dev.yml

    application-prod.yml

    指定要使用的配置文件

    方式一:

    创建名为application-dev.yml的配置文件,SpringBoot默认会读取该文件,在文件中指定要使用的配置文件信息:

    spring:
    	profiles:
      	active: dev  #dev即为环境标识
    

    方式二

    不需要创建默认的application.yml,而是在运行程序时通过参数来指定要使用的配置文件

    • 通过java虚拟机参数:
    java -jar -Dspring.profiles.active=prod  /Users/jerry/IdeaProjects/SpringBootDemo/target/SpringBootDemo-1.0-SNAPSHOT.jar
    
    • 也可以通过Springboot参数指定:
    java -jar /Users/jerry/IdeaProjects/SpringBootDemo/target/SpringBootDemo-1.0-SNAPSHOT.jar --spring.profiles.active=prod  
    

    注意:使用该方式则必须在引导类中将获取的命令行参数传递给SpringBoot

    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            //args 即为命令行参数
            SpringApplication.run(Application.class,args);
        }
    }
    

    常见配置项:

    # ----------------------------------------
    # WEB PROPERTIES
    # ----------------------------------------
    # EMBEDDED SERVER CONFIGURATION (ServerProperties)
    server.port=8080 # Server HTTP port.
    server.servlet.context-path= # Context path of the application.
    server.servlet.path=/ # Path of the main dispatcher servlet.
    # HTTP encoding (HttpEncodingProperties)
    spring.http.encoding.charset=UTF-8 # Charset of HTTP requests and responses.
    Added to the "Content-Type" header if not set explicitly.
    # JACKSON (JacksonProperties)
    spring.jackson.date-format= # Date format string or a fully-qualified date
    format class name. For instance, `yyyy-MM-dd HH:mm:ss`.
    # SPRING MVC (WebMvcProperties)
    spring.mvc.servlet.load-on-startup=-1 # Load on startup priority of the
    dispatcher servlet.
    spring.mvc.static-path-pattern=/** # Path pattern used for static resources.
    spring.mvc.view.prefix= # Spring MVC view prefix.
    spring.mvc.view.suffix= # Spring MVC view suffix.
    # DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
    spring.datasource.driver-class-name= # Fully qualified name of the JDBC driver.
    Auto-detected based on the URL by default.
    spring.datasource.password= # Login password of the database.
    spring.datasource.url= # JDBC URL of the database.
    spring.datasource.username= # Login username of the database.
    # JEST (Elasticsearch HTTP client) (JestProperties)
    spring.elasticsearch.jest.password= # Login password.
    spring.elasticsearch.jest.proxy.host= # Proxy host the HTTP client should use.
    spring.elasticsearch.jest.proxy.port= # Proxy port the HTTP client should use.
    spring.elasticsearch.jest.read-timeout=3s # Read timeout.
    spring.elasticsearch.jest.username= # Login username.
    

    参考官网:去看看

    SpringBoot中Redis的使用

    添加起步依赖

    <!-- 配置使用redis启动器 --> 
    <dependency>
    		<groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    

    配置redis信息

    • 单机

      spring:
        redis:
          host: 10.211.55.6
          port: 6379
          #Sprin boot 默认使用的是lettuce作为redis客户端,使用异步IO,且线程安全
          lettuce:
            pool:
              max-active: 10
              max-idle: 5
      #连接池不是必须的配置项,基础配置只需要host和port即可
      
    • 集群

      spring:
        redis:
          cluster:
            nodes: 10.211.55.6:6379,10.211.55.6:6380,10.211.55.6:6381,10.211.55.6:6382,10.211.55.6:6383,10.211.55.6:6384
      #节点之间使用逗号隔开
      

    数据读写案列

    @Service
    public class UserServiceImpl implements UserService {
    
        @Autowired
        StringRedisTemplate redisTemplate;
    
        @Autowired
        UserMapper mapper;
    
        @Autowired
        ObjectMapper objectMapper;//用于json序列化
    
        @Override
        public List<User> getAll() {
            try {
                //从redis获取数据
                String users_json = redisTemplate.opsForValue().get("users");
                //如果存在则直接返回
                if (users_json != null && users_json.length() > 0){
                    System.out.println("缓存数据.......");
                    CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(List.class, User.class);
                    return objectMapper.readValue(s, collectionType);
                }else{
                    //不存在则查询数据库
                    List<User> users = mapper.selectUserList();
                    //并放入redis
                    redisTemplate.opsForValue().set("users",objectMapper.writeValueAsString(users));
                    //返回
                    return users;
                }
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return mapper.selectUserList();
        }
    }
    

    请求测试:http://localhost:8080/user/list,可以看到输出缓存数据表示redis已正常工作

    事务管理

    涉及数据库的操作就免不了事务,在ssm项目中我们需要配置事务管理器等相关信息,这写配置但多数情况下也都是差不多的,所以在SpringBoot中,我们不需要编写任何的配置信息,只要在需要进行事务管理的方法上添加事务注解即可

    事务测试案例:

    @Service
    public class UserServiceImpl implements UserService {
      @Override
      @Transactional(propagation = Propagation.REQUIRED)
      public void updateUser(){
          User user = mapper.selectUserById(1);
          user.setUsername("JERRY1");
          mapper.updateByPrimaryKey(user);
          int i = 1/0;
      }
    }
    

    若不生效可在引导类上添加@EnableTransactionManagement注解

    @EnableTransactionManagement
    public class Application {
        public static void main(String[] args) {
            //启动Spring boot 需要指定引导类
            SpringApplication.run(Application.class,args);
        }
    }
    

    日志配置

    当我们加入了web的起步依赖后,SpringBoot就已经自动的配置了日志了,其默认使用的是slf4j+logback,并将日志直接输出到控制台,一些情况下我们需要自己来修改日志的一些参数,如级别,输出位置等;

    日志的起步依赖:当然这不需要我们自己添加,SpringBoot已经有了

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-logging</artifactId>
    </dependency>
    

    输出日志

    @Controller
    public class UserController {
        //获取一个logger
        private Logger logger = LoggerFactory.getLogger(getClass());
        
        @Autowired
        UserService service;
    
        @RequestMapping("/show")
        public String showList(Model model){
            logger.info("request path:/show");
            logger.info("request path:/show");
            logger.debug("request path:/show");
            logger.warn("request path:/show");
    
            List<User> all = service.getAll();
            model.addAttribute("userList",all);
            return "userlist";
        }
    }
    

    简单配置

    logging:
      level:
        root: info  # rootLogger的级别
        com.kkb.controller: debug  #某个包的日志级别
      file:
        path: ./logs/  #日志输出目录
        max-size: 1GB #文件大小
        max-history: 5 #文件个数
      pattern:
        console: "%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger-%msg哈哈哈哈%n"
    

    切换至log4j

    logback的配置文件基本上和log4j差不多,但仍然有一些差别,当我们需要对日志进行详细的定制时无疑会增加我们的学习成本,推荐直接使用log4j,单从对比数据上来看log4j更有优势;

    使用前需要先将原本的logback依赖排除掉,然后添加log4f的依赖

    添加依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>
    
    <!--找到spring-web的起步依赖 排除logback-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <exclusions>
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    

    在resources下提供log4j2.xml日志配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
        <!--自定义属性信息-->
        <properties>
            <property name="LOG_HOME">logs</property>
            <property name="FILE_NAME">applog</property>
        </properties>
        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            </Console>
            <!--滚动日志配置
                filePattern用于设置滚动文件的命名规则
                            若以.zip为结尾则会自动归档日志文件 也支持其他的格式.gz, .zip, .bz2, 等-->
            <RollingRandomAccessFile name="RollingAppender"
                                     fileName="${LOG_HOME}/${FILE_NAME}.log"
                                     filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd HH-mm}-%i.log">
                <PatternLayout
                        pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
                <Policies>
                    <!--滚动时间间隔 该参数需结合filePattern中的时间格式 此时表示为1分钟更换一个新文件
                        若时间格式为%d{yyyy-MM-dd HH}则表示每小时更换一个新文件-->
                    <TimeBasedTriggeringPolicy interval="1"/>
                    <!--单个日志文件最大容量                -->
                    <SizeBasedTriggeringPolicy size="1 MB"/>
                </Policies>
                <!--最大保留的日志文件个数  默认为7个          -->
                <DefaultRolloverStrategy max="20"/>
            </RollingRandomAccessFile>
        </Appenders>
        <Loggers>
            <Root level="info">
                <AppenderRef ref="Console"/>
            </Root>
            <Logger name="com.kkb.controller" level="debug">
                <AppenderRef ref="RollingAppender"/>
                <AppenderRef ref="Console"/>
            </Logger>
        </Loggers>
    </Configuration>
    

    若名称不是默认的log42.xml则可以在springboot中添加配置来指定:

    logging:
      config: classpath:log4j3.xml
    

    Handler拦截器

    还记得拦截器是用来干什么的吗,它在什么时候执行?

    在web-mvc中我们已经认识了拦截器,它可以在一个请求到达Handler处理之前对请求进行拦截,从而可以轻松的实现权限控制,登录认证等功能;

    定义拦截器:

    public class LogginInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("拦截器执行..................");
            if (request.getRequestURI().contains("login")){
                return true;
            }
    
            if (request.getSession().getAttribute("user") == null){
                response.sendRedirect("/login.html");
                return false;
            }
            return true;
        }
    }
    

    控制器添加代登录接口和登录页面

    @RequestMapping("/login")
    public String userLogin(User user, HttpSession session){
      User u = service.userLogin(user);
      if (user.getUsername().equals("jerry") && user.getPassword().equals("123")){
        session.setAttribute("user",user);
        return "redirect:/show";
      }
      return "redirect:/login.html";
    }
    
    @RequestMapping("/login.html")
    public String getage(){
      return "login";
    }
    

    创建mvc配置类添加自定义的拦截器

    @Configuration
    public class MyConfigruation implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LogginInterceptor()).addPathPatterns("/**");
        }
    }
    

    异常处理

    webmvc中异常处理采用的是AOP,我们只需要提供用于处理异常的通知即可

    定义异常处理通知:

    @ControllerAdvice //异常处理使用的是AOP 所以处理逻辑 将做为通知被织入
    public class GlobalExceptionHandler {
        //日志记录器
        private Logger logger = LoggerFactory.getLogger(getClass());
        //指定该方法可以处理的异常类型
        @ExceptionHandler(Exception.class)
        //model 用于向错误页面传递数据
        public String defaultHandler(Model model,Exception e){
            model.addAttribute("error",e.getMessage());//添加错误信息
            logger.error(e.getMessage(),e);//输出到日志
            return "error";//跳转error.html
        }
    }
    

    提供一个错误页面:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>系统错误</h1>
    原因:<span th:text="${error}" style="color:red"/>
    </body>
    </html>
    

    SpringBoo工程的打包

    在pom中添加SpringBoot的maven插件,这将使得maven打包时会将所有依赖的jar包全部打包,形成一个fat jar,这样一来只要有java环境就能运行工程了,不需要在配置相关的依赖;

    添加插件:

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <fork>true</fork>
        </configuration>
    </plugin>
    

    执行命令:

    #cd到工程根目录下:
    mavem package
    #打包前会先执行项目中的所有单元测试,若不需要运行测试可以使用以下参数跳过测试直接打包
    maven -DskipTests package
    

    运行打包好的项目:

    #打包完成后会在项目根目录下生产target目录,里面就包含了打包完的jar,进入target后执行以下命令即可
    java -jar ./target/SpringBootDemo-1.0-SNAPSHOT.jar
    

    整合Dubbo

    服务提供方和消费方依然是独立的项目,各自管理自己的依赖关系,然后抽取公共部分

    创建工程:

    | common (空的maven)
    	| HelloService
    | provider (dubbo + SpringBot)
    	| HelloServiceImpl
    | consumer (dubbo + SpringBot + webMVC)
    	| HelloController
    

    服务提供方:

    pom文件:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.11</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    

    实现类:

    @Service //注意 要使用dubbo提供的Service注解
    public class HelloServiceImpl implements HelloService {
        @Override
        public String sayHello(String name) {
            return "hello "+name;
        }
    }
    

    配置文件:

    dubbo:
      application:
        name: my-provider
        qos-enable: false
      registry:
        protocol: zookeeper
        address: 10.211.55.5:2182
      protocol:
        name: dubbo
        port: 21888
    

    引导类:

    @SpringBootApplication
    @EnableDubbo
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class,args);
        }
    }
    

    消费方:

    pom文件:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.11</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    

    控制器:

    @RestController
    public class HeolloController {
    
        @Reference
        HelloService helloService;
    
        @RequestMapping("/test/{name}")
        public String serviceTest(@PathVariable String name){
            return helloService.sayHello(name);
        }
    }
    

    配置文件:

    dubbo:
      application:
        name: my-consumer
        qos-enable: false
      registry:
        protocol: zookeeper
        address: 10.211.55.5:2182
        #集群写法 address: zookeeper://192.168.50.132:2181?backup=192.168.50.133:2181,192.168.50.134:2181
    

    引导类:

    @SpringBootApplication
    public class ConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class,args);
        }
    
    }
    

    访问测试:http://localhost:8080/test/jerry

    页面输出名字即访问成功

    Dubbo的pom文件和普通的SpringBoot略微不同,不用指定parent

  • 相关阅读:
    常用验证函数isset()/empty()/is_numeric()函数
    jquery select取option的value值发生变化事件
    (转)浅谈HTML5与css3画饼图!
    文本框输入值文字消失常用的两种方法
    简洁的滚动代码(上下滚动)
    (转)PHP的语言结构和函数的区别
    兼容ie7的导航下拉菜单
    jquery中each()函数
    tomcat源码导入eclipse
    weblogic linux环境下新建domain
  • 原文地址:https://www.cnblogs.com/yangyuanhu/p/12527907.html
Copyright © 2011-2022 走看看