SpringBoot进阶(二)

(一)SpringBoot搭建web项目三部曲(搭建环境jdk1.8,maven,IDEA2017)

(1)将pom文件导入相关starter(相关jar包)。

(2)编写mvc业务层代码。

(3)根据不同的部署方式编写启动类。

(+1)SpringBoot启动加载数据在实际应用中,我们会有在项目服务启动的时候就去加载一些数据或者一些事情这样的需求,为了解决这样的问题,SpringBoot为我们提供了一个方法,通过实现接口CommandLineRunner来实现。

(二)SpringBoot整合mybatis两点说明:

(1)通过@MapperScan将dao层放入spring容器。

(2)通过application.properties通过mybatis.mapperLocations属性将相关mapper.xml放入spring容器。

(三)SpringBoot常用注解解释

(1)@SpringBootApplication 标明这是一个SpringBoot应用程序,等价于以默认属性使用@Configuration,@EnableAutoConfiguration和@ComponentScan。

@ComponentScan 类似于xml配置中的<context:component-scan>。

@EnableAutoConfiguration自动装配,根据依赖的jar包来自动状态,自动操作一些行为。

@ComponentScan类似于xml配置文件

(2)@RestController 返回json字符串的数据,直接可以编写RESTFul的接口,@ResponseBody和@Controller的合集。

(3)@PathVariable 当使用@RequestMapping URI template 样式映射时,即 someUrl/{paramId}, 
这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。

(4)@ComponentScan 表示将该类自动发现(扫描)并注册为Bean,可以自动收集所有的Spring组件, 
包括@Configuration类。我们经常使用@ComponentScan注解搜索beans,并结合@Autowired注解导入。 
如果没有配置的话,Spring Boot会扫描启动类所在包下以及子包下的使用了@Service,@Repository等注解的类。

(5)@ServletComponentScan spring能够扫描到自己编写的servlet和filter, 
SpringBootApplication 上使用@ServletComponentScan注解后,Servlet、Filter、Listener, 
可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。

(6)@Repository、@Service、@Controller,它们分别对应存储层 Bean,业务层 Bean,和展示层 Bean,将类标识为 Bean; 

分别用于软件系统的不同层次: 
@Component 是一个泛化的概念,仅仅表示一个组件 (Bean) ,可以作用在任何层次。 
@Service 通常作用在业务层,但是目前该功能与 @Component 相同。 
@Constroller 通常作用在控制层,但是目前该功能与 @Component 相同。 
通过在类上使用 @Repository、@Component、@Service 和 @Controller注解,Spring会自动创建相应的 BeanDefinition 对象, 
并注册到 ApplicationContext 中。这些类就成了 Spring 受管组件。这三个注解除了作用于不同软件层次的类, 
其使用方式与 @Repository 是完全相同的。

(7)@Scope(“prototype”) Spring默认产生的bean是单例的,”prototype” 表示原型即每次都会new一个新的出来。

(8)@Bean标注在方法上(返回某个实例的方法),作用为注册bean对象 

@Bean注解在返回实例的方法上,如果未通过@Bean指定bean的名称,则默认与标注的方法名相同;

@Bean注解默认作用域为单例singleton作用域,可通过@Scope(“prototype”)设置为原型作用域;

既然@Bean的作用是注册bean对象,那么完全可以使用@Component、@Controller、@Service、@Ripository等 
注解注册bean,当然需要配置@ComponentScan注解进行自动扫描。

(9)@RequestHeader 可以把Request请求header部分的值绑定到方法的参数上如(@RequestHeader("Accept-Encoding") String encoding){}。

(10)@Transactional注解

rollbackFor 表示当该方法中抛出指定的异常时数据回滚。

dontRollbackOn 表示当该方法中抛出指定的异常时数据不回滚。

(11)@Resource、@Autowired、@Qualifier 区别

@Resource和@Autowired都可以来完成注入依赖,但它们之间是有区 别的: 
1. @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入; 
2. @Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用; 
3. @Resource注解是又J2EE提供,而@Autowired是由Spring提供,故减少系统对spring的依赖建议使用@Resource的方式; 
4. @Resource和@Autowired都可以书写标注在字段或者该字段的setter方法之上。

(四)SpringBoot整合swagger自动生成接口文档

