关于SpringBoot的一些使用技巧

SpringBoot的基本使用

SpringBoot四大神器

1. 自动配置

  • 针对很多Spring应用程序和常见的应用功能,SpringBoot能自动提供依赖

2. 起步依赖

  • 高速SpringBoot需要什么功能,他就引入需要的依赖库

3. Actuator

  • 能够深入运行中的SpringBoot应该用程序

4. 命令行界面

  • springboot的可选特性,主要针对Groovy语言使用

SpringBoot的创建方式

  1. 通过IDEA或者Eclipse的spring Initializer创建(需要连网)
  2. 访问http://start.spring.io/创建spring boot的骨架,然后导入Eclipse或者Idea
  3. 手动创建Maven项目,导入以下pom依赖
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.18.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</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>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

SpringBoot运行方式

  • 运行DemoApplication的main方法
  • 打jar包,运行java -jar xxxx.jar即可
  • 通过spring-boot-plugin的方式

SpringBoot参数传递

  • 通过ApplicationArguments对象封装了jvm传递的参数
  • applicationArguments.getNonOptionArgs() // 获取jvm参数

application.properties配置文件

  • 加载优先级(由高到底)

    1. 当前项目/config子目录
    2. 当前项目
    3. classpath:/config目录
    4. classpath目录
  • 默认读取application.properties(最好不要改),修改名字需要在启动时带上–spring.config.name=文件名

  • server.port=8082 修改tomcat启动端口为8082

SpringApplication简介

  • 修改banner,把banner.txt放在resources目录下即可
  • spring.main.banner-mode=off # 不显示banner
  • 启动springboot方式1
    public static void main(String[] args) {
        // SpringApplication.run(DemoApplication.class, args);
        SpringApplication springApplication = new SpringApplication(DemoApplication.class);
        springApplication.run(args);
    }
  • 启动方式2(链式编程)
    public static void main(String[] args) {
        new SpringApplicationBuilder(DemoApplication.class).run(args);
    }

SpringBoot注解

@ConfigurationProperties参数绑定

  • Bean的注入方式
    • 自定义类注入方式
    @Data
    @Component
    @ConfigurationProperties(prefix = "db")
    public class MyDruid {
        private String username;
        private String password;
        private String url;
        private String driverClassName;
    }
    
    • 第三方类注入方式
    @Bean
    @ConfigurationProperties("db")
    public MyDruid MyDruid(){
        return new MyDruid();
    }
    
  • 属性注入的方式
    • 在application.properties中配置
    db.username=123
    db.password=password
    db.url=jdbc:mysql://localhost:3306/druid
    db.driver_class_name=com.mysql.jdbc.Driver
    
    • 通过java命令行参数注入
    • java -jar xxxxx.jar --username=123 password=456 url=abcd driver_class_name
  • 属性注入大写可以换成下划线或者横线

