• SpringBoot入门


    1. 简介

    • 目的:简化配置、内嵌Tomcat方便部署(尤其微服务)
    • 版本:SNAPSHOT版是快照版,虽然稳定,但还会有更新
    • 创建空项目:https://start.spring.io/上创建下载,然后再从文件系统导入到eclipse或者IDEA中
      • web应用需要在pom.xml中增加依赖spring-boot-starter-web
      • 可以选是maven还是gradle项目
      • 可以选语言
      • 可以选spring boot版本
      • 可以输入所需要的依赖包
        • 常用的:Lombok、Spring Web、Spring for RabbitMQ、Spring Data JPA、Spring Data Redis (Access+Driver)、PostgreSQL Driver等
    • Spring Tool Suite的New->Project->Spring Boot->Spring Starter Project可以一步一步的创建Spring Boot项目,最终调的还是https://start.spring.io/得接口,其他IDE也是,虽然可以选不同service,但目前都是https://start.spring.io/。
      • 最终还是用的https://start.spring.io/,会调其接口,如https://start.spring.io/starter.zip?name=SpringBootGradle&groupId=com.jasonwang&artifactId=SpringBootGradle&version=0.0.1-SNAPSHOT&description=Spring+Boot+Common+Modules&packageName=com.jasonwang&type=gradle-project&packaging=jar&javaVersion=1.8&language=java&bootVersion=2.1.8.RELEASE&dependencies=lombok&dependencies=amqp&dependencies=data-redis&dependencies=data-jpa&dependencies=postgresql&dependencies=web
    • Spring Tool Suite中可以打开Boot Dash这个view,集成Cloud Foundry,方便部署。

    2. web项目结构

    • 根包
      • 通常放启动类XxxApplication
      • 加注解@SpringBootApplication,也可以同时限定扫描和排除的包@SpringBootApplication(scanBasePackages = { "xxx.xxx" },exclude = {xxx.class})
        • 启动类其实名字可以随便起
      • 还可以加注解@MapperScan("microservice.qssj.mapper"),默认不加的话只扫描main类所在包及子包下面的controller,否则就要加scanBasePackages或@ComponentScan
    • controller
      • 接口层
      • 为controller类加注解@RestController和@RequestMapping("xxx"),xxx区分大小写
      • 使用到的其他类如Service类使用注解@Resource进行注入
      • 为具体的接口方法增加注解@CrossOrigin、@ApiOperation(value = "xxx", notes = "xxx")、@RequestMapping(value = "xxx", method = RequestMethod.GET),xxx区分大小写
      • 返回值可以自定义,GET方式参数要使用注解@RequestParam(required = true),POST方式参数要使用注解@RequestBody,这些参数类都要实现Serializable
      • 可以使用ResponseEntity处理Controller的返回值,T为要返回的内容,可以同时指定返回状态码
        • 如果想避免重复代码,可以抛出异常,然后用@RestControllerAdvice来标识自定义全局异常处理类、用@ExceptionHandler标识方法来做全局的异常处理,统一包装返回给客户端的信息
    • service
      • 接口上使用注解@Service("xxxService")或只是@Service
      • 在需要使用的job或controller类中注入时,类型为接口类型即可,不需要具体到实现类
    • serviceImpl
      • 类上使用注解@Service("xxxService")或只是@Service
      • 如果没有继承自service接口,在需要使用的job或controller类中注入时,需要具体到实现类
      • 使用到的其他类如Mybatis的Mapper类使用注解@Resource进行注入
      • 可以为成员使用注解@Value("${xxx}")为其赋上properties文件中的配置值
    • db.mapper.primary
      • 定义访问数据的方法,可以直接用sql语句,也可以指定provider类中的方法拼接sql,也可以使用xml文件
    @Mapper
    public interface EUserInfoMapper {
    
    	 /**
         *用户登录
         * @param userName
         * @param pwd 
         * @return
         */
        @Select("select * from  `staff` where id=#{userName} and password=#{pwd}")
        EUser login(@Param("userName") String userName,@Param("pwd") String pwd);
        
         * @return
         */
        @SelectProvider(type = UserSqlProvider.class, method = "getUsersFilter")
        List<EUser> serachUsers(SerachUserVO serachUserVO);
       
    }
    
    
    • db.mapper.provider
      • 相当于动态拼接sql语句,也类似于传统的mybatis的xml文件的作用
    
    
    public class UserSqlProvider {
    
        public String getUsersFilter(final SerachUserVO serachUserVO) {
            String sql =new SQL() {
                {
                    SELECT("*");
                    FROM("staff");
                    WHERE("del_flag=0");
                    if (StringUtil.isNotEmpty(serachUserVO.getUser_name())) {
                        WHERE("id=#{user_name}");
                    }
                    if (StringUtil.isNotEmpty(serachUserVO.getReal_name())) {
                    	WHERE("name=#{real_name}");
                    }
                    if (StringUtil.isNotEmpty(serachUserVO.getMobile())) {
                    	WHERE("cell_phone=#{mobile}");
                    }
                    ORDER_BY("id desc limit #{page_index},#{page_size}");
                }
            }.toString();
            return sql;
        }
    }
    
    • exception
    • entity
      • 最好还是按用途分层使用:vo、po等
      • 如果是用于mybatis数据访问的实体类,比如primary包中返回的类型,那么每个字段名称都要和数据库中一致
    • util
    • config
      • MybatisDbConfig.java
    @Configuration
    @MapperScan(basePackages = "xxx.db.mapper.primary", sqlSessionTemplateRef = "primarySqlSessionTemplate")
    public class MybatisDbAConfig {
    
        @Value("${pagehelper.offsetAsPageNum}")
        private String offsetAsPageNum;
    
        @Value("${pagehelper.helperDialect}")
        private String helperDialect;
    
        @Bean(name = "primaryDataSource")
        @ConfigurationProperties(prefix = "spring.datasource.primary")
        @Primary
        public DataSource primaryDataSource() {
            return new DruidDataSource();
        }
    
        @Bean(name = "primaryTransactionManager")
        @Primary
        public DataSourceTransactionManager setTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {
            return new DataSourceTransactionManager(dataSource);
        }
    
        @Bean(name = "primarySqlSessionFactory")
        @Primary
        public SqlSessionFactory setSqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            bean.setDataSource(dataSource);
          //  bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/base/*.xml"));
            // 分页拦截器-begin
            PageInterceptor interceptor = new PageInterceptor();
            Properties properties = new Properties();
            properties.setProperty("helperDialect", helperDialect);
            properties.setProperty("offsetAsPageNum", offsetAsPageNum);
            interceptor.setProperties(properties);
            bean.getObject().getConfiguration().addInterceptor(interceptor);
            // 分页拦截器-end
            return bean.getObject();
        }
    
        @Bean(name = "primarySqlSessionTemplate")
        @Primary
        public SqlSessionTemplate setSqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
            return new SqlSessionTemplate(sqlSessionFactory);
        }
    
    }
    
    * DruidDataSourceConfiguration.jva
    
    @Configuration
    public class DruidDataSourceConfiguration {
    
    	@Bean(name="primaryDataSource")
        @Qualifier("primaryDataSource")
        @Primary
        @ConfigurationProperties(prefix = "spring.datasource.primary")
        public DataSource primaryDataSource() {
            DruidDataSource druidDataSource = new DruidDataSource();  
            return druidDataSource;
        }
    
    }
    
    * Swagger2Config.java
    
    • 定时任务job(不需要调用,启动后就开始)
      • 主类上要加@EnableScheduling
      • 使用@Component注解?
      • 使用@Scheduled(cron = "0/10 * * * * ?")来控制间隔时间

    3. 配置文件

    • 按约定,spring的配置文件是src/main/resources/application.properties(IDEA用的是application.yml)
      • 根据application.properties中的spring.profiles.active=test配置,找到当前环境对应的真正的配置文件,如application-test.properties
      • 可通过server.port修改端口号
    • kafka的配置文件可以是producer.properties和consumer.properties,然后程序中读取并使用
    • 可以全局指定时区的日期转json字符串的方式,时间戳一般专指一个格式

    4. Swagger

    • 与.NET版不同,接口、实体类的描述是通过注解去标注的,而不是通过注释(有可能也支持注释的方式?),然后再抽取出这些标注并生成接口文档
    • Swagger UI自己的web页面等,可能直接就在maven引入的jar包中,类似Spring boot的jar包启动方式,也包含页面等文件,解压后可以看到
    • 访问地址:http://localhost:8081/swagger-ui.html
    • 安装
      • pom.xml文件增加依赖并maven update project
            <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>
    
    * 在单独的配置文件中配置接口包地址、生成的接口的版本描述名称
    
    @Configuration
    @EnableSwagger2
    public class Swagger2Config {
    
    	@Bean
    	public Docket createRestApi() {
    		return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
    				.apis(RequestHandlerSelectors.basePackage("com.eastmoney.articlemanager.controller")).paths(PathSelectors.any()).build();
    	}
    
    	private ApiInfo apiInfo() {
    		return new ApiInfoBuilder().title("xxx RESTful APIs")
    				.description("xxx")
    				 .version("1.0").build();
    	}
    
    }
    
    * 在需要提供描述信息的位置上增加注解
        * Model类的属性注解
    
    public class BaseResponse {
    	@ApiModelProperty("返回编码")
    	private String resultCode;
    
    	@ApiModelProperty("返回信息")
    	private String resultMsg;
    
    	@ApiModelProperty("错误码")
    	private String errorCode;
    
    	@ApiModelProperty("返回具体内容")
    	private Object data;
    
    	public void setResult(String resultCode, String resultMsg, String errorCode, Object data) {
    		this.resultCode = resultCode;
    		this.resultMsg = resultMsg;
    		this.errorCode = errorCode;
    		this.data = data;
    	}
    
    	public BaseResponse() {
    
    	}
    
    }
    
        * 接口类的注解
            * @ApiOperation(value = "获取总体趋势", notes = "获取总体趋势")
    

    5. lombok

    • 安装
      • 先要在pom.xml文件中增加依赖(可以不指定版本,eclipse会自动选择)
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
    
    * 然后在下载的lombok.jar依赖包目录运行java -jar lombok.jar以打开安装界面,选择eclipse安装目录后安装即可
    * 安装完成后要重新maven update project。
    
    • 如果报错“getId() is undefined”,可能是虽然增加了依赖,但没有安装lombok.jar,即参考上一项安装。也有人说是eclipse太新,也有人说需要打开eclipse的注解开关什么的。
    • 使用时,需要在类或者成员上标志@Data、@Getter、@Setter

    6. 运行/部署

    • 运行
      • Run as或者Debug as为Java Application,在弹窗中需要新建一项,选择Main class然后运行/调试
    • 部署
      • 传统、简单的jar方式
        • 内置tomcat(貌似可以换成Jetty等)
        • 生成:使用命令mvn install或者Eclipse上项目右击选择Run As选择maven install(有时生成不了,可能是文件编码等原因报错了,可以命令行跑一下mvn package试一下,看看输出)
        • 部署:target目录会生成一个jar包及相关文件(不知道是不是必要的),直接在该目录java -jar xxx.jar运行即可(在命令行中可通过ctrl+c停止运行)
      • 部署到外部Tomcat中
        • 注意tomcat版本(jdk1.8最好用tomcat1.8)

    7. 项目结构划分

    • PBF(按功能划分包) vs PBL(按层次划分包)
    • 按层次(都用@Component)
      • Web控制层,常使用@RestController、@Controller
      • 业务逻辑层,常使用@Service
      • 数据访问层(常使用@Repository,可以使用Mybatis也可以使用较老的JPA也就是Hibernate)
    • 如果较复杂,可以考虑先按功能分,内部再按层次分
  • 相关阅读:
    WHU 1572 Cyy and Fzz (AC自动机 dp )
    Codeforces 441D Valera and Swaps(置换群)
    Codeforces 527E Data Center Drama(欧拉回路)
    差分约束小结
    Codeforces 193D Two Segments 解题报告
    SGU 231.Prime Sum
    SGU 249.Matrix(Gray码)
    SGU 222.Little Rooks
    SGU 207.Robbers
    risc-v的寻址模式
  • 原文地址:https://www.cnblogs.com/wyp1988/p/10223334.html
Copyright © 2020-2023  润新知