JavaQuarkBBS源码

时间:2019-04-18
本文章向大家介绍JavaQuarkBBS源码,主要包括JavaQuarkBBS源码使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

JavaQuarkBBS是github上的一个社区论坛,里面包含论坛系统,后台管理,手机端(未完成),聊天室等。
原地址如下: https://github.com/ChinaLHR/JavaQuarkBBS

项目结构如下图

 

systemv2.png

 

这里quark-common提供持久化层服务。在此基础上还提供了一套mvc模板。代码如下

BaseController

public class BaseController {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    protected QuarkResult restProcessor(ResultProcessor processor){
        QuarkResult result = null;
        try{
            result = processor.process();
        }
        catch (ServiceProcessException e1){
            logger.error("ServiceProcess Error Log :"+e1.getLocalizedMessage(),e1);
            result = QuarkResult.error(e1.getMessage());
        }
        catch (Exception e){
            logger.error("Error Log :"+e.getLocalizedMessage(),e);
            result = QuarkResult.error("服务器出现异常");
        }

        return result;
    }
}

BaseService

public interface BaseService<T> {

    T findOne(int key);
    T save(T entity);
    void delete(Object key);
    List<T> findAll();

    /**
     * 批量删除
     * @param iterable
     */
    void deleteInBatch(Iterable<T> iterable);

    /**
     * 批量查找
     * @param iterable
     * @return
     */
    List<T> findAll(Iterable<Integer> iterable);

    /**
     * 批量保存
     * @param iterable
     * @return
     */
    List<T> save(Iterable<T> iterable);

}

BaseServiceImpl

public class BaseServiceImpl<E extends JpaRepository,T> implements BaseService<T>{

    @Autowired
    protected E repository;

    @Override
    public T findOne(int key) {
        return (T) repository.findOne(key);
    }

    @Override
    public T save(T entity) {
        return (T) repository.save(entity);
    }

    @Override
    public void delete(Object key) {
        repository.delete(key);
    }

    @Override
    public List<T> findAll() {
       return repository.findAll();
    }

    @Override
    public void deleteInBatch(Iterable<T> iterable) {
        repository.deleteInBatch(iterable);
    }

    @Override
    public List<T> findAll(Iterable<Integer> iterable) {
        return repository.findAll(iterable);
    }

    @Override
    public List<T> save(Iterable<T> iterable) {
        return repository.save(iterable);
    }


}

ResultProcessor

@FunctionalInterface
public interface ResultProcessor {
    QuarkResult process();     //QuarkResult为相应数据dto
}

那么作者是如何使用这套模板的呢?请看如下代码

Controller层

public class AdminUserController extends BaseController {

    @Autowired
    private AdminUserService adminUserService;

    @GetMapping
    public PageResult getAll(AdminUser adminUser, String draw,
                             @RequestParam(required = false, defaultValue = "1") int start,
                             @RequestParam(required = false, defaultValue = "10") int length) {
        int pageNo = start / length;
        Page<AdminUser> page = adminUserService.findByPage(adminUser, pageNo, length);
        PageResult<List<AdminUser>> result = new PageResult<>(
                draw,
                page.getTotalElements(),
                page.getTotalElements(),
                page.getContent());
        return result;
    }

 //此处省略代码
}

Service层接口

public interface AdminUserService extends BaseService<AdminUser>{

    AdminUser findByUserName(String username);

    Page<AdminUser> findByPage(AdminUser adminUser, int pageNo, int length);

    void saveAdmin(AdminUser entity);

    void saveAdminRoles(Integer uid,Integer[] roles);

    void saveAdminEnable(Integer[] ids);
}

Service层实现

@Service
@Transactional
public class AdminUserServiceImpl extends BaseServiceImpl<AdminUserDao, AdminUser> implements AdminUserService {

    @Autowired
    private RoleService roleService;

    @Override
    public AdminUser findByUserName(String username) {
        return repository.findByUsername(username);
    }

    @Override
    public Page<AdminUser> findByPage(AdminUser adminUser, int pageNo, int length) {
        PageRequest pageable = new PageRequest(pageNo, length);

        Specification<AdminUser> specification = new Specification<AdminUser>() {

            @Override
            public Predicate toPredicate(Root<AdminUser> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Integer> $id = root.get("id");
                Path<String> $username = root.get("username");
                Path<Integer> $enable = root.get("enable");

                ArrayList<Predicate> list = new ArrayList<>();
                if (adminUser.getId() != null) list.add(criteriaBuilder.equal($id, adminUser.getId()));
                if (adminUser.getEnable() != null) list.add(criteriaBuilder.equal($enable, adminUser.getEnable()));
                if (adminUser.getUsername() != null)
                    list.add(criteriaBuilder.like($username, "%" + adminUser.getUsername() + "%"));

                Predicate predicate = criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
                return predicate;
            }
        };

        Page<AdminUser> page = repository.findAll(specification, pageable);

        return page;
    }

}

1.参照上面的代码可以看出,作者是通过抽象出来BaseServiceBaseServiceImpl来将所有的基本crud等操作抽象出来,将DAO和实体类直接写到定义里,省着以后手动注入了,这是一个挺好的方法,并且给后续的开发人员一个统一的规范,避免出错。

缺点是serviceImpl类的实现定义起来很长,比如

public class AdminUserServiceImpl extends BaseServiceImpl<AdminUserDao, AdminUser> implements AdminUserService

2.此外在BaseController中通过restProcessor方法,来统一所有的Controller操作,子类通过写匿名函数的形式来处理具体逻辑,这样写的好处可能是保证了controller中的请求都调用统一的方法restProcessor()和接收了统一的返回值QuarkResult,并且抽象了try-catch方法,节省代码量,统一异常捕获。
这样所有的子类controller都需要实现

QuarkResult result = restProcessor(() -> {
          //匿名函数卸载这里即可,只需要返回QuarkResult实例。
        });

3.还有一点函数式接口ResultProcessor使用的@FunctionalInterface注解

通过JDK8源码javadoc,可以知道这个注解有以下特点:
1、该注解只能标记在"有且仅有一个抽象方法"的接口上。

2、JDK8接口中的静态方法和默认方法,都不算是抽象方法。

3、接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。

4、该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。

注意:@FunctionalInterface标记在接口上,“函数式接口”是指仅仅只包含一个抽象方法的接口。

如果一个接口中包含不止一个抽象方法,那么不能使用@FunctionalInterface,编译会报错。
比如下面这个接口就是一个正确的函数式接口:

@FunctionalInterface  
public interface TestInterface {  
  
    // 抽象方法  
    public void sub();  
  
    // java.lang.Object中的方法不是抽象方法  
    public boolean equals(Object var1);  
  
    // default不是抽象方法  
    public default void defaultMethod(){  
  
    }  
  
    // static不是抽象方法  
    public static void staticMethod(){  
  
    }  
}  

 



原文链接:https://www.jianshu.com/p/dde71c67e676