JAVA开发笔记

发布于:2023-01-01 ⋅ 阅读:(563) ⋅ 点赞:(0)


前言

本文章用于记录个人开发的一些笔记


一、需求前期准备工作

TAPD上查看需求,gitlab上面创建属于自己的单独分支(分支最好以-yyyy-MM-dd作为后缀),然后拉取最新代码,本地idea切换分支进行开发。

常用命令  git pull     拉取

                git push   推送

                git checkout  xxxx  切换分支

二、需求实现阶段

1.关于代码编写方面

  1. 代码要书写规范,命名要言简意赅,mapper,service层方法命名可以参考mybatisplus。
  2. 得到的集合结果集也要见名知意,如existlist  等  
  3. 具体命名规范可参考java开发手册
  4. 常量类大写,动态配置类小写驼峰

2.代码细节方面

1.数据库数据处理方面

注意数据库能不全表扫描就别全表扫描,执行计划查看索引是否使用,尽量带条件查询

  1.    合理运用stream流,lamda表达式可以大幅度简化代码。
  2.    尽量避免在for循环中重复操作db,可以一次性查出来放入缓存中,如map,redis等。
  3.   数据量过大时,不要一次查出数据放入for中做比较,可以将我们要比较的数据当做数据库条件查询。在进行数据库操作时,能在数据库进行过滤的尽量在数据库过滤,避免一次性读取过多数据。 
  4.  数据库进行新增时,如果数据量过大,可进行批量操作,每100作为一个档次
 List<List<MobileBlackDO>> totalList = Lists.partition(mobileBlackDOList, MobileBlackConstant.ADD_MOBILE_BATCH_MAX_SIZE);
        totalList.forEach(singleList -> mobileBlackMapper.insertBatch(singleList));

对于有增删改多个操作时得加上事务,如图

   @Transactional(rollbackFor = Throwable.class)
    public void execute(ShardingContext shardingContext) {
        log.info("开始准备刷上行短信到黑名单");
        addMobileBlack();
        log.info("刷上行短信到黑名单结束");
    }

如果数据库数据量过大,一次查出来不方便,可分多次查询,一次可2000但是得一次性查到底,不可只查部分数据。如一开始记录本次id,具体代码如下

 //获取上次记录id,取出数据
        Long lastSmsUplinkId = smsUplinkIndexService.selectLastSmsUplinkId();
        List<SmsUplinkDO> collectList = new ArrayList<>();
        do {
            lastSmsUplinkId = smsUplinkService.selectIdByMarket(lastSmsUplinkId, MobileBlackConstant.ADD_MOBILE_PAGE_SIZE, collectList);
        } while (lastSmsUplinkId != null);
        //获取黑名单限制条件,过滤黑名单得到黑名单数据

    @Override
    public Long selectIdByMarket(Long lastSmsUplinkId, int pageSize, List<SmsUplinkDO> collectList) {
        List<SmsUplinkDO> existMarketList = smsUplinkMapper.selectByMarket(lastSmsUplinkId, pageSize);
        if (CollectionUtils.isEmpty(existMarketList)) {
            return null;
        }
        collectList.addAll(existMarketList);
        return existMarketList.get(existMarketList.size() - 1).getId();
    }

mapper要根据id排序,方便取出id,尽量避免子查询。

2.查询结果集方面

  1. 取出来的集合或者map如果接下来对他要进行判断操作,可以利用工具类进行非空判断。比如commonlang3包下面的collectionutils.isempey,或者stirngutils,如需返回结果为空,可利用collections.emptylist;
     CollectionUtils.isEmpty();
            StringUtils.isNotBlank();
            Collections.emptyList();
            BeanUtils.copyProperties();

3.其他

  1.  方法返回结果需要什么数据就返回什么数据,不需要service层返回controller所需数据
  2. 不要使用魔法数字,可放入该模块的常量类中。
  3. 不要在for中删除集合元素,应使用迭代器
  4. 在配置中心的项,如果后续有db操作,现判断是否有值  没值直接跳过不需要db操作。
  5. list集合contain方法是用迭代器进行遍历,使用set效率更高,set使用hasmap实现
  6. 对于for循环里面多个同一操作,可以提取在for循环外部进行。
  7. 嵌套不要太多层可以优化代码,必要时进行方法抽取

三、需求发布阶段

注意事项:配置中心数据一定要每个环境都得配上

配置中心默认pro环境,修改时得看清环境修改,不要修改别人配置

  1.        在dev环境测试完毕后,可在jenkins上打包发布,在ops上面发布到测试环境。如果有配置中心,也需将其发布到test的配置中心上。
  2. 先进行数据库ddl,dml的发布,保存文件在本地,提交到代码上。如果ops5即可走sql审核,审核完毕后即可发布。
  3. 配置中心数据一起发布,前面准备完成后
  4. 开始发布代码到pro环境。

pro环境需要审核,审核完毕才可发布!!!

发布后可到kinba上查看具体日志信息

为什么要使用分布式调度

  1. scheduled是单机分布式任务,如果每台机器都需要执行就可以使用scheduled。比如刷新到本地缓存,本地缓存是独有的因此每台机器都得需要。
  2. elastic-job是微服务的定时任务调度,更适合于不需要每台机器都执行的任务。比如刷新到mysql或者redis等操作,只需要一台机器执行即可,可配置策略,指定机器执行,而不是每台机器都执行。而且可以加快执行速度,负载均衡
  3. 对于数据量太大的任务就进行分片,加快处理速度