SpringBoot的热部署

  • 导入依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
    <!--option为true表示该依赖不传递到下一个依赖当前项目的项目-->
    
  • 原理
    • SpringBoot重启是reload重启,通过监控classpath的变化,如果,classpath变化,即触发重启。SpringBobasiot通过两个classpath来完成reload,一个basic classloader中加载不变的类,一个restart classloader中加载classpath中的类,充气垫是后,restart classloader中的类丢弃并重新加载;
  • 排除资源
    • spring.devtools.restart.exclude=static/**,templates/**
    • spring.devtools.restart.enabled=false // 禁用自动重启
    • spring.devtools.restart.triggerFile=trigger.file使用triggerfile的重启策略,注意这个文件不要放到default_excludes目录下面

Spring常用工具包

  • spring-boot-starter 核心工具包,提供了自动配置的支持,日志和yaml配置支持
  • spring-boot-starter-activemq 针对快速集成ActiveMQ的工具包
  • spring-boot-starter-aop 提供了快速集成AOP和AspectJ的工具包
  • spring-boot-starter-deta-redis 提供了快速集成Redis和Jedis的工具包
  • spring-boot-starter-fremarker 提供了快速集成Freemarker的工具包
  • spring-boot-start-mail 提供了快速集成右键发送的工具包
  • spring-boot-starter-web 提供了对web开发的工具包,包括基于SpringMVC的Restful应用开发,内置的tomcat服务器等
  • spring-boot-starter-actuator 提供了对生产环境中应用监控的工具包
  • spring-boot-starter-logging 提供了对日志的工具包,默认使用Logback

SpringBoot集成mysql,druid dataSource

  • 导入pom依赖
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>
  • 手动装配dataSource
    @Bean
    @ConfigurationProperties("db")
    public DataSource dataSource(){
        return new DruidDataSource();
    }
    
    db.username=root
    db.password=123456
    db.url=jdbc:mysql:///springboot
    db.driver_class_name=com.mysql.jdbc.Driver
    
  • 自动装配
    spring.datasource.druid.username=root
    spring.datasource.druid.password=123456
    spring.datasource.druid.url=jdbc:mysql:///springboot
    spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.druid.initial-size=5
    

SpringBoot集成Mybaits

  1. 导入依赖
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybais-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>
  1. 配置(可以不要mybatis-cfg.xml文件)

    mybatis.type-aliases-package=com.wyq.test.domain
    mybatis.mapper-locations=classpath:mapper/*.xml
    mybatis.config-location=classpath:conf/mybatis-cfg.xml
    logging.level.com.wyq.test.mapper=debug # sql打印
    
    • Mapper文件放在resources目录中
    • Mapper文件放在java文件中需要在pom中添加如下配置,不然不会编译到classpath目录中(添加到build标签中)
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
    
  2. 在启动类添加扫描Mapper接口注解或者在Mapper接口上添加Mapper注解

    • @MapperScan(“com.wyq.test.mapper”)

SpringBoot集成事务

  • 基于注解的事务管理(推荐)
    1. 在主配置类贴上@EnableTransactionManagement
    2. 在需要事务的Service上贴上@Transactional注解,表示该类下面的所有方法都需要事务
    3. 在不需要事务的方法上贴上 @Transactional(readOnly = true)
  • 基于xml配置(略)

SpringBoot的Web开发

静态资源的加载问题

  • 静态资源加载目录
    • 默认可以是classpath:/META-INF/resources/,classpath:/resources/,classpath:static/,classpath:/public/
  • 指定静态资源加载目录
    spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:static/,classpath:/public/,classpath:/mydir

SpringBoot集成Freemarker

  • Freemarker页面以ftl为后缀
  • SpringBoot对Jsp的支持不好,不建议使用
  • 导包
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
  • 在低版本中freemarker是不开启session的,也就是说前端页面无法获取session中的值
  • 可以通过开启spring.freemarker.expose-session-attributes=true,在高版本中无论是true还是false都支持
  • SpringBoot对freemarker的配置
    1. spring.freemarker.enabled=true 是否开启freemarker支持
    2. spring.freemarkerallow-request-override是否允许request中的属性覆盖model中同名属性,默认是false
    3. spring.freemarker.allow-session-override是否允许session中的属性覆盖model中同名属性,默认是false
    4. spring.freemarke.cacher是否支持模板缓存,默认是false
    5. spring.freemarker.charset=utf-8 模板编码
    6. spring.freemarker.content-type=text/html 模板contenttype
    7. spring.freemarker.expose-request-attributes 是否开启request属性expose,默认是false
    8. spring.freemarker.expose-session-attributes 是否开启session属性expose,默认是false
    9. spring.freemarker.expose-sprong-macro-helpers 是否开启spring的freemarker宏支持,默认为false
    10. spring.freemarker.prefer-file-system-access 默认是true,支持实时检查模板修改
    11. spring.freemarker.prefix 加载模板时候的前缀
    12. spring.freemarker.setting.* 直接配置freemarker参数
    13. spring.freemarker。suffix 模板文件后缀
    14. spring.freemarker.template-loader-path=classpath:/temppates/ 模板加载地址

统一异常处理

  • 统一异常处理类(SpringMVC本来就有的,并不是SpringBoot独有的)
    @ControllerAdvice
    public class ErrorControllerAdvice {
        @ExceptionHandler(Exception.class)
        public void hadlerError(Exception e, HandlerMethod handlerMethod){
            System.out.println("统一异常处理");
            System.out.println(e.getMessage());
            System.out.println("出错的类:" + handlerMethod.getBean().getClass());
            System.out.println("出错的方法:" + handlerMethod.getMethod());
        }
    }
    
  • 统一异常处理页面
    • SpringBoot默认情况下,把所有的错误都重新定位到/error这个处理路径上,有BasicErrorController类完成处理
    • SpringBoot提供了默认的替换错误页面的路径
      src/resources/public/error/404.html
      src/resources/public/error/401.html
      src/resources/public/error/5xx.html
      

SpingBoot集成Servlet,Filter,Listener

  1. 注解方式创建Bean
    • 在启动类添加servlet的注解扫描@ServletComponentScan (启动类的扫描默认扫描当前包及其子包)
  • 手动创建Bean的方式

    @Bean
    public ServletRegistrationBean testServlet(){
        ServletRegistrationBean bean = new ServletRegistrationBean();
        bean.setServlet(new TestServlet());
        bean.addUrlMappings("/testServlet");
        return bean;
    }
    同理:过滤器用:FilterRegistrationBean
         监听器用: ServletListenerRegistrationBean<TestListener>
    

    SpringBoot集成文件上传

    • 与SpringMVC一样
    • 不同的是需要先给一个存储文件的绝对路径,因为没有webapp目录,只能通过配置文件注入进来
    @Value("${file.path}")
    private String path;
    @RequestMapping("/upload")
    @ResponseBody
    public String upload(MultipartFile file) throws IOException{
        String fileName = UUID.randomUUID() + file.getOriginalFilename();
        FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(new File(path + fileName)));
        return "上传成功";
    }
    

    SpringBoot注册拦截器

    1. 创建自定义拦截器类
    public class MyInterceptor extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("MyInterceptor preHandle 拦截器");
            return true;
        }
    }
    
    1. 改写启动类(让它继承WebMvcConfigurerAdapter)
    public class TestApplication extends WebMvcConfigurerAdapter {
        @Override
        // 注册拦截器的方法
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(myInterceptor()).addPathPatterns("/*");
        }
    
        @Bean
        // 创建拦截器的Bean
        public MyInterceptor myInterceptor(){
            return new MyInterceptor();
        }
        
        public static void main(String[] args) {
            SpringApplication.run(TestApplication.class, args);
        }
    
    }
    

SpringBoot集成Redis

  1. 导入依赖
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
</dependency>
  1. 在application.properties中配置连接信息
# Redis
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=1
spring.redis.timeout=0
  1. 创建相关Bean(Redis的template)
@Bean
public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
    CacheManager cacheManager = new RedisCacheManager(redisTemplate);
    return cacheManager;
    /*RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
    // 多个缓存的名称,目前只定义了一个
    rcm.setCacheNames(Arrays.asList("thisredis"));
    //设置缓存默认过期时间(秒)
    rcm.setDefaultExpiration(600);
    return rcm;*/
}
// 以下两种redisTemplate自由根据场景选择
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);

    //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
    Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);

    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    serializer.setObjectMapper(mapper);

    template.setValueSerializer(serializer);
    //使用StringRedisSerializer来序列化和反序列化redis的key值
    template.setKeySerializer(new StringRedisSerializer());
    template.afterPropertiesSet();
    return template;
}
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
    StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
    stringRedisTemplate.setConnectionFactory(factory);
    return stringRedisTemplate;
}
  1. 操作Redis,redis与数据库配合实现增删改查

    • 用代码的方式
    package com.wyq.test.service.impl;
    
    import com.wyq.test.mapper.UserMapper;
    import com.wyq.test.pojo.User;
    import com.wyq.test.service.UserService;
    import com.wyq.test.util.RedisKeyPrefix;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserMapper userMapper;
        @Resource
        private RedisTemplate<String, User> redisTemplate;
    
        @Override
        public List<User> selectAllUser() {
            List<User> users = userMapper.selectAllUser();
            return users;
        }
    
        @Override
        public int addUser(User user) {
            return userMapper.addUser(user);
        }
    
        @Override
        public int deleteById(long id) {
            // 缓存存在,删除缓存
            String key = "user_" + id;
            boolean hasKey = redisTemplate.hasKey(key);
            if (hasKey) {
                redisTemplate.delete(key);
                System.out.println("删除用户时候,从缓存中删除用户 >> " + id);
            }
            return userMapper.deleteById(id);
        }
    
        @Override
        public int update(User user) {
            long userId = user.getId();
            // 缓存存在,删除缓存
            String key = "user_" + userId;
            boolean hasKey = redisTemplate.hasKey(key);
            if (hasKey) {
                redisTemplate.delete(key);
                System.out.println("更新用户时候,从缓存中删除用户 >> " + userId);
            }
            return userMapper.update(user);
        }
    
        @Override
        public User selectOne(long id) {
            String key = RedisKeyPrefix.USER + id;
            // 缓存存在
            boolean hasKey = redisTemplate.hasKey(key);
            if (hasKey) {
                User user = redisTemplate.opsForValue().get(key);
                System.out.println("从缓存中查");
                return user;
            }
            // 从数据库取,并存回缓存
            User user = userMapper.findOne(id);
            System.out.println("从数据库查");
            // 放入缓存,并设置缓存时间
            redisTemplate.opsForValue().set(key, user, 600, TimeUnit.SECONDS);
            return user;
        }
    }
    
    
    • 用注解的方式
     // 从redis中删除该用户并把数据库中的一起删除
    @CacheEvict(value="thisredis", key="'user:'+#id",condition="#id!=1")
    public int deleteById(long id) {
        System.out.println("从数据库删除user,并删除缓存中数据");
        return userMapper.deleteById(id);
    }
    
    // 从缓存中删除该用户,下次再查询时重新从数据库查,然后再更新到redis
    @CacheEvict(value="thisredis", key="'user:'+#id")
    public int update(User user) {
        return userMapper.update(user);
    }
    
    // 第一次从数据库查,保存到redis中,以后从redis中查
    @Cacheable(value="thisredis", key="'user:'+#id")
    public User selectOne(long id) {
        User user = userMapper.findOne(id);
        System.out.println("缓存中没有,从数据库查");
        return user;
    }
    
  2. 在启动类贴上@EnableCaching // 开启springboot中的缓存

