《智选网开发系列》之 后端服务升级(四)

原创  郑建华   2021-03-28   360人阅读  1 条评论

    该项目停滞多时,终于在今日重启了!原来的开发模式,效率太低了。现在重启,为了提高开发效率,决定做一系列的升级改造。

  • 引入Lombok

  • 引入MyBatisPlus

  • 引入Swagger

  • 引入代码生成器

  • 使用Java8新特性语法

......

2021年3月28日

一、引入Lombok

1、添加pom依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.8</version>
</dependency>

2、实体类增加注解

@Data
@NoArgsConstructor

二、引入MybatisPlus

1、添加pom依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>

2、去除已有的mybatis依赖

3、修改实体类,增加注解

@Data
@NoArgsConstructor
@TableName("admin_user")
@ApiModel(value = "AdminUser", description = "管理用户")
public class AdminUser implements Serializable{

   /**
    * 
    */
   private static final long serialVersionUID = 1L;

   /**
    * 主键id
    */
   @ApiModelProperty("主键id")
   @NotNull(message = "主键id不能为空")
   @TableId(value = "id", type = IdType.AUTO)
   private Integer userId;
   
   /**
    * 用户名
    */
   @ApiModelProperty("用户名")
   @Length(max = 255, message = "用户名长度不能超过255")
   @TableField(value = "userName")
   private String userName;
   
   /**
    * 密码
    */
   @ApiModelProperty("密码")
   @Length(max = 255, message = "密码长度不能超过255")
   @TableField(value = "passWord")
   private String passWord;
   
   /**
    * 昵称
    */
   @ApiModelProperty("昵称")
   @Length(max = 255, message = "昵称长度不能超过255")
   @TableField(value = "nickName")
   private String nickName;
   
   
   /**
    * 创建时间
    */
   @ApiModelProperty("创建时间")
   @TableField("createTime")
   @JsonFormat(shape =JsonFormat.Shape.STRING,pattern="yyyy-MM-dd")
   private LocalDate createTime;
   
   
   /**
    * 更新时间
    */
   @ApiModelProperty("更新时间")
   @TableField("updateTime")
   @JsonFormat(shape =JsonFormat.Shape.STRING,pattern="yyyy-MM-dd")
   private LocalDate updateTime;
   
   /**
    * 用户状态 1 启用,2 禁用
    */
   @ApiModelProperty("用户状态 1 启用,2 禁用")
   @TableField("userStatus")
   private String userStatus;
   
   /**
    * 是否是超级管理员 
    */
   @ApiModelProperty("是否是超级管理员")
   @TableField("superUser")
   private String superUser;

}

4、service继承IService

public interface IAdminUserService extends IService<AdminUser>

5、serviceImpl继承ServiceImpl

public class AdminUserServiceImpl extends ServiceImpl<IAdminUserMapper, AdminUser> implements IAdminUserService

6、mapper继承BaseMapper

public interface IAdminUserMapper extends BaseMapper<AdminUser>

三、引入Swagger

1、增加pom依赖 使用其他的swaggerUI

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
        </exclusion>
    </exclusions>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.swagger</groupId>
    <artifactId>swagger-models</artifactId>
    <version>1.5.21</version>
</dependency>
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.6</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-bean-validators</artifactId>
    <version>2.9.2</version>
</dependency>

2、添加如下三个文件

image.png

package com.zjh.swagger2;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.github.xiaoymin.swaggerbootstrapui.configuration.SwaggerBootstrapUIConfiguration;
import com.github.xiaoymin.swaggerbootstrapui.filter.ProductionSecurityFilter;
import com.github.xiaoymin.swaggerbootstrapui.filter.SecurityBasicAuthFilter;

import io.swagger.models.MarkdownFiles;
import lombok.extern.slf4j.Slf4j;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * Swagger2 启动类
 * 启动条件:
 * 1,配置文件中zxw.swagger.enabled=true
 * 2,配置文件中不存在:zxw.swagger.enabled 值
 *
 */
