Springboot+Layui新项目总结

Springboot+Layui新项目总结,第1张

Springboot+Layui新项目总结 与平时项目进行对比 不同 对比

  自己的项目:传统创建mapper,然后在相应的mapper方法上加对应的注解@Select、@Update诸如此类的方法,最后service层直接调用mapper。然后controller直接用service然后统一回复个result就结束了

 公司的项目:

1、sql

sql都是封装好的,写在resource/sql-ext select id, company_code from sys_company where company_code in (:companyCodes)

(:companyCodes)代表传进的参数
其中我发现了有个在参数前面有个:符号,这是因为防止sql注入,还有提高性能。所以这样写的话,一般要在参数前面加:

总结:拆分得不能再拆分,好维护好修改

2、model

公司的实体类都是在model下。公司创建了一些基于@MappedSuperclass注解的model用于代码复用

《1》标注为@MappedSuperclass的类将不是一个完整的实体类,他将不会映射到数据库表,但是他的属性都将映射到其子类的数据库字段中。

《2》标注为@MappedSuperclass的类不能再标注@Entity或@Table注解,也无需实现序列化接口。
所以有很多model是extends ***Model(各式各样的通用属性)。如果不需要用到通用属性的话或者本身作为被通用的类也就是有@MappedSuperclass注解的类,就得implements Model //import com.chinaservices.jpa.Model

Model源码

public interface Model extends Serializable {
    void setCompanyId(Long var1);

    void setCreator(Long var1);

    void setCreateTime(Date var1);

    void setModifier(Long var1);

    void setModifyTime(Date var1);
}

可以看出这是一种规范,也就意味着每个model都必须要有这些方法

总结:规范,复用再复用,省事儿

3、bean
bean文件夹下,会为条件创建相应的condition、为增加创建相应的item、为搜索创建相应的Query

例如:

其中

Condition extends PageCondition(如果不是PageCondition而是其他Condition,其原因也是因为复用属性,但最终还是会继承Condition)

//PageCondition里有3个参数,可以看出是用于分页

private Integer pageSize;
private Integer pageNumber;
private String orderBy;

Item implements Item

//Item里有2个属性,是为了规范,一定要加这2个属性

void setModifier(Long var1);

void setModifyTime(Date var1);

Query implements Query

//Query啥都没有,不过估计是没有要规范的,但写出来还是因为代码规范

 以上都是import com.chinaservices.jpa.*

Condition

用来写参数,例如

public class DispatchGpsCondition extends WmsPageCondition {

    private String startTime;
    private String endTime;
    private String terminalId;

    public String getStartTime() {
        return startTime;
    }

    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }

    public String getEndTime() {
        return endTime;
    }

    public void setEndTime(String endTime) {
        this.endTime = endTime;
    }

    public String getTerminalId() {
        return terminalId;
    }

    public void setTerminalId(String terminalId) {
        this.terminalId = terminalId;
    }
}

这段代码是为了查询GPS,其中sql中需要三个参数,一个是id还有2个分别是开始时间和结束时间

,咱们可以看看对应的sql文件便知

sql

select
a.id,
a.gps_time,
a.terminal_id,
a.lat,
a.lng as lon
from cs_gps_pack_${terminalId} a
where
a.gps_time >= :startTime
and a.gps_time <= :endTime

Query

这个就无需贴出来了,因为它写的是查询表中需要查询到的数据,由于太多,不想发。格式还是一样,无非就是private 巴拉巴拉,然后getset。

Item

也是private巴拉巴拉加getset,它写的变量是需要更新或者新增的数据。
 

总结:拆分再拆分,好维护好拓展好****

4、Service

可以说Service是将bean和sql结合起来进行crud *** 作。

公司的Service 都是继承于WmsbaseService

public class WmsbaseService extends baseService {

    private static String PRIMARY_KEY = "id";
    @Autowired
    protected CommonJpaRepository dao;
    @Autowired
    protected SqlExecutor sqlExecutor;

    public  boolean saveOrUpdate(Class modelClass, Item item, InsertPreSave preSave) {
        SessionUserInfo sessionUserInfo = SessionContext.getSessionUserInfo();
        item.setModifier(sessionUserInfo.getUserId());
        item.setModifyTime(new Date());

        if (EmptyUtil.isEmpty(ClassUtil.getPropertyValue(item, PRIMARY_KEY))) {
            try {
                T model = modelClass.newInstance();
                BeanUtil.copyProperties(item, model);
                model.setCreator(sessionUserInfo.getUserId());
                model.setCreateTime(new Date());
                model.setCompanyId(sessionUserInfo.getCompanyId());
                preSave.accept(model);
                dao.insert(model);
                BeanUtil.copyProperties(model, item);
            } catch (Exception e) {
            	logger.error(e.getMessage());
                return false;
            }
        } else {
            dao.update(modelClass, item);
        }
        return true;
    }

    public boolean saveOrUpdate(Class modelClass, Item item) {

        SessionUserInfo sessionUserInfo = SessionContext.getSessionUserInfo();
        if(null == sessionUserInfo){
            item.setModifier(-1L);
        }else {
            item.setModifier(sessionUserInfo.getUserId());
        }
        item.setModifyTime(new Date());

        if (EmptyUtil.isEmpty(ClassUtil.getPropertyValue(item, PRIMARY_KEY))) {
            try {
                Model model = (Model) modelClass.newInstance();
                BeanUtil.copyProperties(item, model);
                if(null == sessionUserInfo){
                    model.setCreator(-1L);
                } else {
                    model.setCreator(sessionUserInfo.getUserId());
                    model.setCompanyId(sessionUserInfo.getCompanyId());
                }
                model.setCreateTime(new Date());
                dao.insert(model);
                BeanUtil.copyProperties(model, item);
            } catch (Exception e) {
            	logger.error(e.getMessage());
                return false;
            }
        } else {
            dao.update(modelClass, item);
        }
        return true;
    }

