栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java开发杂项总结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java开发杂项总结

java开发小白杂项总结

前言:本人毕业于2021年,刚刚接触java开发,在开发过程中发现自己什么都不懂,因此写下本文作为总结自己在初入开发时遇到的问题,希望有机会看到本文的家人们,避免踩我相同的坑(有些坑自己都觉得傻,本文等于小白成长日志)。本文包括一些java写法,规范,报错问题,常见问题等杂项,希望能帮助各位和我一样刚步入java开发的小伙伴。文中有什么不对的,也希望大家不吝指点。这也是我第一次尝试写博文,一些排版等问题日后也会向大家多多学习。星光不问赶路人 时光不负有心人(本文持续更新)

一、java 1.java8新特性 (1)stream流式操作

  //使用流过滤
  public static void main(String[] args) { 
    List list = new ArrayList<>();
    list.add("张无忌");
    list.add("周芷若");
    list.add("赵敏");
    list.add("张强");
    list.add("张三丰");
    list.stream().filter(s->s.startsWith("张")).filter(s-> s.length() == 3).forEach(System.out::println);
    
  //流map 
  
      //1.将流中的元素映射到另一个流中,这个是在后期经常用到的,比如方法所接收的返回值是A,但是接收的却是B
    list.stream().map(item -> {
                    ProductInfoAttributes productInfoAttributes = new ProductInfoAttributes();
                    BeanUtils.copyProperties(item, productInfoAttributes);
                    productInfoAttributes.setProductId(productId);
                    productInfoAttributes.setAttributeId(IDGenerator.getId());
                    return productInfoAttributes;
                }).collect(Collectors.toList());
   
      //2.将String类型的流转换为Integer 类型
              Stream stringStream = Stream.of("1", "2", "3", "4", "5", "6");
        stringStream.map(str->Integer.parseInt(str)).forEach(System.out::println);
	
      //3.方法需要返回的是List ,但是这里只有List,此时就要想到stream().map
          public  List queryNamesByIds(List ids){
        
              List categories = this.categoryMapper.selectByIdList(ids);
       
    return  categories.stream().map(category -> 					            
                                    category.getName()).collect(Collectors.toList());
    }

2.static使用(与属性注入的关系) (1)static(主函数是static修饰)只能调用调用static方法

静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法。

public abstract class A {
    public static void func1(){
    }
    // public abstract static void func2();  // Illegal combination of modifiers: 'abstract' and 'static'
}

只能访问所属类的静态字段和静态方法,方法中不能有 this 和 super 关键字,因为这两个关键字与具体对象关联。

public class A {

    private static int x;
    private int y;

    public static void func1(){
        int a = x;
        // int b = y;  // Non-static field 'y' cannot be referenced from a static context
        // int b = this.y;     // 'A.this' cannot be referenced from a static context
    }
}
(2) 静态内部类(从类的加载顺序可知【加载原则先静态后非静态,先父类再子类】)

非静态内部类依赖于外部类的实例,也就是说需要先创建外部类实例,才能用这个实例去创建非静态内部类。而静态内部类不需要。

public class OuterClass {

    class InnerClass {
    }

    static class StaticInnerClass {
    }

    public static void main(String[] args) {
        // InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context
        OuterClass outerClass = new OuterClass();
        InnerClass innerClass = outerClass.new InnerClass();
        StaticInnerClass staticInnerClass = new StaticInnerClass();
    }
}

静态内部类不能访问外部类的非静态的变量和方法。不应该通过类实例访问静态成员,使用类名去访问

父类(静态变量、静态语句块)

子类(静态变量、静态语句块)

父类(实例变量、普通语句块)

父类(构造函数)

子类(实例变量、普通语句块)

子类(构造函数)

3.集合 (1)List中add和addAll的区别

add是添加list对象,addAll是添加list中的每一个object

4.java常用API(常看api文档)

JDK1.8源码中文说明

http://blog.fondme.cn/apidoc/jdk-1.8-google

1.集合(工具类)
 ArrayList result = Lists.newArrayList();
        List list = lfCommodityInfoPlMapper.findTypeList(LfType.VIDEO);
        list.addAll(lfCommodityInfoPlMapper.findTypeList(LfType.GAME));


lists.newarraylist():

List list = new ArrayList(); 

new arraylist() :

List list = Lists.newArrayList();

//Lists和Maps是两个工具类, Lists.newArrayList()其实和new ArrayList()几乎一模一样, 唯一它帮你做的(其实是javac帮你做的), 就是自动推导(不是"倒")尖括号里的数据类型.
2.Arrays
//转string 
Arrays.toString
3.Collections
//判断是否为空
Collections.isEmpty
5.IO流

(1)读文件(输入流):

BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("infilename")));

不管你从磁盘读,从网络读,或者从键盘读,读到内存,就是InputStream。

(2)写文件(输出流):

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("outfilename")));

不管你写倒磁盘,写到网络,或者写到屏幕,都是OuputStream

6.java自带util
//CollectionUtils,集合工具类  https://blog.csdn.net/huangwenyi1010/article/details/53706297
//交并补差,是否相等,是否为空等等
CollectionUtils.isEmpty(childCategoryList);

//StringUtils,字符工具类
StringUtils.isEmpty();
二、Mysql 1)外连接查询/函数运用到相应的列

        select loi.order_no                              orderNo,
               loi.unit_price                            totalPrice,
               loi.account                               phone,
               loi.order_status                          status,
               lon.order_info                            cardInfo,
               lc.icon,
               lc.id                                     categoryId,
               //三元表达式
               IF(loi.sec_kill = 1, lcip.name, lci.name) commodityName,
               IF(loi.sec_kill = 1, lcip.type, lci.type) type,
               loi.created,
               //从该列的左边开始计算到第19位
            LEFt(aon.gmt_payment, 19)                 payTime
        from lf_order_info loi
            left join lf_commodity_info lci on loi.code = lci.code
            left join lf_commodity_info_pl lcip on loi.code = lcip.code
            left join lf_category lc on lci.category = lc.id
            left join lf_order_notify lon on loi.order_no = lon.out_id
            left join alipay_order_notify aon on loi.order_no = aon.out_trade_no
        where loi.uid = #{uid}
        GROUP BY loi.id
        order by loi.created desc
    
2)模糊查询写法

name like concat(’%’,#{name},’%’);

3)foreach/trim区别
//循环数组,开闭,分隔器

        #{id}



        insert into lf_commodity_info
        
            code,
            name,
            value_str,
            type_code,
            member_type,
            price,

            category,

            underlined_price,
            selling_price,

            type,
            enable,
            created,
            updated,
            tax_rate,
        
        
            #{code},
            #{name},
            #{valueStr},
            #{typeCode},
            #{memberType},
            #{price},

            #{category},

            #{underlinedPrice},
            #{sellingPrice},

            #{type},
            #{enable},
            #{created},
            #{updated},
            #{taxRate},
        
    
4)Mybatis插入list集合
 insert into lf_commodity_info(
            id,
            code,
            name,
            value_str,
            type_code,
            member_type,
            category,
            price,
            underlined_price,
            selling_price,
            type,
            enable,
            tax_rate,
            created,
            updated)
            values
            
                (
                 #{item.id},
                 #{item.code},
                 #{item.name},
                 #{item.valueStr},
                 #{item.typeCode},
                 #{item.memberType},
                 #{item.category},
                 #{item.price},
                 #{item.underlinedPrice},
                 #{item.sellingPrice},
                 #{item.type},
                 #{item.enable},
                 #{item.taxRate},
                 #{item.created},
                 #{item.updated}
                )
            
 //sql语句   
INSERT INTO student(name,age,sex)
VALUES("张三",12,"男"),("王三",12,"男")
5)关联查询
select icon
        from lf_category a
        right join lf_commodity_info b on a.type=b.type
        where b.category = #{category}
5.1.sql左联右联的差别

​ 左联接:已一边为主表保留其全部数据