@Configuration
@ConditionalOnProperty(name = "zxw.swagger.enabled", havingValue = "true", matchIfMissing = true)
@EnableSwagger2
/*@EnableSwaggerBootstrapUI*/
@Import({BeanValidatorPluginsConfiguration.class, SwaggerBootstrapUIConfiguration.class, Swagger2Configuration.ZxwSecurityConfiguration.class})
public class Swagger2Configuration implements WebMvcConfigurer {
    /**
     * 这个地方要重新注入一下资源文件,不然不会注入资源的,也没有注入requestHandlerMappping,相当于xml配置的
     * <!--swagger资源配置-->
     * <mvc:resources location="classpath:/META-INF/resources/" mapping="swagger-ui.html"/>
     * <mvc:resources location="classpath:/META-INF/resources/webjars/" mapping="/webjars/**"/>
     * 不知道为什么,这也是spring boot的一个缺点(菜鸟觉得的)
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");

    }

    @Slf4j
    public static class ZxwSecurityConfiguration {

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(name = "zxw.swagger.production", havingValue = "true")
        public ProductionSecurityFilter productionSecurityFilter(SwaggerProperties swaggerProperties) {
            return new ProductionSecurityFilter(swaggerProperties.getProduction());
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(name = "zxw.swagger.basic.enable", havingValue = "true")
        public SecurityBasicAuthFilter securityBasicAuthFilter(SwaggerProperties swaggerProperties) {
            SwaggerProperties.Basic basic = swaggerProperties.getBasic();
            return new SecurityBasicAuthFilter(basic.getEnable(), basic.getUsername(), basic.getPassword());
        }

        @Bean(initMethod = "init")
        @ConditionalOnMissingBean
        @ConditionalOnProperty(name = "zxw.swagger.markdown.enable", havingValue = "true")
        public MarkdownFiles markdownFiles(SwaggerProperties swaggerProperties) {
            return new MarkdownFiles(swaggerProperties.getMarkdown().getBasePath());
        }

    }

}
package com.zjh.swagger2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.RequestMethod;

import com.github.xiaoymin.swaggerbootstrapui.model.OrderExtensions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;

/**
 * swagger 包扫描配置
 * @Description:
 */

@Import({
        Swagger2Configuration.class
})
@EnableConfigurationProperties(SwaggerProperties.class)
public class SwaggerAutoConfiguration implements BeanFactoryAware {
    private static final String AUTH_KEY = "token";
    @Autowired
    SwaggerProperties swaggerProperties;