(1)使用swagger,首先在pom中引入jar依赖。

<dependency>
           <groupId>io.springfox</groupId>
           <artifactId>springfox-swagger2</artifactId>
           <version>2.2.2</version>
        </dependency>
        <dependency>
           <groupId>io.springfox</groupId>
           <artifactId>springfox-swagger-ui</artifactId>
           <version>2.2.2</version>
</dependency>

(2)添加swagger配置文件(创建配置类),引入@EnableSwagger2来启动swagger注解.

package cn.enjoy.config;


import io.swagger.models.Contact;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket api(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .pathMapping("/")
                .select()
                .paths(PathSelectors.regex("/.*"))
                .build();
    }
    private ApiInfo apiInfo(){
        return  new ApiInfoBuilder().title("Spring Boot 中使用Swagger2构建RESTful AIPS")
                .description("更过SpringBoot相关文章请关注:https://blog.csdn.net/csdnyzj")
                .termsOfServiceUrl("https://blog.csdn.net/csdnyzj")
                .contact("程序猿YZJ")
                .version("1.0")
                .build();

    }

}

(3)编写测试controller

package cn.enjoy.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/restful")
@Api("RestfulController相关api")
public class RestfulController {

    @RequestMapping("/boot/user/{id}/{name}")
    @ApiOperation(value="测试restful风格接口", httpMethod = "GET",response = String.class,notes="根据url的id和name进行相关测试")
    public Object testRestful(@PathVariable("id") int id,@PathVariable("name") String name ){
        return "id="+id+"name="+name;
    }
}

注解说明:

  • @Api:用在类上,说明该类的作用
  • @ApiOperation:用在方法上,说明方法的作用
  • @ApiImplicitParams:用在方法上包含一组参数说明
  • @ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
    • paramType:参数放在哪个地方
      • header-->请求参数的获取:@RequestHeader
      • query-->请求参数的获取:@RequestParam
      • path(用于restful接口)-->请求参数的获取:@PathVariable
      • body(不常用)
      • form(不常用)
    • name:参数名
    • dataType:参数类型
    • required:参数是否必须传
    • value:参数的意思
    • defaultValue:参数的默认值
  • @ApiResponses:用于表示一组响应
  • @ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
    • code:数字,例如400
    • message:信息,例如"请求参数没填好"
    • response:抛出异常的类
  • @ApiModel:描述一个Model的信息(这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述的时候)
    • @ApiModelProperty:描述一个model的属性

(4)启动SpringBoot项目,访问 http://localhost:8080/swagger-ui.html

(五)SpringBoot整和Redis集群

 (1)添加redis依赖;

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-redis</artifactId>
      <version>1.4.7.RELEASE</version>
    </dependency>