SpringBoot整合RabbitMQ

  1. 导入依赖
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    
  2. 配置虚拟主机,连接等信息
    # rabbitmq
    spring.rabbitmq.host=127.0.0.1
    spring.rabbitmq.port=5672
    spring.rabbitmq.username=wyq
    spring.rabbitmq.password=123456
    spring.rabbitmq.publisher-confirms=true
    spring.rabbitmq.virtual-host=/
    
  3. 创建队列的Bean
    @Configuration
    public class SenderConf {
        @Bean
        public Queue queue() {
            return new Queue("queue");
        }
    }
    
  4. 创建生产者与消费者
    1. Direct 直接模式(默认的模式)

      @Autowired
      private AmqpTemplate template;
      @Override
      // 生产user
      public void addUser(User user) {
          System.out.println("把user保存到rabbitMQ中");
          template.convertAndSend("queue",user);
      }
      
      @Override
      // 监听并消费user
      @RabbitListener(queues="queue")
      public void getUserSaveInDB(User user) {
          System.out.println("从rabbitmq中取出数据并保存到数据库:" + user);
          userMapper.addUser(user);
      }
      
      
    2. Fanout Exchange 广播模式

      1. 创建多个队列
        @Bean(name="Amessage")
        public Queue AMessage() {
            return new Queue("fanout.A");
        }
        
        @Bean(name="Bmessage")
        public Queue BMessage() {
            return new Queue("fanout.B");
        }
        
        @Bean(name="Cmessage")
        public Queue CMessage() {
            return new Queue("fanout.C");
        }
        
      2. 创建1个FanoutExchange交换机
        @Bean
        FanoutExchange fanoutExchange() {
            return new FanoutExchange("fanoutExchange");//配置广播路由器
        }
        
      3. 将多个队列与这个交换机绑定
        @Bean
        Binding bindingExchangeA(@Qualifier("Amessage") Queue AMessage,FanoutExchange fanoutExchange) {
            return BindingBuilder.bind(AMessage).to(fanoutExchange);
        }
        
        @Bean
        Binding bindingExchangeB(@Qualifier("Bmessage") Queue BMessage, FanoutExchange fanoutExchange) {
            return BindingBuilder.bind(BMessage).to(fanoutExchange);
        }
        
        @Bean
        Binding bindingExchangeC(@Qualifier("Cmessage") Queue CMessage, FanoutExchange fanoutExchange) {
            return BindingBuilder.bind(CMessage).to(fanoutExchange);
        }
        
      4. 创建三个监听来监听消费这三个队列
        @RabbitListener(queues="fanout.A")
        public void processA(String str1) {
            System.out.println("ReceiveA:"+str1);
        }
        @RabbitListener(queues="fanout.B")
        public void processB(String str) {
            System.out.println("ReceiveB:"+str);
        }
        @RabbitListener(queues="fanout.C")
        public void processC(String str) {
            System.out.println("ReceiveC:"+str);
        }
        
      5. 创建生产者并测试
        @Test
        public void testRabbitFanout() {
            template.convertAndSend("fanoutExchange", "", "发送的消息");
        }
        
    3. Topic转发模式

      1. 创建队列
        @Bean(name="topicQueue1")
        public Queue topicQueue1() {
            return new Queue("topic.queue1");
        }
        
        @Bean(name="topicQueue2")
        public Queue topicQueue2() {
            return new Queue("topic.queue2");
        }
        
        
      2. 创建交换机
        @Bean
        public TopicExchange exchange() {
            return new TopicExchange("exchange");
        }
        
      3. 绑定
        @Bean
        Binding bindingExchangeMessage(@Qualifier("topicQueue1") Queue topicQueue1, TopicExchange exchange) {
            return BindingBuilder.bind(topicQueue1).to(exchange).with("topic.queue1");
        }
        
        @Bean
        Binding bindingExchangeMessages(@Qualifier("topicQueue2") Queue topicQueue2, TopicExchange exchange) {
            return BindingBuilder.bind(topicQueue2).to(exchange).with("topic.#");//*表示一个词,#表示零个或多个词
        }
        
      4. 创建监听
        @RabbitListener(queues="topic.queue1")    //监听器监听指定的Queue
        public void process1(String str) {
            System.out.println("queue1:"+str);
        }
        @RabbitListener(queues="topic.queue2")    //监听器监听指定的Queue
        public void process2(String str) {
            System.out.println("queue2:"+str);
        }
        
      5. 创建生产者并测试
        @Test
        public void testRabbitTopic() {
            template.convertAndSend("exchange", "topic.queue1", "hello rabbitmq topic");
        }
        

SpringBoot整合Shiro

SpringBoot整合lucene

猜你喜欢

转载自blog.csdn.net/wangyanqun2017/article/details/85854330
今日推荐