    private BeanFactory beanFactory;

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(name = "zxw.swagger.enabled", havingValue = "true", matchIfMissing = true)
    public List<Docket> createRestApi() {
        ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
        List<Docket> docketList = new LinkedList<>();

        // 没有分组
        if (swaggerProperties.getDocket().isEmpty()) {
            final Docket docket = createDocket(swaggerProperties);
            configurableBeanFactory.registerSingleton(swaggerProperties.getTitle(), docket);
            docketList.add(docket);
            return docketList;
        }

        // 分组创建
        for (String groupName : swaggerProperties.getDocket().keySet()) {
            SwaggerProperties.DocketInfo docketInfo = swaggerProperties.getDocket().get(groupName);

            ApiInfo apiInfo = new ApiInfoBuilder()
                    .title(docketInfo.getTitle().isEmpty() ? swaggerProperties.getTitle() : docketInfo.getTitle())
                    .description(docketInfo.getDescription().isEmpty() ? swaggerProperties.getDescription() : docketInfo.getDescription())
                    .version(docketInfo.getVersion().isEmpty() ? swaggerProperties.getVersion() : docketInfo.getVersion())
                    .license(docketInfo.getLicense().isEmpty() ? swaggerProperties.getLicense() : docketInfo.getLicense())
                    .licenseUrl(docketInfo.getLicenseUrl().isEmpty() ? swaggerProperties.getLicenseUrl() : docketInfo.getLicenseUrl())
                    .contact(
                            new Contact(
                                    docketInfo.getContact().getName().isEmpty() ? swaggerProperties.getContact().getName() : docketInfo.getContact().getName(),
                                    docketInfo.getContact().getUrl().isEmpty() ? swaggerProperties.getContact().getUrl() : docketInfo.getContact().getUrl(),
                                    docketInfo.getContact().getEmail().isEmpty() ? swaggerProperties.getContact().getEmail() : docketInfo.getContact().getEmail()
                            )
                    )
                    .termsOfServiceUrl(docketInfo.getTermsOfServiceUrl().isEmpty() ? swaggerProperties.getTermsOfServiceUrl() : docketInfo.getTermsOfServiceUrl())
                    .build();

            // base-path处理
            // 当没有配置任何path的时候,解析/**
            if (docketInfo.getBasePath().isEmpty()) {
                docketInfo.getBasePath().add("/**");
            }
            List<Predicate<String>> basePath = new ArrayList<>(docketInfo.getBasePath().size());
            for (String path : docketInfo.getBasePath()) {
                basePath.add(PathSelectors.ant(path));
            }

            // exclude-path处理
            List<Predicate<String>> excludePath = new ArrayList<>(docketInfo.getExcludePath().size());
            for (String path : docketInfo.getExcludePath()) {
                excludePath.add(PathSelectors.ant(path));
            }

            Docket docket = new Docket(DocumentationType.SWAGGER_2)
                    .host(swaggerProperties.getHost())
                    .apiInfo(apiInfo)
                    .globalOperationParameters(assemblyGlobalOperationParameters(swaggerProperties.getGlobalOperationParameters(),
                            docketInfo.getGlobalOperationParameters()))
                    .groupName(docketInfo.getGroup())
                    .select()
                    .apis(RequestHandlerSelectors.basePackage(docketInfo.getBasePackage()))
                    .paths(
                            Predicates.and(
                                    Predicates.not(Predicates.or(excludePath)),
                                    Predicates.or(basePath)
                            )
                    )
                    .build()
                    .securitySchemes(securitySchemes())
                    .securityContexts(securityContexts())
                    .globalResponseMessage(RequestMethod.GET, getResponseMessages())
                    .globalResponseMessage(RequestMethod.POST, getResponseMessages())
                    .globalResponseMessage(RequestMethod.PUT, getResponseMessages())
                    .globalResponseMessage(RequestMethod.DELETE, getResponseMessages())
                    .extensions(Lists.newArrayList(new OrderExtensions(swaggerProperties.getOrder())));

            configurableBeanFactory.registerSingleton(groupName, docket);
            docketList.add(docket);
        }
        return docketList;
    }