6)嵌套查询
select icon
        from lf_category a
        where a.type = (select type
                        from lf_commodity_info b
                        where b.category = #{category})
7)distinct关键字去重
//distinct去重查询
select icon
        from lf_category a
        where a.type = (select DISTINCT type from lf_commodity_info b where b.category = #{category})
    
    
 //关联查询的去重   
    SELECt
	a.id,
	a.title,
	a.total,
	count( DISTINCT ( b.user_id ) ) AS 'read',//去重后计算该类别中的总数
	a.time,
	a.status 
FROM
	message a
	RIGHT JOIN msg_read b ON a.id = b.msg_id
	GROUP BY a.id//巧用分组,分组计算
三、Spring全家桶 1.注解

(1)Spring中异步注解@Async的使用、原理及使用时可能导致的问题

(2)

    @requestBody(将json转成object对象,前端到后端交互时使用)

    注解@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。

	  @RequestParam():@RequestParam

注解@RequestParam接收的参数是来自HTTP请求体或请求url的QueryString中。

RequestParam可以接受简单类型的属性,也可以接受对象类型。

@RequestParam有三个配置参数:

required 表示是否必须,默认为 true,必须。
defaultValue 可设置请求参数的默认值。
value 为接收url的参数名(相当于key值)

(3)@PathVariable(接收类如aaa/{id})直接在url后的参数

(4)@Cacheable(用于缓存注解)

​ @Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。Spring在缓存方法的返回值时是以键值对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略,这个稍后会进行说明。需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。@Cacheable可以指定三个属性,value、key和condition。

(5)@Configration

​ @ConfigrationProperties(prefix=“lf”) //配置类的注解

(6)@RequestMapping请求和别的区别

  @RequestMapping(name = " 支付宝 支付返回数据", value = "/aliPay/return_url", method = {RequestMethod.POST, RequestMethod.GET})
2.OpenFeign的使用

创建应用主类Application,并通过@EnableFeignClients注解开启Spring Cloud Feign的支持功能。

@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients(basePackages = { "com.kyle.client.feign.inter" })
public class Application {
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

▪️定义HelloServiceFeign,接口@FeignClient注解指定服务名来绑定服务,然后再使用Spring MVC的注解来绑定具体该服务提供的REST接口。

@FeignClient(value = "hello-service-provider")
public interface HelloServiceFeign {

    @RequestMapping(value = "/demo/getHost", method = RequestMethod.GET)
    public String getHost(String name);

    @RequestMapping(value = "/demo/postPerson", method = RequestMethod.POST, produces = "application/json; charset=UTF-8")
    public Person postPerson(String name);
}

注意:这里服务名不区分大小写,所以使用hello-service-provider和HELLO-SERVICE-PROVIDER都是可以的。另外,在Brixton.SR5版本中,原有的serviceId属性已经被废弃,若要写属性名,可以使用name或value。

▪️接着,创建一个RestClientController来实现对Feign客户端的调用。使用@Autowired直接注入上面定义的HelloServiceFeign实例,并在postPerson函数中调用这个绑定了hello-service服务接口的客户端来向该服务发起/hello接口的调用。

@RestController
public class RestClientController {
@Autowired
private HelloServiceFeign client;


@RequestMapping(value = "/client/postPerson", method = RequestMethod.POST, produces = "application/json; charset=UTF-8")
public Person postPerson(String name) {
    return client.postPerson(name);
}


@RequestMapping(value = "/client/getHost", method = RequestMethod.GET)
public String getHost(String name) {
    return client.getHost(name);

MyDev

//添加注解,实现api接口
@RestController
public class IfClient implements LfHandleApi {
    @Resource
    private LfCommodityInfoMapper lfCommodityInfoMapper;
    @Resource
    private DocLfPayService lfPayService;
    @Resource
    private LfCategoryMapper lfCategoryMapper;

    
    @Override
    public void pay(LfOrderInfo lfOrderInfo) {
        //查找商品
        LfCommodityInfo commodityInfo = lfCommodityInfoMapper.findByCode(lfOrderInfo.getCode());
        if (commodityInfo == null) {
            throw new BizException(ErrorMessages.BASIC_0001, "商品不存在");
        }
        switch (commodityInfo.getType()) {
            case LfType.VIDEO:
                lfPayService.payVideo(commodityInfo, lfOrderInfo.getAccount(), lfOrderInfo.getOrderNo());
                break;
            case LfType.GAME:
            case LfType.RECHARGE_CARD:
                lfPayService.payGame(commodityInfo, lfOrderInfo.getAccount(), lfOrderInfo.getIp(), lfOrderInfo.getOrderNo());
                break;
            case LfType.PHONE_BILL:
                lfPayService.payMobile(commodityInfo, lfOrderInfo.getAccount(), lfOrderInfo.getOrderNo());
                break;
            default:
                throw new BizException(ErrorMessages.BASIC_0001, "商品类型不存在!");
        }
    }

    @Override
    public LfCommodityInfo findByCode(String code) {
        //通过code查询
        LfCommodityInfo lfCommodityInfo = lfCommodityInfoMapper.findByCode(code);
        return lfCommodityInfo;
    }

    @Override
    public String getIcon(Long category) {
        return lfCategoryMapper.selectIcon(category);
    }
@EnableFeignClients//远程调用入口
@SpringBootApplication
@MapperScan(value = "com.xfw.welfare.docking.lf.mapper")
public class DockingApplication {

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

}
//api模块,去调用别的模块,定义api接口
@FeignClient(value = "${lf.namespace:}lf")
public interface LfHandleApi {
    
    @GetMapping("/api/welfare-lf/pay")
    void pay(@RequestBody LfOrderInfo lfOrderInfo);
    
    @GetMapping("/api/welfare-lf/findByCode")
    LfCommodityInfo findByCode(String code);
    
    @GetMapping("/api/welfare-lf/getIcon")
    String getIcon(@RequestParam("category") Long category);
}
理解feign的代码架构方式

三层架构的理解,lfclient,DocLfPayservice,DocLfPayserviceimpl 区别

一、远程调用类再主服务中,实现api中api接口方法(这里写url),需要注解@RestController,类似于实现类

3.@Scheduled定时任务cron表达式

定时任务Scheduled

cron表达式详解https://help.eset.com/era_admin/65/zh-CN/cron_expression.html

@Component
public class Task
{
    @Scheduled(cron="0/5 * *  * * ? ")   //每5秒执行一次
    public void execute(){
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置日期格式
        System.out.println("欢迎访问 pan_junbiao的博客 " + df.format(new Date()));
    }


//启动类添加注解
@SpringBootApplication
@EnableScheduling //开启定时任务
public class ScheduledDemoApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(ScheduledDemoApplication.class, args);
    }


4.配置文件的使用
server: //端口
  port: ${APP_PORT:19970}

spring:
  application:
    name: ${order-server.namespace:}order
  cloud:
    nacos:
      username: ${NACOS_SERVER_USERNAME:nacos}
      password: ${NACOS_SERVER_PASSWORD:xfw1234}
      server-addr: ${NACOS_SERVER_ADDR:172.16.9.159:8848}
      config: //nacos中配置的前缀和yml后缀
        prefix: order
        enabled: true
        file-extension: yml
      discovery:
        enabled: true

  profiles:
    active: @profiles.active@
  main:
    allow-bean-definition-overriding: true
四、Mybatis 1、传参问题

1.MyBatis BindingException: Parameter ‘a’ not found(mapper中的参数没有在xml里被使用)

2.解决

这里需要注意的是collection必须为array,否则会报错如下:

Caused by: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [array]

5、trim剪切标签的使用
//
 
        insert into lf_commodity_info
        //suffixOverrides后缀覆盖
            code,
            name,
            value_str,
            type_code,
            member_type,
            price,

            category,

            underlined_price,
            selling_price,

            type,
            enable,
            created,
            updated,
            tax_rate,
        
        
            #{code},
            #{name},
            #{valueStr},
            #{typeCode},
            #{memberType},
            #{price},

            #{category},

            #{underlinedPrice},
            #{sellingPrice},

            #{type},
            #{enable},
            #{created},
            #{updated},
            #{taxRate},
        
    
    
                //separator分隔符
                
                
                (
                 #{item.id},
                 #{item.code},
                 #{item.name},
                 #{item.valueStr},
                 #{item.typeCode},
                 #{item.memberType},
                 #{item.category},
                 #{item.price},
                 #{item.underlinedPrice},
                 #{item.sellingPrice},
                 #{item.type},
                 #{item.enable},
                 #{item.taxRate},
                 #{item.created},
                 #{item.updated}
                )
            
五、异常总结 1)数据截断异常

数据截断异常:(原因:导入的数据长度大于数据库长度)

Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation

2)BadSqlGrammarException(只要报这个异常,直接将语句放到数据库调试)

​ sql语句的问题,1.列名,2.sql语句的异常1.sql列数和参数不一样多

3)result问题

MyBatis.TooManyResultsException(封装的返回值不够)

4)异常

java.sql.SQLIntegrityConstraintViolationException(违反完整性约束):
一、其实就是违反了数据库的唯一约束条件!也就是插入数据时,具有唯一约束条件的列值重复了。
根据我图中描述信息的展示可知,我的表中"test1"这一列是具有唯一约束的,现在插入列值时数据有重复了。所以务必确认插入数据的主键或者具有唯一性约束的列不要有重复数据!!!

二、缺少主键

5)java.lang.IllegalArgumentException: Pattern cannot be null or empty