(2)在application.properties添加配置信息

         # Redis服务器地址

         #spring.redis.host=10.100.50.23

         # Redis服务器连接端口

         #spring.redis.port=6379

         # Redis服务器连接密码(默认为空)

         spring.redis.password=

          # 连接池最大连接数(使用负值表示没有限制)

          spring.redis.pool.max-active=8

          # 连接池最大阻塞等待时间(使用负值表示没有限制)

          spring.redis.pool.max-wait=-1

          # 连接池中的最大空闲连接

          spring.redis.pool.max-idle=8

          # 连接池中的最小空闲连接

          spring.redis.pool.min-idle=0

          # 连接超时时间(毫秒)

          spring.redis.timeout=0

          spring.redis.commandTimeout=5000

          # redis.cluster

         spring.redis.cluster.nodes=10.100.50.23:6380,10.100.50.23:6381,10.100.50.23:6382,10.100.50.23:6383,10.100.50.23:6384,10.100.50.23:6385

         (3)编写redis配置类     

          import com.fasterxml.jackson.annotation.JsonAutoDetect;

         import com.fasterxml.jackson.annotation.PropertyAccessor;

         import com.faste   rxml.jackson.databind.ObjectMapper;

         import org.springframework.beans.factory.annotation.Value;

         import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

         import org.springframework.context.annotation.Bean;

         import org.springframework.context.annotation.Configuration;

         import org.springframework.data.redis.connection.RedisConnectionFactory;

         import org.springframework.data.redis.core.RedisTemplate;

         import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

         import org.springframework.data.redis.serializer.StringRedisSerializer;

         import redis.clients.jedis.HostAndPort;

         import redis.clients.jedis.JedisCluster;

         import redis.clients.jedis.JedisPoolConfig;

         import java.net.UnknownHostException;

         import java.util.HashSet;

         import java.util.Set;

         @Configuration

         @ConditionalOnClass({JedisCluster.class})

         public class RedisConfig {

         @Value("${spring.redis.cluster.nodes}")

         privateString clusterNodes;

         @Value("${spring.redis.timeout}")

          private inttimeout;

         @Value("${spring.redis.pool.max-idle}")

          private intmaxIdle;

          @Value("${spring.redis.pool.max-wait}")

          private longmaxWaitMillis;

          @Value("${spring.redis.commandTimeout}")

          private intcommandTimeout;

          @Bean

          publicJedisCluster getJedisCluster() {

           String[] cNodes = clusterNodes.split(",");

           Set<HostAndPort> nodes =new HashSet<>();

           //分割出集群节点

           for(String node : cNodes) {

              String[] hp = node.split(":");

              nodes.add(newHostAndPort(hp[0],Integer.parseInt(hp[1])));

          }

          JedisPoolConfig jedisPoolConfig =new JedisPoolConfig();

          jedisPoolConfig.setMaxIdle(maxIdle);

          jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);

          //创建集群对象

          // JedisCluster jedisCluster = new JedisCluster(nodes,commandTimeout);

          return newJedisCluster(nodes,commandTimeout,jedisPoolConfig);

          }

         /**

        * 设置数据存入redis 的序列化方式

        *</br>redisTemplate序列化默认使用的jdkSerializeable,存储二进制字节码,导致key会出现乱码,所以自定义

        *序列化类

        */

        @Bean

 public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {

         RedisTemplate<Object,Object> redisTemplate = newRedisTemplate<>();

         redisTemplate.setConnectionFactory(redisConnectionFactory);

         Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =new Jackson2JsonRedisSerializer(Object.class);

         ObjectMapper objectMapper =new ObjectMapper();

         objectMapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);

         objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

          jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

         redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.setKeySerializer(newStringRedisSerializer());

        redisTemplate.afterPropertiesSet();

           return redisTemplate;

        }

       }

   (4)编写redis启动类;

         @SpringBootApplication

         @MapperScan("com.example.dao")

         @EnableCaching

          public class DemoApplication {

          public static voidmain(String[] args) {

          SpringApplication.run(DemoApplication.class,args);

          }

          }

     (5)测试redis;

(六)SpringBoot整合dubbo开发步骤 

 (1)开发Dubbo服务接口

   注:创建一个maven项目即可