    /**
     * 创建 Docket对象
     *
     * @param swaggerProperties swagger配置
     * @return Docket
     */
    private Docket createDocket(final SwaggerProperties swaggerProperties) {
        //API 基础信息
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                .description(swaggerProperties.getDescription())
                .version(swaggerProperties.getVersion())
                .license(swaggerProperties.getLicense())
                .licenseUrl(swaggerProperties.getLicenseUrl())
                .contact(new Contact(swaggerProperties.getContact().getName(),
                        swaggerProperties.getContact().getUrl(),
                        swaggerProperties.getContact().getEmail()))
                .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
                .build();

        // base-path处理
        // 当没有配置任何path的时候,解析/**
        if (swaggerProperties.getBasePath().isEmpty()) {
            swaggerProperties.getBasePath().add("/**");
        }
        List<Predicate<String>> basePath = new ArrayList<>();
        for (String path : swaggerProperties.getBasePath()) {
            basePath.add(PathSelectors.ant(path));
        }

        // exclude-path处理
        List<Predicate<String>> excludePath = new ArrayList<>();
        for (String path : swaggerProperties.getExcludePath()) {
            excludePath.add(PathSelectors.ant(path));
        }

        return new Docket(DocumentationType.SWAGGER_2)
                .host(swaggerProperties.getHost())
                .apiInfo(apiInfo)
                .groupName(swaggerProperties.getGroup())
                .globalOperationParameters(
                        buildGlobalOperationParametersFromSwaggerProperties(
                                swaggerProperties.getGlobalOperationParameters()))
                .select()

                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()))
                .paths(
                        Predicates.and(
                                Predicates.not(Predicates.or(excludePath)),
                                Predicates.or(basePath)
                        )
                )
                .build()
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts())
                .globalResponseMessage(RequestMethod.GET, getResponseMessages())
                .globalResponseMessage(RequestMethod.POST, getResponseMessages())
                .globalResponseMessage(RequestMethod.PUT, getResponseMessages())
                .globalResponseMessage(RequestMethod.DELETE, getResponseMessages())
                .extensions(Lists.newArrayList(new OrderExtensions(swaggerProperties.getOrder())))
                ;
    }

    protected List<ResponseMessage> getResponseMessages() {
        List<ResponseMessage> collect = Arrays.asList(
                new ResponseMessageBuilder().code(0).message("成功").build()
        );
        return collect;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    private List<SecurityContext> securityContexts() {
        List<SecurityContext> contexts = new ArrayList<>(1);
        SecurityContext securityContext = SecurityContext.builder()
                .securityReferences(defaultAuth())
                //.forPaths(PathSelectors.regex("^(?!auth).*$"))
                .build();
        contexts.add(securityContext);
        return contexts;
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> references = new ArrayList<>(1);
        references.add(new SecurityReference(AUTH_KEY, authorizationScopes));
        return references;
    }

    private List<ApiKey> securitySchemes() {
        List<ApiKey> apiKeys = new ArrayList<>(1);
        ApiKey apiKey = new ApiKey(AUTH_KEY, AUTH_KEY, "header");
        apiKeys.add(apiKey);
        return apiKeys;
    }

    private List<Parameter> buildGlobalOperationParametersFromSwaggerProperties(
            List<SwaggerProperties.GlobalOperationParameter> globalOperationParameters) {
        List<Parameter> parameters = Lists.newArrayList();

        if (Objects.isNull(globalOperationParameters)) {
            /*parameters.add(new ParameterBuilder()
                    .name(AUTH_KEY)
                    .description("token令牌")
                    .modelRef(new ModelRef("string"))
                    .parameterType("header")
                    .defaultValue("test")
                    .required(false)
                    .order(1)
                    .build());*/
            return parameters;
        }
        for (SwaggerProperties.GlobalOperationParameter globalOperationParameter : globalOperationParameters) {
            parameters.add(new ParameterBuilder()
                    .name(globalOperationParameter.getName())
                    .description(globalOperationParameter.getDescription())
                    .modelRef(new ModelRef(globalOperationParameter.getModelRef()))
                    .parameterType(globalOperationParameter.getParameterType())
                    .required(Boolean.parseBoolean(globalOperationParameter.getRequired()))
                    .build());
        }
        return parameters;
    }

    /**
     * 局部参数按照name覆盖局部参数
     *
     * @param globalOperationParameters
     * @param docketOperationParameters
     * @return
     */
    private List<Parameter> assemblyGlobalOperationParameters(
            List<SwaggerProperties.GlobalOperationParameter> globalOperationParameters,
            List<SwaggerProperties.GlobalOperationParameter> docketOperationParameters) {

        if (Objects.isNull(docketOperationParameters) || docketOperationParameters.isEmpty()) {
            return buildGlobalOperationParametersFromSwaggerProperties(globalOperationParameters);
        }

        Set<String> docketNames = docketOperationParameters.stream()
                .map(SwaggerProperties.GlobalOperationParameter::getName)
                .collect(Collectors.toSet());

        List<SwaggerProperties.GlobalOperationParameter> resultOperationParameters = Lists.newArrayList();

        if (Objects.nonNull(globalOperationParameters)) {
            for (SwaggerProperties.GlobalOperationParameter parameter : globalOperationParameters) {
                if (!docketNames.contains(parameter.getName())) {
                    resultOperationParameters.add(parameter);
                }
            }
        }

        resultOperationParameters.addAll(docketOperationParameters);
        return buildGlobalOperationParametersFromSwaggerProperties(resultOperationParameters);
    }
}
package com.zjh.swagger2;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * swagger2 属性配置
 * 必须配置 prefix ,才能有提示
 *
 */