个人经验,该传的参数没传,参数名称写错了,@requestBody/@requestParam 忘记注解

其他具体问题参考:https://blog.csdn.net/weixin_44259720/article/details/103185972

6)feign.FeignException$NotFound: [404] during [POST]

feign调用失败,当代码确定没用问题的前提下,可能时分布式架构下,多服务启动造成的问题,解决方法在调用方服务中添加被调用方服务名

六、第三方开发工具的使用 1.xshell的使用(linux常用命令行)

https://www.cnblogs.com/bowendown/p/11937159.html 下载安装地址

开发常用命令

tail -200f welfare-operation.nohup.out ()查看具体文件的后几行,查看部署环境下最后发生了什么问题

cd 进入文件

2.xxlJob分布式定时任务的使用

官方文档:https://www.xuxueli.com/xxl-job/

项目结构:

快速入门:

1.建两个分布式事务模块

2.建数据库

3.导入依赖

4.xxlJob配置类(可将配置写入nocas等),必写不然通过代码是不能注册任务的

package com.xfw.welfare.message.config;

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
@Slf4j
public class XxlJobConfig {
    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;

    @Value("${xxl.job.accessToken}")
    private String accessToken;

    @Value("${xxl.job.executor.appname}")
    private String appname;

    @Value("${xxl.job.executor.address}")
    private String address;

    @Value("${xxl.job.executor.ip}")
    private String ip;

    @Value("${xxl.job.executor.port}")
    private int port;

    @Value("${xxl.job.executor.logpath}")
    private String logPath;

    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;

	//执行器组件
    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        log.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setAddress(address);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    }


}

5.添加并启动任务为例(其实就是调用xxljob的接口)


//1.XxlJobInfo此参数其实理解上来就是数据库中的XxlJobInfo实体类,实体类见下方
//2.调用addAndStart见下
    public Integer addAndStart(XxlJobInfo xxlJobInfo) {
        //发送请求,到xxljobAdmin微服务的controller接口,详细结构见截图
        HttpsRequest request = new HttpsRequest(addAndStartUrl + "/jobinfo/addAndStart");
        // 任务参数
        request.setJsonBody(JSONObject.toJSONString(xxlJobInfo));
        if (request.executePostRequest()) {
            String response = request.getResponse();
            log.info("创建任务:response==={}", response);
            JSONObject jo = JSON.parseObject(response);
            if (!"200".equals(jo.getString("code"))) {
                log.error("创建启动任务失败,jobId={}", xxlJobInfo.getId());
                throw new RuntimeException(jo.getString("msg"));
//                throw new BusinessException(jo.getString("msg"));
            }
            return jo.getInteger("content");
        }
        throw new RuntimeException("创建任务失败");
//        throw new BusinessException("创建任务失败");
    }

6.实体类(对标数据库中的xxljobinfo表)

package com.xfw.welfare.message.xxljob;

import lombok.Data;

import java.util.Date;


@Data
public class XxlJobInfo {
    private int id;                // 主键ID

    private int jobGroup;        // 执行器主键ID
    private String jobDesc;

    private Date addTime;
    private Date updateTime;

    private String author;        // 负责人
    private String alarmEmail;    // 报警邮件

    private String scheduleType;            // 调度类型
    private String scheduleConf;            // 调度配置,值含义取决于调度类型
    private String misfireStrategy;            // 调度过期策略

    private String executorRouteStrategy;    // 执行器路由策略
    private String executorHandler;            // 执行器,任务Handler名称
    private String executorParam;            // 执行器,任务参数
    private String executorBlockStrategy;    // 阻塞处理策略
    private int executorTimeout;            // 任务执行超时时间,单位秒
    private int executorFailRetryCount;        // 失败重试次数

    private String glueType;        // GLUE类型	#com.xxl.job.core.glue.GlueTypeEnum
    private String glueSource;        // GLUE源代码
    private String glueRemark;        // GLUE备注
    private Date glueUpdatetime;    // GLUE更新时间

    private String childJobId;        // 子任务ID,多个逗号分隔

    private int triggerStatus;        // 调度状态:0-停止,1-运行
    private long triggerLastTime;    // 上次调度时间
    private long triggerNextTime;    // 下次调度时间

    private String appName; // 执行器名称
}

7.调用上方5api

		//创建并启动任务
        XxlJobInfo xxlJobInfo = assemblyParam(msgDetRequest);
		//添加并启用
        Integer jobId = addAndStartApi.addAndStart(xxlJobInfo);



    public XxlJobInfo assemblyParam(MsgDetRequest msgDetRequest) {
        //将时间转化为cron表达式
        String cron = DateUtil.getCron(msgDetRequest.getDate());
        //生成jobId
        Long jobId = IDGenerator.getId();
        // jobGroup必须为 ( jobGroup必须为代表的是对应执行器,如果执行器不知道是多少就默认为 0,但是必须传执行器名称appName)
        XxlJobInfo xxlJobInfo = new XxlJobInfo();
        xxlJobInfo.setId(jobId.intValue());
        xxlJobInfo.setJobGroup(0);
        xxlJobInfo.setAppName("message-executor");
        xxlJobInfo.setJobDesc("定时推送消息任务" + msgDetRequest.getTitle());
        xxlJobInfo.setAddTime(new Date());
        xxlJobInfo.setUpdateTime(new Date());
        xxlJobInfo.setAuthor("admin");
        xxlJobInfo.setScheduleType("CRON");
        xxlJobInfo.setScheduleConf(cron);
        xxlJobInfo.setMisfireStrategy("DO_NOTHING");
        xxlJobInfo.setExecutorRouteStrategy("FIRST");
        //TODO 设置jobHandler名称
        xxlJobInfo.setExecutorHandler("messageHandler");
        //TODO 任务参数 消息id
        xxlJobInfo.setExecutorParam(String.valueOf(msgDetRequest.getMsgId()));
        xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");
        xxlJobInfo.setExecutorTimeout(0);
        xxlJobInfo.setExecutorFailRetryCount(3);
        xxlJobInfo.setGlueType("BEAN");
        xxlJobInfo.setGlueRemark("GLUE代码初始化");
        xxlJobInfo.setGlueUpdatetime(new Date());
        //TODO 调度状态:0-停止,1-运行 刚添加的调度状态为0(添加定时任务默认为开启)
        xxlJobInfo.setTriggerStatus(1);
        xxlJobInfo.setTriggerLastTime(0L);
        xxlJobInfo.setTriggerNextTime(0L);
        return xxlJobInfo;
    }
3.redis使用

https://www.cnblogs.com/yechangzhong-826217795/p/11202316.html

使用安装redis 的坑

Can’t connect to redis-server

解决 运行=》services.msc=》redis启用

4.Jrebel热部署(提高开发效率)

https://www.haah.net/archives/6285.html

七、中间件的使用 1.nacos官方文档

springCloud 引入nocas官方文档 https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html

1.下载,

2.导入两个依赖

3.yml书写

server:
  port: ${APP_PORT:19977}

spring:
  application:
    name: ${message.namespace:}message
  cloud:
  #重点:寻找nocas中的配置文件
    nacos:
      username: ${NACOS_SERVER_USERNAME:nacos}
      password: ${NACOS_SERVER_PASSWORD:666}
      server-addr: ${NACOS_SERVER_ADDR:172.16.9.149:666}
      config:
        prefix: message
        enabled: true
        file-extension: yml
      discovery:
        enabled: true

  profiles:
    active: dev
  main:
    allow-bean-definition-overriding: true