    public void preSave(Item item) {
        SessionUserInfo sessionUserInfo = SessionContext.getSessionUserInfo();
        if(null == sessionUserInfo){
            item.setModifier(-1L);
        }else {
            item.setModifier(sessionUserInfo.getUserId());
        }
        item.setModifyTime(new Date());
    }

    public void preSave(Model model) {
        SessionUserInfo sessionUserInfo = SessionContext.getSessionUserInfo();
        if (EmptyUtil.isNotEmpty(sessionUserInfo)){
            model.setModifier(sessionUserInfo.getUserId());
        }else {
            model.setModifier(-1L);
        }
        model.setModifyTime(new Date());
        if (EmptyUtil.isEmpty(ClassUtil.getPropertyValue(model, PRIMARY_KEY))) {
            if (EmptyUtil.isNotEmpty(sessionUserInfo)){
                model.setCreator(sessionUserInfo.getUserId());
                model.setCompanyId(sessionUserInfo.getCompanyId());
            }else {
                model.setCreator(-1L);
            }
            model.setCreateTime(new Date());
        }
    }
    //接口用preSave,没有session
    public void ediPreSave(Model model) {
        model.setModifier(1L);
        model.setModifyTime(new Date());
        if (EmptyUtil.isEmpty(ClassUtil.getPropertyValue(model, PRIMARY_KEY))) {
            model.setCreator(1L);
            model.setCreateTime(new Date());
        }
    }
}

saveOrUpdate():见名知其意,保存或者更新。有2种方式,一个是三个参数,一个是两个参数。其中因为是需求不一样,所以有不同的方法。很容易发现这两个方法的参数之中的区别就是多了一个InsertPreSave preSave,而这个参数只用在一句话上:

preSave.accept(model);

看看源码

@FunctionalInterface
public interface InsertPreSave {
    void accept(T t);

    default Consumer andThen(Consumer after) {
        Objects.requireNonNull(after);
        return (T t) -> {
            accept(t);
            after.accept(t);
        };
    }
}

里面只有一个方法Object.requireNonNull(),这个方法只是进行了一个简单的判断, 如果所要判断的元素为 null, 则返回空指针异常 NullPointerException, 否则直接返回对应的对象。

之所以多了个这个参数的原因是:

首先, 从这个方法的名称可以看出, 这个方法使用的场景是, 我们使用一个对象的方法时, 正常的运行状态应该能保证这个对象的引用非空, 如果这个对象为空了, 那一定是其他某个地方出错了, 所以我们应该抛出一个异常, 我们不应该在这里处理这个非空异常.

其次, 这里涉及到一个很重要的编程思想, 就是 Fail-fast 思想, 翻译过来就是, 让错误尽可能早的出现, 不要等到我们很多工作执行到一半之后才抛出异常, 这样很可能使得一部分变量处于异常状态, 出现更多的错误. 这也是 requireNonNull 这个方法的设计思想, 让错误尽早出现. 使用这个方法, 我们明确的抛出异常, 发生错误时, 我们立刻抛出异常.

说白了就是debug会更明确,更简洁

下面还有两个preSave()方法,两者差别又是参数不一样

带Item的preSave()方法是用EmptyUtil.isNotEmpty(sessionUserInfo)判断session是否存在,不存在则返回-1,存在则把用户id存入item的某个值中

带Model的preSave()方法与上一个的不同地方在于多了2个判断,首先是if(EmptyUtil.isEmpty(ClassUtil.getPropertyValue(model, PRIMARY_KEY)))

这个判断是用于判断类的方法,通俗来讲就是通过方法的修饰符(public/protected/private/package),来判断方法的调用者是否可以访问该方法

其次是EmptyUtil.isNotEmpty(sessionUserInfo)再次判断session是否存在,如果存在则设置用户信息以及公司的信息给model,我猜测应该是很重要的信息,所以需要多重判断

最后一个方法ediPreSave()方法已经很明了了,就是没有session的情况,也就是只用判断if(EmptyUtil.isEmpty(ClassUtil.getPropertyValue(model, PRIMARY_KEY)))即可,判断通过就赋值。

同时我们发现,WmsbaseService又继承于LoggerFactory,点进去看了一下源码,里面只有一个方法

public abstract class baseService {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    public baseService() {
    }
}

查了一下,说是使用指定类初始化日志对象,在日志输出的时候,可以打印出日志信息所在类
如:Logger logger = LoggerFactory.getLogger(Actions.class);
logger.debug("日志信息");
将会打印出: Actions : 日志信息

WmsbaseService还有2个开头的

@Autowired
protected CommonJpaRepository dao;
@Autowired
protected SqlExecutor sqlExecutor;

其中CommonJpaRepository即公司封装好的JpaRepository,这用到了spring data jpa的知识,也就意味着里面的方法可以直接 *** 作数据库

而SqlExecutor则是sql执行器,也是执行数据库 *** 作的

看了公司的某个Service类

(1)分页 *** 作和复杂查询的 *** 作使用SqlExecutor里的方法

(2)增加更新 *** 作则用WmsbaseService里面的方法

(3)删除简单查询不需要分页还有校验判断之类的用CommonJpaRepository里的方法

其实还是得根据情况来用方法。。。。。。

5、Controller

在每个方法的上面还多加一个注解,例如

@Log(model = "运输管理", description = "装货明细分页查询")

说白了就是加了日志

方法的类型如果是自己的项目是Result,而公司的则是 ResponseData<?>,当然这个也不是固定的,还是得看情况而言

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5682994.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存