@Data
//@RefreshScope
@Component
@ConfigurationProperties(prefix = "zxw.swagger")
public class SwaggerProperties {
    /**
     * 是否开启swagger
     **/
    private Boolean enabled = true;

    /**
     * 是否生产环境
     */
    private Boolean production = false;
    /**
     * 离线文档路径
     */
    private Markdown markdown = new Markdown();


    /**
     * 访问账号密码
     */
    private Basic basic = new Basic();

    /**
     * 标题
     **/
    private String title = "在线文档";
    private String group = "";
    /**
     * 描述
     **/
    private String description = "zxw 在线文档";
    /**
     * 版本
     **/
    private String version = "1.0";
    /**
     * 许可证
     **/
    private String license = "";
    /**
     * 许可证URL
     **/
    private String licenseUrl = "";
    /**
     * 服务条款URL
     **/
    private String termsOfServiceUrl = "";

    private Contact contact = new Contact();

    /**
     * swagger会解析的包路径
     **/
    private String basePackage = "com.zjh";

    /**
     * swagger会解析的url规则
     **/
    private List<String> basePath = new ArrayList<>();
    /**
     * 在basePath基础上需要排除的url规则
     **/
    private List<String> excludePath = new ArrayList<>();

    /**
     * 分组文档
     **/
    private Map<String, DocketInfo> docket = new LinkedHashMap<>();

    /**
     * host信息
     **/
    private String host = "";

    /**
     * 排序
     */
    private Integer order = 1;
    /**
     * 全局参数配置
     **/
    private List<GlobalOperationParameter> globalOperationParameters;

    @Setter
    @Getter
    public static class GlobalOperationParameter {
        /**
         * 参数名
         **/
        private String name;

        /**
         * 描述信息
         **/
        private String description;

        /**
         * 指定参数类型
         **/
        private String modelRef;

        /**
         * 参数放在哪个地方:header,query,path,body.form
         **/
        private String parameterType;

        /**
         * 参数是否必须传
         **/
        private String required;
    }

    @Data
    public static class DocketInfo {
        /**
         * 标题
         **/
        private String title = "在线文档";
        /**
         * 自定义组名
         */
        private String group = "";
        /**
         * 描述
         **/
        private String description = "zxw 在线文档";
        /**
         * 版本
         **/
        private String version = "1.0";
        /**
         * 许可证
         **/
        private String license = "";
        /**
         * 许可证URL
         **/
        private String licenseUrl = "";
        /**
         * 服务条款URL
         **/
        private String termsOfServiceUrl = "";

        private Contact contact = new Contact();

        /**
         * swagger会解析的包路径
         **/
        private String basePackage = "";

        /**
         * swagger会解析的url规则
         **/
        private List<String> basePath = new ArrayList<>();
        /**
         * 在basePath基础上需要排除的url规则
         **/
        private List<String> excludePath = new ArrayList<>();

        private List<GlobalOperationParameter> globalOperationParameters;

        /**
         * 排序
         */
        private Integer order = 1;

        public String getGroup() {
            if (group == null || "".equals(group)) {
                return title;
            }
            return group;
        }
    }

    public String getGroup() {
        if (group == null || "".equals(group)) {
            return title;
        }
        return group;
    }