八、开发中Problem 1)spring中使用Junit测试 1、导入Junit依赖

​ 2、注意测试类的路径必需与非测试类路径一样

可参考:https://blog.csdn.net/weixin_39800144/article/details/79241620

注解

@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderTest {
    @Resource
    private OrderPremiumServiceImpl orderPremiumService;
    @Resource
    private baseInfoMapper baseInfoMapper;
    @Resource
    private baseProductItemsMapper productItemsMapper;

//    @Test
//    public void testCreateOrder(){
//        CreatOrderRequest request = new CreatOrderRequest();
//
//        orderPremiumService.createOrder()
//    }

    
    @Test
    public void testSave() {
        baseInfo baseInfo = new baseInfo();
        baseInfo.setbaseInfoId(Long.valueOf(10));
        baseInfoBuyerContact baseInfoBuyerContact = new baseInfoBuyerContact();
        baseInfoBuyerContact.setBuyerId(Long.valueOf(20));
        baseInfoSellerContact baseInfoSellerContact = new baseInfoSellerContact();
        baseInfoSellerContact.setSellerId(Long.valueOf(30));
        baseInfoReceInfo baseInfoReceInfo = new baseInfoReceInfo();
        baseInfoReceInfo.setReceInfoId(Long.valueOf(50));

        baseInfoLogistics baseInfoLogistics = new baseInfoLogistics();
        baseInfoLogistics.setLogId(Long.valueOf(60));

        baseInfoLogisticsItems baseInfoLogisticsItems = new baseInfoLogisticsItems();
        baseInfoLogisticsItems.setLogItemsId(Long.valueOf(70));

        baseProductItems baseProductItems = new baseProductItems();
        baseProductItems.setId(Long.valueOf(80));
//        orderPremiumService.saveOrder(baseInfo, baseInfoBuyerContact, baseInfoSellerContact, baseInfoReceInfo,
//                baseInfoLogistics, baseInfoLogisticsItems, baseProductItems);
    }
2)代码规范

分new ,get,set(分点组装从参数)

总new ,get,set(将分点组装进总参数)

类中定义方法,代码冗余,地区定义

// 2. 拼接省市区镇街道,调用1688api解析地址编码,调用内部类,并调用内部类中的方法(方法定义在类中)
String districtCode = getDistrictCode(request.getDeliveryAddress().getAddressText());
字符串拼接,使用stringBuilder
public String getAddressText() {    
    StringBuilder text = new StringBuilder();    	text.append(provinceText).append(cityText).append(areaText).append(townText).append(address);    
    return text.toString();}

3)分装json对象
//jsonObject 返回json对象(如何封装json对象)
public ArrayList phoneBill() {
        ArrayList result = Lists.newArrayList();
        List list = lfCommodityInfoPlMapper.findTypeList(LfType.PHONE_BILL);
        list.forEach(LfCategory -> {
            JSONObject category = new JSONObject();
            category.putOpt("id", LfCategory.getId());
            category.putOpt("name", LfCategory.getName());
            category.putOpt("icon", LfCategory.getIcon());
            category.putOpt("rule", LfCategory.getRules());
            category.putOpt("specifications", lfCommodityInfoPlMapper.findCommodityListByCategoryId(LfCategory.getId()));
            int dayOfMonth = DateUtil.thisDayOfMonth();
            //每月的8-19号 有优惠 其他日期原价
            category.putOpt("discount", dayOfMonth >= Constant.PHONE_BILL_DISCOUNT_START && dayOfMonth <= Constant.PHONE_BILL_DISCOUNT_END);
            result.add(category);
        });
        return result;
    }
4)发送Http请求/获取httpRequest和httpResponse
//1,hutool 
//发送http请求
HttpResponse response = HttpRequest.post(LFPayGameRequest.URL).form(BeanUtil.beanToMap(request)).timeout(10000).execute();
//2.HttpClient发送

//怎么获得httprequest和httpresponse

public abstract class baseHandler extends ResponseEntityExceptionHandler {
private static ServletRequestAttributes getRequestAttributes() {
    RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
    return (ServletRequestAttributes) attributes;
}

protected static HttpServletRequest getRequest() {
    return getRequestAttributes().getRequest();
}

protected static HttpServletResponse getResponse() {
    return getRequestAttributes().getResponse();
}


@ExceptionHandler(Throwable.class)
@ResponseBody
public Response handleThrowable(Throwable ex) {
    logger.error("baseHandler Error", ex);
    return Response.error(new BusinessException(ErrorMessages.BASIC_0001));
}
}
5)封装对象,
//lf支付请求参数,封装方法
@Data
public class LFPayGameRequest {
    //定义静态常量
    public static final String URL = "http://open.jiaofei100.com/Api/PayGame.aspx";


    private String APIID;
    private String TradeType;
    private String Account;
    private String UnitPrice;
    private String BuyNum;
    private String TotalPrice;
    private String OrderID;
    private String CreateTime;
    private String isCallBack;
    private String GoodsID;
    private String ClientIP;
    private String Sign;


    
    //定义类方法
    public String generateSign(String appKey) {
        String sb = "APIID=" + APIID +
                "&Account=" + Account +
                "&BuyNum=" + BuyNum +
                "&ClientIP=" + ClientIP +
                "&CreateTime=" + CreateTime +
                "&GoodsID=" + GoodsID +
                "&isCallBack=" + isCallBack +
                "&OrderID=" + OrderID +
                "&TotalPrice=" + TotalPrice +
                "&TradeType=" + TradeType +
                "&UnitPrice=" + UnitPrice +
                "&APIKEY=" + appKey;
        return MD5Util.md5Hex(sb).toUpperCase();
    }
}
6)BigDecimal类型转化千万不能强制类型转换(精度丢失,详见阿里开发手册),转化(元,分,厘)【无非就是简单的乘除操作】
//BigDecimal
//单位 厘
        BigDecimal price = infoModel.getUnderlinedPrice().multiply(new BigDecimal("1000")).setScale(0);


BigDecimal 分转元

BigDecimal feeNo = new BigDecimal(fee);//string 转 BigDecimal 分转元
feeNo = feeNo.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);//分转元
7)String 的正则表达式
fileName.matches("^.+\.(?i)(xlsx)$")//matches方法
8)pom文件引用的坑,用于抽取API模块时,依赖引用问题

主类中应用api即可,api中不能引用主类中的依赖

9)前后端文件传输

https://blog.csdn.net/sdut406/article/details/85647982 MultipartFile与File的一些事,这两个词一般是Java中出现的吧,前者代表HTML中form data方式上传的文件,后者是文件系统的抽象,前者信息较少,只有二进制数据+文件名称

10)枚举类和属性类的区别

属性类

public class LfType {

    
    public final static int VIDEO = 1;
    public final static int GAME = 2;
    public final static int PHONE_BILL = 3;
    public final static int RECHARGE_CARD = 4;


}

枚举类

package com.xfw.common.enums;

import lombok.Getter;


@Getter
public enum CodeResponseEnum {

    PARAMETER_ERROR(10007, "参数错误"),
    ORDER_TIMEOUT(10008, "订单超时"),
    PARAMETER_VERIFICATION_ERROR(10009, "参数校验错误"),
    AGENCY_ID_DOES_NOT_EXIST(10010, "代理商 ID 不存在"),
    NUMBER_TO_LONG(10011, "订单号长度大于 36"),
    AGENCY_STATUS_ERROR(10012, "代理商状态错误"),
    INSUFFICIENT_BALANCE(10013, "账户余额不足"),
    IP_ERROR(10014, "IP 地址验证失败"),
    PHONE_ERROR(10015, "充值号码有误"),
    NOT_SUPPORT(10016, "暂不支持该号码"),
    BAN(10017, "禁止采购该商品"),
    SUCCESS(10018, "订单提交成功"),

    FAILED(10020, "订单提交失败"),
    UNKNOWN(10021, "未知错误"),
    DUPLICATE(10022, "订单号重复"),
    NOT_SUPPORT_01(10024, "暂不支持该面值"),
    PROCESSING(10025, "订单处理中"),
    FAIL_TRANSACTION(10026, "交易失败"),
    SUCCESS_TRANSACTION(10027, "交易成功"),