总结说就是:

  1. 为了将大的拆成小的,分成多份各自执行各自的,但是都是为了完成一个需求
  2. 集群中都是同样功能,但是定时器只需要其中一个进行执行就可以

🔗https://blog.csdn.net/qq_42370967/article/details/119707981

四、mybatisplus

        mybatis返回的map是只能返回一个的,遇到多的就会报错,会将select后面的字段的名称作为key,值作为value。

五、小结

类的初始化会一开始就保证给所有成员变量初始化,然后再掉对应的初始化语句,其次才是构造函数初始化。

双重for循环不可取,少用,如果要比较里面的属性,可以使用map,然后map.get获取

利用URLConnection来发送POST和GET请求 - 晴空~万里 - 博客园

springSecurity学习笔记

https://download.csdn.net/download/weixin_46365049/87274480
SpringSecurity学习记录(WebSecurityConfigurerAdapter被弃用,SecurityConfig新玩法)_学习_还有很多事要做啊.-DevPress官方社区


响应写出工具类

   public static void write(HttpServletResponse response, Object result) {
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        try (PrintWriter writer = response.getWriter()) {
            writer.write(JSON.toJSONString(result));
            writer.flush();
        } catch (IOException ex) {
            log.error("response write detected error", ex);
        }
    }

bean复制工具类

@Data
@Slf4j
public final class BeanCopyUtils {

    private BeanCopyUtils() {
    }

    /**
     * 复制单个bean
     */
    public static <S, T> T copyBean(S sourceBean, Class<T> targetClass) {
        try {
            T t = targetClass.newInstance();
            BeanUtils.copyProperties(sourceBean, t);
            System.out.println(10 / 0);
            return t;
        } catch (Exception e) {
            e.printStackTrace();
            log.info("错误:{}", e.getMessage());
            return null;
        }
    }

    /**
     * 复制list集合
     */
    public static <S, T> List<T> copyList(List<S> sourceList, Class<T> targetClass) {
        return sourceList.stream().map(s -> copyBean(s, targetClass)).filter(Objects::nonNull).collect(Collectors.toList());
    }



    public static void main(String[] args) {
        Student student = new Student("zs", "男");
        System.out.println(copyBean(student, Person.class));
        List<Student> students = Arrays.asList(student, new Student("xiaohong", "女"));
        System.out.println(copyList(students, Person.class));
    }
}

 vo可以复用,可以在每个do里面写一个静态方法转成vo,然后查询详情和查询list的可以服用。

dto也可以复用,没必要一个crud接口写一个dto或者vo。

controller  命名简单明了

eg: querylist  queryInfo 

更新或者新增接口  DTO接受  查询接口xxxQuery接收  返回参数VO返回

。service参考mp

分页:

/**
 * @author pengxiaoxi
 * @Description
 * @date 2022/12/21 18:01
 **/
@Data
public class PageParameter implements Serializable {

    private static final long serialVersionUID = 5393527808721863129L;

    private static final Integer DEFAULT_PAGE_SIZE = 10;

    private Integer currentPage;

    private Integer pageSize;

    private Integer prePage;

    private Integer nextPage;

    private Integer offset;

    private Integer totalCount;

    private Integer totalPage;

    public PageParameter() {
        this.currentPage = 1;
        this.pageSize = DEFAULT_PAGE_SIZE;
    }

    public PageParameter(final Integer currentPage, final Integer pageSize) {
        this.currentPage = Objects.isNull(currentPage) || currentPage <= 0 ? 1 : currentPage;
        this.pageSize = Objects.isNull(pageSize) || pageSize <= 0 ? DEFAULT_PAGE_SIZE : pageSize;
        this.offset = (this.currentPage - 1) * this.pageSize;
    }

    public PageParameter(final Integer currentPage, final Integer pageSize, final Integer totalPage) {
        this.currentPage = Objects.isNull(currentPage) || currentPage <= 0 ? 1 : currentPage;
        this.pageSize = Objects.isNull(pageSize) || pageSize <= 0 ? DEFAULT_PAGE_SIZE : pageSize;
        this.offset = (this.currentPage - 1) * this.pageSize;
        this.prePage = currentPage <= 1 ? 1 : currentPage - 1;
        this.totalPage = (int) Math.ceil((double) totalPage / (double) this.pageSize);
        this.nextPage = this.currentPage >= totalPage ? totalPage : this.currentPage + 1;
        this.totalCount = totalPage;
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonPager<T> implements Serializable {

    private static final long serialVersionUID = -6143244580674359019L;

    private List<T> dataList;

    private Integer count;
}
public class PageResultUtils implements Serializable {

    private static final long serialVersionUID = 714852774118107467L;

    public static <T> CommonPager<T> result(final Supplier<List<T>> listSupplier, final Supplier<Integer> countSupplier) {
        Integer count = countSupplier.get();
        if (Objects.isNull(count) || count <= 0) {
            return new CommonPager<>(Collections.emptyList(), 0);
        }
        return new CommonPager<>(listSupplier.get(), count);
    }
}

实现applicationaware接口注入上下文

public class ApplicationContextAware implements org.springframework.context.ApplicationContextAware, BeanNameAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        doSetApplicationContext(applicationContext);
    }

    private static void doSetApplicationContext(ApplicationContext applicationContext) {
        ApplicationContextAware.applicationContext = applicationContext;
    }

    public static <T> T getByClass(Class<T> tClass) {
        return applicationContext.getBean(tClass);
    }

    @Override
    public void setBeanName(String s) {

    }
}

总结

简单记录,间隔更新


网站公告

今日签到

点亮在社区的每一天
去签到