    @Data
    public static class Contact {
        /**
         * 联系人
         **/
        private String name = "zxw";
        /**
         * 联系人url
         **/
        private String url = "";
        /**
         * 联系人email
         **/
        private String email = "";
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Basic {
        private Boolean enable = false;
        private String username = "zxw";
        private String password = "zxw";
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Markdown {
        private Boolean enable = false;
        private String basePath = "classpath:markdown/*";
    }
}

3、在mvcConfigurer中添加配置

image.png

4、界面效果

image.png

关于在配置swagger过程中碰到的问题,例如此类问题

image.png

我在过程中也碰到了doc.html打不开的问题,根据当前项目环境,过滤器中排除了doc.html请求,也在mvcConfigeurer中增加了resourceHandler,结果doc.html能打开了,但是接口内容并没有显示出来。直到最后,偶然间的尝试,成功显示了接口内容。那就是在启动类注解中,指定了扫描包范围,@SpringBootApplication(scanBasePackages = {"com.zjh"}),我猜测应该是没有配置时不会扫描进去,所以404找不到资源。还是怪自己,配置不够熟悉。


时间不早了,今天就先到这里,明天再继续后面的改造。


2021.03.29更新

今天继续做服务升级,原本的mybatisPlus还未完全集成好,在使用原有语句查询时,竟然报错提示

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):com.****

而直接使用mybatisPlus的条件构造器查询就正常显示,所以mybatisPlus的配置基本是没有问题的,问题可能就出在mapper.xml的配置上了。

直到后来才发现,可能是由于mapper-location配置引起的。

本工程引入的是

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>

配置文件中如下

#mybatis sqlMap的xml文件目录
#mybatis.mapper-locations=classpath*:sqlmap/*.xml

经过查阅:

如果引用mybatis-plus-boot-starter 依赖,需要配置 mybatis-plus.mapper-locations

如果引用mybatis-plus 依赖,需要配置 mybatis.mapper-locations

所以,修改了配置如下

mybatis-plus.mapper-locations=classpath*:sqlmap/*.xml

这样,就能正常执行了。


另外,还解决了一个@JsonFormat(shape =JsonFormat.Shape.STRING,pattern="yyyy-MM-dd")注解,页面未格式化的问题

1、pom.xml需要引入依赖

<!-- jdk8 Time-->
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.9.8</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-parameter-names</artifactId>
    <version>2.9.8</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
</dependency>

2、后台请求原本是使用net.sf.json的方法,转换对象为json字符串,再前端解析的方式。其中将Date类型的进行了Json格式化

JsonConfig config = new JsonConfig ();
config.registerJsonValueProcessor (Date.class, new JsonDateValueProcessor ("yyyy-MM-dd"));
String resultStr=JSONObject.fromObject (resultMap,config).toString(); 
retrun resultStr;

而现在将原来的java.util.Date更改为了java.time.LocalDate,虽然加上了@JsonFormat注解,但是界面显示的还是一个[Object]。

经过断点调试,发现实际已经生效了的。但是再通过JSONObject的转换,又成功将其转换成了普通的JSON对象,LocalDate对应的是一个LocalDate的JSON格式对象而不是一个字符串。后来直接在接口返回Map,界面显示正常了。

image.png

今天用来做事的时间不多,处理完这两个问题,已经是凌晨00:29了,那么代码生成器部分就有时间再做吧。


2021.03.30更新

今天继续研究,目标是搞定代码生成器

image.png

官网其实是有教程说明的,按照此步骤操作即可。为了节省时间,以及使用顺手,参考了公司代码生成模块,基于自身项目风格做了改造。

image.png

总体来说,服务升级算是差不多了,使用JAVA8新特性编写代码就在后续过程中慢慢应用。过段时间,有空的话,研究下jenkins自动化部署,在服务器上安装一套。接下来,就可以好好写代码了。


本文地址:https://www.zjh336.cn/?id=2031
版权声明:本文为原创文章,版权归 郑建华 所有,欢迎分享本文,转载请保留出处!

发表评论


表情

 评论列表

  1. 招投标
    招投标 【助理】  @回复

    博主好专业