    NOT_EXIST(10029, "订单不存在"),
    LIMIT(10035, "限制5分钟内同一时间和同一个金额"),
    MAINTENANCE(10036, "系统维护"),
    NOT_STARTED(10037, "活动未开始"),
    FINISH(10038, "活动已经结束"),
    ;

    private final int code;
    private final String msg;

    CodeResponseEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    
    public static CodeResponseEnum getEnum(int code) {
        CodeResponseEnum result = null;
        for (CodeResponseEnum s : values()) {//values 表示当前枚举类
            if (s.getCode() == code) {
                result = s;
                break;
            }
        }
        return result;
    }

}
11)list.foreach的实际应用
 productCategoryList.forEach(categoryDTO -> {
     
            List childCategoryList = productCategoryFactory.getChild(allProductCategoryList,
                    categoryDTO.getId(), getAllCategoryList(), request.getQueryType());
            if(Objects.nonNull(request.getQueryType()) && request.getQueryType() == 1){
                //在商品分类界面调用,需要返回商品
                int productNum = 0;
                if(CollectionUtils.isEmpty(childCategoryList)){
                    List categoryIds = new ArrayList<>();
                    ProductCategoryRelWrapper.Selecter matcherSumProductList = new ProductCategoryRelWrapper.Selecter();
                    matcherSumProductList.categoryIdIn(categoryIds);
                    productNum = productCategoryRelMapper.selectCount(matcherSumProductList).intValue();
                }else {
                    productNum = childCategoryList.stream().mapToInt(ProductCategoryResponse::getProductNum).sum();
                }
                categoryDTO.setProductNum(productNum);
            }
            categoryDTO.setCategoryChildList(childCategoryList);
        });
12)巧用三元运算符
    public int getInventory(String purchaseLimitCode) {
        String key = getKey(purchaseLimitCode);
        Integer inventory = (Integer) redisTemplate.opsForValue().get(key);
        return inventory == null ? 0 : inventory;
    }
13)Date格式
new DateTime().toString("yyyyMMddHHmmss")//??导入依赖,有问题
    	//java自带
   	    Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        String s = dateFormat.format(date);
        System.out.println(s);
14)excel导入导出
取excel的坑 https://blog.csdn.net/qq_35893120/article/details/80395080

导出excel模板 https://blog.51cto.com/u_15127658/4337321
15)DTO和VO的区别

http://www.tnblog.net/aojiancc2/article/details/2396

前后端交互使用request和response

VO(View Object):封装参数

​ 视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。

DTO(Data Transfer Object):网络传输,中间件的交互

​ 数据传输对象,泛指用于展示层与服务层之间的数据传输对象。

PO(Persistent Object):

​ 持久化对象,就是和数据库保持一致的对象

16)开发工具安装问题,程序扫描

安装目录空格,查看报错信息,%(符号为百分号),将workspace拉到别的地方

17)配置文件

绑定异常(修改配置文件),我们使用的时Mybatis-plus,实际我们的配置为mybatis,所以配置类读取错误

mybatis-plus:

​ type-aliases-package: com.xfw.welfare.docking

​ mapper-locations: classpath* */mapper/mapping/ *.xml

18)接不到参数为空,原因

接前端参数,或者接远程调用的参数的为null时可能时因为@RequestBody注解忘记打了等注解没使用

19)为了再nacos中起不一样的服务,避免开发冲突(其中在调用方也需要配置调用方)

//不然可以会报找不到服务

20)数据库设计,时间自动增长,和插入的时间有关


阿里java

21)转化请求的时间格式

转时间格式(在类属性中)

  @ApiModelProperty(value = "操作时间,最近一次上下架的时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    private Date operateDate;
22)在类中使用静态变量(定义常量)和方法(日常写法)
package com.xfw.welfare.docking.dto.request;

import cn.modousa.mds.common.tools.MD5Util;
import lombok.Data;


@Data
public class LFPayVideoRequest {
    public static final String URL = "http://open.jiaofei100.com/Api/PayVideo.aspx";

    private String APIID;
    private String Account;
    private String ProductCode;
    private String BuyNum;
    private String OrderID;
    private String CreateTime;
    private String IsCallBack;
    private String CallBack;
    private String Sign;

    
    public String generateSign(String appKey) {
        String sb = "APIID=" + APIID +
                "&Account=" + Account +
                "&BuyNum=" + BuyNum +
                "&CreateTime=" + CreateTime +
                "&IsCallBack=" + IsCallBack +
                "&OrderID=" + OrderID +
                "&ProductCode=" + ProductCode +
                "&APIKEY=" + appKey;
        return MD5Util.md5Hex(sb).toUpperCase();
    }
}

23)private和public修饰属性的区别
private String a;//需要set get方法,new之后get出来

public String b;//可以new之后直接点出来
24)数据库和mq的了解

1.数据库设计 https://github.com/jly8866/archer/blob/master/src/docs/mysql_db_design_guide.md

2.了解mq的使用场景 https://www.zhihu.com/question/34243607

25)MultipartFile文件流,前后端交互
// MultipartFile转inputstream,前后端传文件流,不会传地址,传的是文件流
//例
@PostMapping("/upload")
    @ApiOperation("上传文件到oss")
    @ApiImplicitParam(name = "pathName", value = "参数,文件地址", required = true, dataType = "MultipartFile")
    public Response uploadFile(@RequestParam MultipartFile pathName) throws IOException {
        String filename = pathName.getOriginalFilename();//获得流中的文件名
        InputStream inputStream = pathName.getInputStream();//将文件流转化为输入流
        String url = ossUtil.uploadFile(inputStream,filename);//调用下面的方法
        if (!StringUtils.isEmpty(url)) {
            return Response.ok(url);
        }
        log.error("文件上传到Oss失败");
        throw new BusinessException(ErrorMessages.BASIC_0001);
    }


//oss通过流上传文件
 public String uploadFile(InputStream inputStream,String fileName) throws IOException {

        //首先判断是否有welfare的存储空间
        createBucket();

        //将本地文件上传到存储空间bucket中的目录中
        //依次填写Bucket名称(例如examplebucket)、Object完整路径(例如exampledir/exampleobject.txt)和本地文件的完整路径。Object完整路径中不能包含Bucket名称。
        //TODO bucket下的目录文件夹?
        PutObjectRequest objectRequest = new PutObjectRequest(OssConfig.BUCKET_NAME, "common/" + fileName,inputStream);
        //上传文件
        PutObjectResult putObjectResult = ossClient.putObject(objectRequest);
        //判断ETag(ETag用于标识一个Object的内容)
        if (StringUtils.isEmpty(putObjectResult.getETag())) {
            log.error("上传文件失败{}");
            //关闭OssClient
            ossClient.shutdown();
            return "false";
        }
        log.info("上传文件成功{}");
        //拼接访问url
        String url = backUrl(fileName);
        //关闭OssClient
        ossClient.shutdown();
        return url;
    }



//示例,多态,没必要强行给fileinputstream,想的不全面,变通一点,在idea中查看java继承体系,ctrl+h
右键,最后一个,show继承体系
// 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
//多态
InputStream inputStream = new FileInputStream("D:\localpath\examplefile.txt");
26)jenkens部署,发送代码时,记得发布到测试环境 27)使用mybatisplus Wrapper层的作用

除了关联查询不行,基本上都可以操作

 @Override
    public AlipayOrderInfo findByOutTradeNo(String outTradeNo) {
        AlipayOrderInfoWrapper.Selecter matcher = new AlipayOrderInfoWrapper.Selecter();
        //通过以上对象进行具体的操作
        matcher.outTradeNoEq(outTradeNo);//等于
        matcher.orderByDesc(AlipayOrderInfo.cols().id().orderNo().toList());//降序
        
        return alipayOrderInfoMapper.selectOne(matcher);//wrapper入参
    }


  @Override
    public AlipayOrderInfo findByOrderNo(String orderId) {
        AlipayOrderInfoWrapper.Selecter matcher = new AlipayOrderInfoWrapper.Selecter();
        matcher.orderNoEq(orderId);//等于不同的id,通过点出不同的东西控制
        return alipayOrderInfoMapper.selectOne(matcher);//将wrapper入参
    }
28)经常需要的时间戳(13位),获取毫秒
#### 6.时间戳
 //获得13位时间戳精确到毫秒
        long date = System.currentTimeMillis();
		//阿里开发手册强制推荐:
		//1.获取毫秒数,必须使用
        System.currentTimeMillis();
        //2,而不是
        new Date().getTime();