(2)开发Dubbo服务提供者

        1.创建一个SpringBoot项目并配置好相关的依赖;

        2.加入SpringBoot与dubbo集成的起步依赖;

        <dependency>

            <groupId>com.alibaba.boot</groupId>

           <artifactId>dubbo-spring-boot-starter</artifactId>

            <version>0.1.0</version>

         </dependency>

         3.在SpringBoot的核心配置文件中application.properties中配置dubbo的信息;

           dubbo.application.name=springboot-dubbo-provider

           dubbo.registry.address=zookeeper://127.0.0.1:2181

           dubbo.scan.base-packages=com.xxx.service

           server.port=8888

           由于使用了zookeeper作为注册中心,则需要加入zookeeper的客户端jar包:

           <dependency>

                    <groupId>com.101tec</groupId>

                   <artifactId>zkclient</artifactId>

                   <version>0.2</version>

            </dependency>

           4.编写Dubbo的接口实现类:

           import com.alibaba.dubbo.config.annotation.Service;

           import com.camelot.service.ProvideService;

           import org.springframework.stereotype.Component;

          @Component

          @Service//该注解为dubbo的@service注解

          public class ProvideServiceImpl implements ProvideService {

             public String sayHello(String name) {

                  return "-------hello" + name;

            }

            注:需要引入服务接口的jar包

            5.编写一个入口main程序启动Dubbo服务提供者:

             import org.springframework.boot.SpringApplication;

             import org.springframework.boot.autoconfigure.SpringBootApplication;

            @SpringBootApplication

            @EnableDubboConfiguration//开启dubbo的自动配置

            public class Application {

                public static void main(String[] args) {

                SpringApplication.run(Application.class, args);

                }

             }

(3)开发Dubbo服务消费者

        1.创建一个SpringBoot项目并配置好相关的依赖;

        2.加入SpringBoot与dubbo集成的起步依赖;

        <dependency>

            <groupId>com.alibaba.boot</groupId>

           <artifactId>dubbo-spring-boot-starter</artifactId>

            <version>0.1.0</version>

         </dependency>

         3.在SpringBoot的核心配置文件中application.properties中配置dubbo的信息;

           dubbo.application.name=springboot-dubbo-consumer

           dubbo.registry.address=zookeeper://127.0.0.1:2181

           dubbo.scan.base-packages=com.xxx.service

           server.port=8888

           由于使用了zookeeper作为注册中心,则需要加入zookeeper的客户端jar包:

           <dependency>

                    <groupId>com.101tec</groupId>

                   <artifactId>zkclient</artifactId>

                   <version>0.2</version>

            </dependency>

            4.编写一个Controller类,调用远程的Dubbo服务            

           @RestController

            public class Student {

           @Reference//("/boot/student")

           private ProvideService provideService;

          @RequestMapping("/boot/student")

            public Object getStudent(@RequestParam("id") Integer id){

            return schoolService.selectAll();

            } }

            5.编写一个入口main程序启动Dubbo服务消费者:

             import org.springframework.boot.SpringApplication;

             import org.springframework.boot.autoconfigure.SpringBootApplication;

            @SpringBootApplication

            @EnableDubboConfiguration//开启dubbo的自动配置

            public class Application {

                public static void main(String[] args) {

                SpringApplication.run(Application.class, args);

                }

             }


作者:FantJ
链接:https://www.jianshu.com/p/78835f740404
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

(七)部署SpringBoot开发的WAR应用程序步骤

(1)通过<exclusion>标签除去SpringBoot所有starter中内置的tomcat,将servlet.jsp有关的api设置成provided(不参与打包避免冲突)开发环境下还需增加指定scope的tomcat,代码如下:

<dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-tomcat<artifactId>

        <scope>provided</scope>

</dependency>

scope的分类

1.compile:默认值 他表示被依赖项目需要参与当前项目的编译,还有后续的测试,运行周期也参与其中,是一个比较强的依赖,打包的时候通常需要包含进去。

2.test:依赖项目仅仅参与测试相关的工作,包括测试代码的编译和执行,不会被打包,例如:junit

3.runtime:标识被依赖项目无需参与项目的编译,不过后期的测试和运行周期需要其参与,与compile相比,跳过了编译而已,例如JDBC驱动,适用运行和测试阶段

4.provided:打包的时候可以不用打包进去,别的设施会提供,事实上该依赖理论上可以参与编译,测试,运行等周期,相当于compile,但是打包阶段做了exclude操作

5.system:从参与参与角度来说,和provided相同,不过被依赖项不会从maven仓库下载,而是从本地文件系统拿,需要添加systemPath的属性来定义路径

(2)在pom.xml指定打包名称(即:请求时项目名称)

<build>

       <finalName>xdl</finalName>

</build>

意思是生成xdl.war,发布后请求/xdl/xxx请求

(3)修改SpringBoot启动类

1:extends SpringBootServletInitializer;

2:重写configure方法;

注:在springzh中有这样一个类:org.springframework.web.SpringServletContainerInitializer,阅读该类的注释发现该类的作用是使用编程的方式替代web.xml的。其原理就在于该类位于spring-web-xxx.jar中的META-INF/service有一个遵照java spi规范的文件,在支持servlet 3以上版本的容器中会读取该SPI服务的实现类SpringServletContainerInitializer。springboot已经为我们扩展了该类的SpringBootServletInitializer,但是该类是一个抽象类,抽象类无法被实例化,因为我们需要创建yi一个类并继承该类。

(4)选中project工程,Run As -->Maven-build...,然后再goals输入package命令执行。

(5)将生成的xdl.war放到外部tomcat/webapps目录下,然后启动tomcat服务器访问。

  路径:http://localhost:xxx/xdl/...

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值