29)初识配置nacos

30)读取配置类中的值
package com.xfw.docking.proxy.config;

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class XxlJobConfig {
    private final Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);

    @Value("${xxl.job.admin.addresses}")//通过该注解,${},每一个点表示一层
    private String adminAddresses;

    @Value("${xxl.job.accessToken}")
    private String accessToken;

    @Value("${xxl.job.executor.appname}")
    private String appname;

    @Value("${xxl.job.executor.address}")
    private String address;

    @Value("${xxl.job.executor.ip}")
    private String ip;

    @Value("${xxl.job.executor.port}")
    private int port;

    @Value("${xxl.job.executor.logpath}")
    private String logPath;

    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;


    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setAddress(address);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    }


}

31)项目中的yml配置nacos中的配置
server:
  port: ${APP_PORT:19000}
  servlet:
    context-path: /
spring:
  application:
    name: ${xxl-job-admin.namespace:}xxl-job-admin
  cloud:
    nacos:
      username: ${NACOS_SERVER_USERNAME:nacos}
      password: ${NACOS_SERVER_PASSWORD:xfw1234}
      server-addr: ${NACOS_SERVER_ADDR:172.16.9.159:8848}
      config:
        prefix: xxl-job //nocos中配置的前缀
        enabled: true //启用
        file-extension: yml//nocos中配置的后缀
      discovery:
        enabled: true

  profiles:
    active: @profiles.active@
  main:
    allow-bean-definition-overriding: true

32)nacos中的配置,对标上面的配置
spring:
  datasource:
    url: jdbc:mysql://47.99.39.180:3306/welfare_dev_xxl_job?serverTimezone=CST&useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useInformationSchema=true
    username: root
    password: xinfengwei,2018
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    druid:
      connect-properties:
        config.decrypt: false
        config.decrypt.key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKEDoKdvmsSWILeeRuCqu4yjlaPAoKJbrJw1JNoAP20YLZmvC8kl+/bYwLpmog97lO16PELsPMy/ovq5I2fot2cCAwEAAQ==
      filter:
        config:
          enabled: true
        xfw:
          enabled: true
      max-active: 64
      initial-size: 10
      min-idle: 10
      max-wait: 6000
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: select 'X'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
### xxl-job, access token
xxl:
  job:
    accessToken: y@Ylv2fOxX07SgYm
### xxl-job, i18n (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en")
    i18n: zh_CN

## xxl-job, triggerpool max size
    triggerpool:
      fast:
        max: 200
      slow:
        max: 100
    logretentiondays: 365
    
redis:
    database: 11
    host: 47.99.39.180
    port: 6379
    password: 'xinfengwei,2018'
    timeout: 1000
    lettuce:
      pool:
        max-active: 2
        max-idle: 2
        min-idle: 1
        max-wait: -1
    servlet:
    multipart:
      max-file-size : 20MB
      max-request-size: 100MB
    cloud:
      bus:
        enabled: false

### xxl-job, log retention days
    logretentiondays: 7

environment:
  variable: DEV    
33)postman怎么传json格式
{
    'list':[1,1],//json传集合,数组

​    "flag":1,

​    "msgId": **null**,

​    "title": "测试新建6",

​    "content": "新建内容6",

​    "imgUrl": "https://img-bss.csdn.net/1640226649214.png",

​    "proId": 1,

​    "push": 1,

​    "date": "2020-05-01 01:01:09"//json时间格式

}
34)java后端强行转时间格式
@ApiModelProperty(value = "创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")//此注解
	private Date created;
35)分页代码
//注意返回结果,注意传参
public PageInfo queryMsgPage(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);//在这里控制就好了
        List messagesList = messageMapper.queryMsg();//还是全查出来
        return new PageInfo<>(messagesList);//将查出来的集合进行分页
    }
36)将字符串(string)转化为相应的数据类型的集合(List)
//
int[] ids= Arrays.stream(str.split(",")).mapToInt(s -> Integer.parseInt(s)).toArray();
//转为请求方法对应参数类型
List collect = Arrays.stream(ids).boxed().collect(Collectors.toList());

//一个小坑,集合转为字符串之后,每个逗号后还是有空格的,所以在使用split分割的时候需要加空格
//集合转完有空格
long[] longs = Arrays.stream(substring.split(", ")).mapToLong(item -> Long.parseLong(item)).toArray();

集合转数组(阿里开发手册)

【强制】使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一
致、长度为 0 的空数组。
反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,若强转其它类型数组将出现
ClassCastException 错误。
正例:
List list = new ArrayList<>(2);
list.add("guan");
list.add("bao");
String[] array = list.toArray(new String[0]);
说明:使用 toArray 带参方法,数组空间大小的 length: 1) 等于 0,动态创建与 size 相同的数组,性能最好。
2) 大于 0 但小于 size,重新创建大小等于 size 的数组,增加 GC 负担。
3) 等于 size,在高并发情况下,数组创建完成之后,size 正在变大的情况下,负面影响与 2 相同。
4) 大于 size,空间浪费,且在 size 处插入 null 值,存在 NPE 隐患。
37)前端没有长整型,都是string

长整型都是使用string去接收,传long超过16位就会造成精度丢失

38)限制文件上传大小,添加配置文件
servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 20MB
      enabled: true
39)全局版本号的定义(父子工程pom文件的书写)

POM标签大全详解 - Youpeng - 博客园 (cnblogs.com)

//父工程例子


    4.0.0
    pom
    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.8.RELEASE
         
    
    com.xfw
    welfare
    0.0.1-SNAPSHOT
    welfare
    描述
    //版本号统一管理
    
        UTF-8
        UTF-8
        1.8
        1.8
        1.8
        1.0.15
        0.9.1
        2.3.8.RELEASE
        Hoxton.SR9
        1.8.8.Final
        2.2.6.RELEASE
        1.2.66
        1.18.16
        3.8.2
        3.4.3.2
        1.9.4
        0.0.1-SNAPSHOT
        2.9.2
        2.0.9
        1.5.22
        2.0.0
    
    //父工程模块的管理子模块工程,与删除添加同步
    
        
        welfare-gateway
        
        welfare-product
        
        welfare-product-api
        
        welfare-order
        
        welfare-order-api
        
        welfare-lf
        
        welfare-lf-api
        
        welfare-common
        
        welfare-generator
        
        welfare-docking-proxy
        
        xxl-job-admin
        
        xxl-job-core
        
        welfare-operation
        
        welfare-enterprise
        
        welfare-system
        
        welfare-system-api
        
        welfare-message
        
        welfare-message-api
        
        welfare-authentication

        welfare-auth
        welfare-auth-api
        welfare-push
    
    //dependencyManagement:依赖管理,这是父工程需要使用的,有时内部依赖可能会爆红,可以把			    dependencyManagement删除重新down依赖即可,然后重新添加标签
    
        
            
                org.springframework.boot
                spring-boot-dependencies
                ${springboot.version}//引入版本号的格式
                pom
                import
            

            
                org.springframework.cloud
                spring-cloud-dependencies
                ${springcloud.version}
                pom
                import
            

            
                com.alibaba.cloud
                spring-cloud-alibaba-dependencies
                ${spring-cloud-alibaba-dependencies.version}
                pom
                import
            

            
                com.aliyun.openservices
                ons-client
                ${aliyun.openservices.version}
            
            
                io.jsonwebtoken
                jjwt
                ${jjwt.version}
            
            
                com.alibaba
                fastjson
                ${fastjson.version}
            

            
                org.projectlombok
                lombok
                ${lombok.version}
                provided
            

            
                org.redisson
                redisson
                ${redisson.version}
                true
            

            
                org.redisson
                redisson-spring-boot-starter
                ${redisson.version}
            

            
                com.baomidou
                mybatis-plus-boot-starter
                ${mybatisplus.version}
            

            
                com.baomidou
                mybatis-plus
                ${mybatisplus.version}
            

            
                commons-beanutils
                commons-beanutils
                ${commons-beanutils.version}
            

            
                com.alibaba
                druid-spring-boot-starter
                1.1.21
            
            
                com.alibaba
                druid
                1.1.23
            
            
                com.google.code.gson
                gson
                ${gson.version}
            

            
                io.springfox
                springfox-swagger2
                ${swagger2.version}
                
                    
                        io.swagger
                        swagger-annotations
                    
                    
                        io.swagger
                        swagger-models
                    
                
            
            
                io.swagger
                swagger-models
                ${swagger-models.version}
            
            
                io.swagger
                swagger-annotations
                ${swagger-models.version}
            
            
                io.springfox
                springfox-swagger-ui
                ${swagger2.version}
            

        
    
    //依赖引入
    
        
            org.projectlombok
            lombok
            1.18.16
            provided
        
    


//子工程例子


        
     
     //父工程标签
    
        welfare
        com.xfw
        0.0.1-SNAPSHOT
    
    4.0.0

    welfare-message

    
        8
        8
    
    
             
             
    
        
            org.springframework.cloud
            spring-cloud-starter-openfeign
            
                
                    archaius-core
                    com.netflix.archaius
                
                
                    HdrHistogram
                    org.hdrhistogram
                
                
                    commons-io
                    commons-io
                
            
        

        
            org.springframework.boot
            spring-boot-starter-logging
        
        
        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
        

        
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-config
        

        
            com.alibaba.nacos
            nacos-client
        
        
            com.alibaba
            druid
        
        
            com.xfw
            welfare-common
            ${welfare-version}
            //去除依赖中的某个依赖
            
                
                    com.xfw.framework
                    xfw-framework-leopard-auth
                
            
        
        
            com.xfw
            welfare-authentication
            ${welfare-version}
        
        
            com.xfw
            welfare-message-api
            ${welfare-version}
        
        
            com.aliyun
            dingtalk
            1.2.5
            compile
        
        
            com.xfw.framework
            xfw-framework-leopard-dingtalk-base
            ${xfw-framework.version}
        
        
            com.xuxueli
            xxl-job-core
            0.0.1-SNAPSHOT
            compile
        
    
    
             
    
        
            maven-central
            maven-central
            http://47.99.39.180:8781/repository/maven-releases/
            
                true
            
            
                true
            
        
    
    
        
            
            dev
            
                dev
            
            
                true
            
        
        
            
            test
            
                test
            
        
        
            
            pro
            
                pro
            
        
        
            
            pre
            
                pre
            
            
                
                    
                        src/main/resources/pre
                    
                
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            build-info
                            repackage
                        
                    
                
                
                    true
                
            
            
                org.apache.maven.plugins
                maven-assembly-plugin
                
                    false
                    
                        src/main/assembly/assembly.xml
                    
                
                
                    
                        make-assembly
                        package
                        
                            single
                        
                    
                
            

            
                org.apache.maven.plugins
                maven-resources-plugin
                2.6
                
                    UTF-8
                    ttf
                    pdf
                
            

            
                maven-antrun-plugin
                
                    
                        copy
                        package
                        
                            
                                
                                    
                                    
                                        
                                        
                                    
                                
                            
                        
                        
                            run
                        
                    
                
            

        
        
            
                src/main/java
                
                    ***.yml
                
                false
            
            
                src/main/resources
                false
                
                    fonts
    public String advanceBody(String msgType, String title, String image, String content, String messageUrl) {
        Map body = Maps.newHashMap();
        body.put("msgType", msgType);
        body.put("title", title);
        body.put("image", image);
        body.put("content", content);
        body.put("messageUrl", messageUrl);
        return JSON.toJSONString(body);//需要string,就把map转成string,不能硬拼接需要使用map
    }
42)拼接固定参数url,java Api(StrSubstitutor)指定字符拼接,${}符号中的占位符
//${agentId}必需以${}的形式存在,占位符
    public static void main(String[] args) {
        String url="dingtalk://dingtalkclient/action/open_micro_app?corpId=${corpId}&agentId=${agentId}&miniAppId=%s&pVersion=1&packageType=1&page=%2Fpages%2Fgoods%2Fgoods%3FproductsId%3D";
        HashMap map = new HashMap<>();
        map.put("corpId",122);
        map.put("agentId",1222);
        //参数为map,代替字符串中的对应位置,占位符
        StrSubstitutor strSubstitutor = new StrSubstitutor(map);
        String str = strSubstitutor.replace(url);
        System.out.println(str);
    }
43)SpringCloud Feign 传参问题及传输Date类型参数的时差(未能解决,换了方法) 44)sql语句优化(数据库优化,待学习) 1.查看sql执行过程
//sql执行过程 EXPLAIN关键字
EXPLAIN	select `id`, `corp_id`, `agent_id`, `suite_id`, `ding_user_id_added`, `create_time`, `update_time`, `auth_status`, `service_status`, `is_delete` from sys_corp_suite GROUP BY corp_id
			
			
EXPLAIN select id from sys_corp_suite where id='123456789'
2.结果

45)java8新特性对比(流的方式拿出集合中对应的指定属性,写法上的优化)
  //循环拿出userId
//所要操作的集合
List userList = sysCorpSuiteApi.findAddUser(item.getCorpId());

//1。lambda表达式
            List useridList = userList.stream().map(user -> {
                String dingUserId = user.getDingUserIdAdded();
                return dingUserId;
            }).collect(Collectors.toList());

//2。优化写法
List useridList = userList.stream().map(SysCorpSuite::getDingUserIdAdded).collect(Collectors.toList());
46)JAVA中常量使用常量类或者常量接口,还是使用枚举的区别

(具体情况具体分析,参考阿里巴巴开发手册)建议使用枚举类 https://blog.csdn.net/chenpeng19910926/article/details/76210117

47)浮点数之间的等值判断,不能使用==或equals使用方法

https://www.jianshu.com/p/dfc3ec4350e6(参考博客) 详见阿里巴巴开发手册

【强制】浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals
来判断。
说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进
制无法精确表示大部分的十进制小数,具体原理参考《码出高效》。
反例:
float a = 1.0F - 0.9F;
float b = 0.9F - 0.8F;
if (a == b) {
 // 预期进入此代码块,执行其它业务逻辑
 // 但事实上 a==b 的结果为 false
}
Float x = Float.valueOf(a);
Float y = Float.valueOf(b);
if (x.equals(y)) {
 // 预期进入此代码块,执行其它业务逻辑
 // 但事实上 equals 的结果为 false
}
正例:
(1) 指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。
float a = 1.0F - 0.9F;
float b = 0.9F - 0.8F;
float diff = 1e-6F;
if (Math.abs(a - b) < diff) {
 System.out.println("true");
}
(2) 使用 BigDecimal 来定义值,再进行浮点数的运算操作。
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);
if (x.compareTo(y) == 0) {
 System.out.println("true");
}
48)各种数据类型之间的比较方法选用【==和equals并不是全部适用的】(阿里巴巴见开发手册) 49)遍历map集合的(4+1种)【还有一个事java8:map.forEach】

尽量使用entrySet ,java8中推荐是红map.forEach((key,value)->{}), 详情参照阿里开发手册

50)一边循环一边删除集合中的数据(必须使用迭代器,不能使用forEach)
 while (iterator.hasNext()) {
             String id = iterator.next();
             if (!sysUserProductSettingApi.getMsgUserProductSetting(Long.valueOf(id))) {
                    iterator.remove();
                }
            }
51)递归拿捏(迷宫问题,理解小测试)
package com.example.l220109.my;

import org.junit.Test;


public class Rucursion {

    
    @Test
    public void demo() {
        // 构建一个 8 行 7 列的地图
        int[][] map = initMap(8, 7);
        printMap(map);
        // 一次性没有回溯的路线
        setWay(map, 1, 1, 6, 5);
//         这个点,是有回溯的路线
//        setWay(map, 1, 1, 4, 1);
        System.out.println("路线查找完毕");
        printMap(map);
    }

    
    public boolean setWay(int[][] map, int startX, int startY, int endX, int endY) {
        // 如果当结束点已经走过,表示已经到达了出口
//        System.out.println();
//        printMap(map); // 打开这个可以看到每一步的探索路径
        if (map[endX][endY] == 2) {
            return true;
        }
        // 那么开始我们的策略探索

        // 如果该点还没有走过,则可以尝试探索
        if (map[startX][startY] == 0) {
            // 先假定该点标可以通过,因为要去探索四周的点是否可以走
            map[startX][startY] = 2;
            // 下 -> 右 -> 上 -> 左
            // 根据策略:先往下走,如果可以走则返回 true
            if (setWay(map, startX + 1, startY, endX, endY)) {
                return true;
            }
            // 如果走不通,则继续往右边探索
            else if (setWay(map, startX, startY + 1, endX, endY)) {
                return true;
            }
            // 如果走不通,则继续往上边探索
            else if (setWay(map, startX - 1, startY, endX, endY)) {
                return true;
            }
            // 如果走不通,则继续往左边探索
            else if (setWay(map, startX, startY - 1, endX, endY)) {
                return true;
            }
            // 都走不通,表示改点是一个死点,四周都无法出去
            else {
                map[startX][startY] = 3;
                return false;
            }
        } else {
            // 如果不为 0,可能的情况是:1,2,3,这三种表示都表示不可以走
            return false;
        }
    }

    
    private int[][] initMap(int row, int cloum) {
        // 构建一个 8 行 7 列的地图
        int[][] map = new int[row][cloum];
        // 数字 1 表示挡板,构建一个有挡板的地图

        for (int i = 0; i < map[0].length; i++) {
            map[0][i] = 1;  // 顶部增加挡板
            map[map.length - 1][i] = 1;  // 底部增加挡板
        }

        for (int i = 0; i < map.length; i++) {
            map[i][0] = 1;  // 左侧增加挡板
            map[i][map[0].length - 1] = 1; // 右侧增加挡板
        }

        // 中间的其他固定挡板
        map[3][1] = 1;
        map[3][2] = 1;
        return map;
    }

    public void printMap(int[][] map) {
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map[0].length; j++) {
                System.out.print(map[i][j] + " ");
            }
            System.out.println();
        }
    }

    
    public static void main(String[] args) {
        int i = 7;
//        test(7);
        test2(7);
    }

    public static void test(int s) {
        // 是递归
        if (s > 1) {
            test(s - 1);
        }
        System.out.println(s);


    }

    public static void test2(int j) {
        // 是递归
        if (j == 1) {
            return;
        } else {
            test2(j - 1);
            System.out.println(j);
        }
    }
}

52)专业词汇类目,spu,sku

类目:类目是一个树状结构的系统,大体上可以分成4-5级。如手机->智能手机->苹果手机类目,在这里面,手机是一级类目,苹果手机是三级类目,也是叶子类目。

SPU:苹果6(商品聚合信息的最小单位),如手机->苹果手机->苹果6,苹果6就是SPU。

SKU:土豪金 16G 苹果6 (商品的不可再分的最小单元)。

从广义上讲,类目>SPU>SKU。

53)sql模糊搜索,索引问题

索引与优化like查询

    like %keyword 索引失效,使用全表扫描。但可以通过翻转函数+like前模糊查询+建立翻转函数索引=走翻转函数索引,不走全表扫描。like keyword% 索引有效。like %keyword% 索引失效,也无法使用反向索引。
54)说说count(*)、count(1)、count(列名)有什么区别?

https://juejin.cn/post/6854573219089907720

55)xml多条件模糊查询

    SELECT
    a.user_name,
    a.mobile,
    a.create_time,
    b.state
    FROM
    cb_uc_user_register a
    LEFT JOIN cb_uc_user_register_extends b ON a.id = b.user_id
    
     
            AND a.user_name like concat('%', #{userManagerListDto.userName},'%')
      
      
            AND b.state = #{userManagerListDto.state}
      
    

56)url拼接

dingtalk://dingtalkclient/action/open_micro_app?corpId=KaTeX parse error: Expected 'EOF', got '&' at position 9: {corpId}&̲agentId={agentId}&miniAppId=%s&pVersion=1&packageType=1&page=%2Fpages%2Fgoods%2Fgoods%3FproductsId%3D

dingtalk://dingtalkclient/action/open_micro_app?corpId=%s&agentId=%s&miniAppId=%s&pVersion=1&packageType=1&page=%s

57)MyBatisPlus多条件查询,组合查询

https://www.cnblogs.com/BNTang/articles/14584735.html

58)前后端交互Long和string

【强制】对于需要使用超大整数的场景,服务端一律使用 String 字符串类型返回,禁止使用 Long 类型

说明:Java 服务端如果直接返回 Long 整型数据给前端,JS 会自动转换为 Number 类型(注:此类型为双

精度浮点数,表示原理与取值范围等同于 Java 中的 Double)。Long 类型能表示的最大值是 2 的 63 次方

-1,在取值范围之内,超过 2 的 53 次方 (9007199254740992)的数值转化为 JS 的 Number 时,有些数

值会有精度损失。扩展说明,在 Long 取值范围内,任何 2 的指数次整数都是绝对不会存在精度损失的,所

以说精度损失是一个概率问题。若浮点数尾数位与指数位空间不限,则可以精确表示任何整数,但很不幸,

双精度浮点数的尾数位只有 52 位。

反例:通常在订单号或交易号大于等于 16 位,大概率会出现前后端单据不一致的情况,比如,“orderId”:

for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[0].length; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println();
}
}

public static void main(String[] args) {
    int i = 7;

// test(7);
test2(7);
}

public static void test(int s) {
    // 是递归
    if (s > 1) {
        test(s - 1);
    }
    System.out.println(s);


}

public static void test2(int j) {
    // 是递归
    if (j == 1) {
        return;
    } else {
        test2(j - 1);
        System.out.println(j);
    }
}

}

#### 52)专业词汇类目,spu,sku

类目:类目是一个树状结构的系统,大体上可以分成4-5级。如手机->智能手机->苹果手机类目,在这里面,手机是一级类目,苹果手机是三级类目,也是叶子类目。

SPU:苹果6(商品聚合信息的最小单位),如手机->苹果手机->苹果6,苹果6就是SPU。

SKU:土豪金 16G 苹果6 (商品的不可再分的最小单元)。



从广义上讲,类目>SPU>SKU。



#### 53)sql模糊搜索,索引问题

索引与优化like查询

1. like %keyword    索引失效,使用全表扫描。但可以通过翻转函数+like前模糊查询+建立翻转函数索引=走翻转函数索引,不走全表扫描。
2. like keyword%    索引有效。
3. like %keyword% 索引失效,也无法使用反向索引。





#### 54)说说count(*)、count(1)、count(列名)有什么区别?

https://juejin.cn/post/6854573219089907720



#### 55)xml多条件模糊查询

```java

    SELECT
    a.user_name,
    a.mobile,
    a.create_time,
    b.state
    FROM
    cb_uc_user_register a
    LEFT JOIN cb_uc_user_register_extends b ON a.id = b.user_id
    
     
            AND a.user_name like concat('%', #{userManagerListDto.userName},'%')
      
      
            AND b.state = #{userManagerListDto.state}
      
    

56)url拼接

dingtalk://dingtalkclient/action/open_micro_app?corpId=KaTeX parse error: Expected 'EOF', got '&' at position 9: {corpId}&̲agentId={agentId}&miniAppId=%s&pVersion=1&packageType=1&page=%2Fpages%2Fgoods%2Fgoods%3FproductsId%3D

dingtalk://dingtalkclient/action/open_micro_app?corpId=%s&agentId=%s&miniAppId=%s&pVersion=1&packageType=1&page=%s

57)MyBatisPlus多条件查询,组合查询

https://www.cnblogs.com/BNTang/articles/14584735.html

58)前后端交互Long和string

【强制】对于需要使用超大整数的场景,服务端一律使用 String 字符串类型返回,禁止使用 Long 类型

说明:Java 服务端如果直接返回 Long 整型数据给前端,JS 会自动转换为 Number 类型(注:此类型为双

精度浮点数,表示原理与取值范围等同于 Java 中的 Double)。Long 类型能表示的最大值是 2 的 63 次方

-1,在取值范围之内,超过 2 的 53 次方 (9007199254740992)的数值转化为 JS 的 Number 时,有些数

值会有精度损失。扩展说明,在 Long 取值范围内,任何 2 的指数次整数都是绝对不会存在精度损失的,所

以说精度损失是一个概率问题。若浮点数尾数位与指数位空间不限,则可以精确表示任何整数,但很不幸,

双精度浮点数的尾数位只有 52 位。

反例:通常在订单号或交易号大于等于 16 位,大概率会出现前后端单据不一致的情况,比如,“orderId”:

362909601374617692,前端拿到的值却是: 362909601374617660

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/735192.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号