這是博主自己在使用的一套easyui前端框架的后臺(tái)管理系統(tǒng)模版,包含了后端的Java代碼,已經(jīng)實(shí)現(xiàn)了菜單控制、權(quán)限控制功能,可以直接拿來(lái)使用。
springboot + mybatis + mybatis-plus實(shí)現(xiàn)的增刪查改完整項(xiàng)目,前端使用了easyui前端框架。https://gitee.com/he-yunlin/easyui-crud.git
目錄
功能介紹
一、菜單管理
菜單列表
角色-菜單列表
二、權(quán)限管理
權(quán)限列表
角色-權(quán)限列表
三、用戶管理
用戶列表
用戶-角色列表
四、歌曲管理
歌曲列表
五、系統(tǒng)功能
系統(tǒng)設(shè)置
初始化權(quán)限
代碼介紹
響應(yīng)狀態(tài)碼
統(tǒng)一響應(yīng)實(shí)體類
全局異常處理類
統(tǒng)一數(shù)據(jù)格式處理類
datagrid數(shù)據(jù)格式對(duì)象
獲取用戶登錄信息的工具類
基于easyui的表格過(guò)濾插件功能實(shí)現(xiàn)
基礎(chǔ)的分頁(yè)器
基礎(chǔ)的排序器
功能介紹
這是對(duì)本系統(tǒng)的一些簡(jiǎn)單的功能介紹。
一、菜單管理
菜單列表
點(diǎn)擊表格頭部工具欄的【添加】按鈕,會(huì)添加一條模板數(shù)據(jù)
/**
* 添加
*/
function insert() {
requestUrl = "/menu/insert";
ajaxPost(requestUrl, {
type: 1,
name: "xxx",
url: "/html/xxx_list.html",
icon: "icon-script"
}, function (response) {
showMsg(response.message);
$("#menu_list").datagrid("reload");
}, error);
}
修改功能是基于easyui的表格行內(nèi)編輯完成的,鼠標(biāo)選擇一行數(shù)據(jù),點(diǎn)擊頭部工具欄的【修改】按鈕,會(huì)開(kāi)啟該行的編輯。
點(diǎn)擊保存會(huì)向后臺(tái)控制器提交修改后的數(shù)據(jù),點(diǎn)擊取消則只會(huì)取消行內(nèi)編輯。
通過(guò)給表格添加結(jié)束編輯事件,當(dāng)表格行結(jié)束編輯,也就是調(diào)用了endEdit方法時(shí)觸發(fā)事件,會(huì)把data修改為修改后的行數(shù)據(jù)。
let data = {};
/**
* 保存
*/
function save() {
if (editingId != null) {
let datagrid = $("#menu_list");
// 只有結(jié)束編輯才能獲取到最新的值
datagrid.datagrid("endEdit", editingId);
ajaxPost(requestUrl, data, function () {
editingId = null;
datagrid.datagrid("reload");
}, error);
}
}
$(document).ready(function() {
$("#menu_list").datagrid({
url: "/menu/selectByPage",
method: "get",
height: 680,
fitColumns: true,
pagination: true,
onAfterEdit: function (index, row, changes) {
data = {
id: row.id,
type: row.type,
parentId: row.parentId,
url: changes.url ? changes.url : row.url,
name: changes.name ? changes.name : row.name,
icon: changes.icon ? changes.icon : row.icon
};
},
.....
};
};
刪除功能比較簡(jiǎn)單,就不介紹了~
角色-菜單列表
就是對(duì)角色的菜單進(jìn)行管理,目前只是基于父級(jí)菜單實(shí)現(xiàn),只需要給角色添加對(duì)應(yīng)的父類菜單即可讓該角色獲得該菜單下的所有子菜單的權(quán)限。
二、權(quán)限管理
權(quán)限列表
對(duì)系統(tǒng)資源權(quán)限(也就是控制器接口權(quán)限)進(jìn)行管理
父級(jí)權(quán)限的編號(hào)格式為為服務(wù)名_控制器名,子級(jí)權(quán)限的編號(hào)為服務(wù)名_控制器名_方法名。
權(quán)限初始化功能:一鍵自動(dòng)完成權(quán)限的初始化功能,會(huì)先刪除原來(lái)的權(quán)限,然后掃描控制器類的包,獲取所有控制器接口信息,并保存到數(shù)據(jù)庫(kù)。
涉及的后端代碼
@Override
public void resources() throws ClassNotFoundException {
// 刪除原來(lái)的權(quán)限
permissionMapper.delete(null);
// 掃描路徑
String basePackage = "cn.edu.sgu.www.controller";
// 獲取掃描結(jié)果
List<Permission> permissions = resourceScanner.scan(basePackage);
for (Permission permission : permissions) {
permissionMapper.insert(permission);
}
}
掃描工具類的代碼
package cn.edu.sgu.www.util;
import cn.edu.sgu.www.EasyuiCrud;
import cn.edu.sgu.www.annotation.AnonymityAccess;
import cn.edu.sgu.www.entity.Permission;
import cn.edu.sgu.www.enums.RequestMethod;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* 接口資源掃描工具類
* @author heyunlin
* @version 1.0
*/
@Component
public class ResourceScanner {
/**
* 服務(wù)名
*/
@Value("${spring.application.name}")
private String SERVICE_NAME;
private static List<String> classPaths = new ArrayList<>();
private static final List<Permission> resources = new ArrayList<>();
/**
* 掃描controller包下的目錄,生成權(quán)限
* @param basePackage controller包
* @return List<Permission>
* @throws ClassNotFoundException 類找不到時(shí)拋出異常
*/
public List<Permission> scan(String basePackage) throws ClassNotFoundException {
// 刪除掉上一次的數(shù)據(jù)
if (!resources.isEmpty()) {
resources.clear();
}
if (!classPaths.isEmpty()) {
classPaths.clear();
}
String classpath = EasyuiCrud.class.getResource("/").getPath();
String searchPath = classpath + basePackage.replace(".", "/");
classpath = classpath.replaceFirst("/", "");
classPaths = getClassPaths(new File(searchPath));
for(String classPath : classPaths) {
// 得到類的全限定名
classPath = classPath.replace(classpath.replace("/", "\\")
.replaceFirst("\\\\", ""), "")
.replace("\\", ".")
.replace(".class", "");
classpath = classPath.substring(classPath.indexOf(basePackage));
// 通過(guò)反射獲取類的信息
Class<?> cls = Class.forName(classpath);
// 獲取標(biāo)注在類上的@RequestMapping注解
RequestMapping requestMapping = cls.getAnnotation(RequestMapping.class);
// 構(gòu)建父權(quán)限
Permission parent = new Permission();
// 控制器類上的路徑
String prefix = "";
if(requestMapping != null) {
// path或者value
prefix = requestMapping.value().length > 0 ? requestMapping.value()[0] : requestMapping.path()[0];
parent.setType(0);
parent.setUrl(prefix);
parent.setId(SERVICE_NAME + "_" + cls.getSimpleName());
// 設(shè)置name
if (cls.isAnnotationPresent(Api.class)) {
Api api = cls.getAnnotation(Api.class);
if (api != null) {
// 類的接口文檔@Api注解的tags屬性值
String name = api.tags()[0];
parent.setName(name);
}
}
resources.add(parent);
}
Method[] methods = cls.getDeclaredMethods();
for (Method method : methods) {
getClassAnnotation(method, prefix, cls.getSimpleName(), parent.getId());
}
}
return resources;
}
/**
* 得到類上面的注解信息
* @param method Method
* @param prefix String 控制器類上@RequestMapping注解指定的路徑
* @param controllerName 控制器名稱
* @param parentId String 父級(jí)權(quán)限ID
*/
public void getClassAnnotation(Method method, String prefix, String controllerName, String parentId) {
// 構(gòu)建子權(quán)限
Permission permission = new Permission();
String url = null;
// 獲取url
if (method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
url = prefix + (requestMapping.value().length > 0 ? requestMapping.value()[0] : requestMapping.path()[0]);
String requestMethod = requestMapping.method().length > 0 ? requestMapping.method()[0].name() : "get";
permission.setMethod(RequestMethod.getValueByName(requestMethod));
} else if (method.isAnnotationPresent(GetMapping.class)) {
GetMapping getMapping = method.getAnnotation(GetMapping.class);
url = prefix + getMapping.value()[0];
permission.setMethod(RequestMethod.GET.getValue());
} else if (method.isAnnotationPresent(PostMapping.class)) {
PostMapping postMapping = method.getAnnotation(PostMapping.class);
url = prefix + postMapping.value()[0];
permission.setMethod(RequestMethod.POST.getValue());
}
// 處理URL
if(url != null && url.endsWith("/")) {
url = url.substring(0, url.length() - 1);
}
permission.setUrl(url);
// 設(shè)置value
if (method.isAnnotationPresent(ApiOperation.class)) {
ApiOperation operation = method.getAnnotation(ApiOperation.class);
if (operation != null) {
String name = operation.value();
permission.setName(name);
}
}
// 默認(rèn)值0
permission.setAnonymity(0);
if (method.isAnnotationPresent(AnonymityAccess.class)) {
AnonymityAccess annotation = method.getAnnotation(AnonymityAccess.class);
if (annotation != null) {
permission.setAnonymity(annotation.value() ? 1 : 0);
}
}
permission.setType(1);
permission.setParentId(parentId);
permission.setId(SERVICE_NAME + "_" + controllerName + "_" + method.getName());
resources.add(permission);
}
private List<String> getClassPaths(File path) {
if (path.isDirectory()) {
File[] files = path.listFiles();
if (files != null) {
for (File file : files) {
getClassPaths(file);
}
}
} else {
if (path.getName().endsWith(".class")) {
classPaths.add(path.getPath());
}
}
return classPaths;
}
}
角色-權(quán)限列表
角色權(quán)限的維護(hù),包括簡(jiǎn)單的增刪改和基于easyui樹(shù)實(shí)現(xiàn)的授權(quán)功能,以及超管賬戶的權(quán)限初始化功能。
授權(quán)功能:通過(guò)簡(jiǎn)單的復(fù)選框勾選/取消勾選來(lái)給角色分配權(quán)限
權(quán)限初始化功能:其實(shí)非常簡(jiǎn)單,就是查詢所有的資源權(quán)限,然后分配給超管用戶。
@Override
public void init(String userId) {
// 刪除用當(dāng)前戶所有角色的權(quán)限
rolePermissionMapper.deleteByUserId(userId);
// 查詢?nèi)孔訖?quán)限
List<Permission> list = permissionMapper.selectByType(PermissionType.ZQX.getValue());
list.forEach(permission -> {
RolePermission rolePermission = new RolePermission();
rolePermission.setId(null);
rolePermission.setRoleId(1);
rolePermission.setPermissionId(permission.getId());
rolePermissionMapper.insert(rolePermission);
});
}
三、用戶管理
因?yàn)檫@個(gè)部分的功能很簡(jiǎn)單,只有簡(jiǎn)單的crud,不做過(guò)多介紹。
用戶列表
用戶-角色列表
四、歌曲管理
歌曲列表
歌曲的維護(hù)、歌單導(dǎo)入/導(dǎo)出功能。
五、系統(tǒng)功能
系統(tǒng)設(shè)置
鼠標(biāo)移動(dòng)到右上方的下拉菜單,點(diǎn)擊【系統(tǒng)設(shè)置】打開(kāi)系統(tǒng)設(shè)置窗口。
修改密碼功能
?對(duì)密碼進(jìn)行加密存儲(chǔ)
@Override
public void updatePassword(UserPassUpdateDTO userPassUpdateDTO) {
// 用戶名
String username = userPassUpdateDTO.getUsername();
// 舊密碼
String oldPass = userPassUpdateDTO.getOldPass();
// 新密碼
String password = userPassUpdateDTO.getPassword();
// 驗(yàn)證兩次輸入的密碼是否相等
if (password.equals(userPassUpdateDTO.getRePass())) {
// 查詢用戶信息
String encodedPassword = selectByUsername(username).getPassword();
// 驗(yàn)證輸入的舊密碼是否正確
if (PasswordEncoder.matches(oldPass, encodedPassword)) {
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("username", username);
wrapper.set("password", PasswordEncoder.encode(password));
userMapper.update(wrapper.getEntity(), wrapper);
} else {
throw new GlobalException(ResponseCode.FORBIDDEN, "輸入的密碼不正確");
}
} else {
throw new GlobalException(ResponseCode.FORBIDDEN, "兩次輸入的密碼不一樣");
}
}
菜單控制功能:就是控制左側(cè)菜單的顯示,勾選/取消勾選對(duì)應(yīng)的菜單,然后點(diǎn)擊窗口右下角的【確定】按鈕提交修改。
初始化權(quán)限
這個(gè)按鈕的功能和權(quán)限列表的【初始化】按鈕是一樣的。
代碼介紹
前面已經(jīng)對(duì)這個(gè)系統(tǒng)做了一些簡(jiǎn)單的介紹,接下來(lái)介紹一下博主經(jīng)過(guò)多次實(shí)踐產(chǎn)出的一部分公共的Java代碼,可以直接使用。
響應(yīng)狀態(tài)碼
在枚舉中自定義了幾種響應(yīng)狀態(tài)碼
package cn.edu.sgu.www.restful;
/**
* 響應(yīng)狀態(tài)碼
* @author heyunlin
* @version 1.0
*/
public enum ResponseCode {
/**
* 請(qǐng)求成功
*/
OK(200),
/**
* 失敗的請(qǐng)求
*/
BAD_REQUEST(400),
/**
* 未授權(quán)
*/
UNAUTHORIZED(401),
/**
* 禁止訪問(wèn)
*/
FORBIDDEN(403),
/**
* 找不到
*/
NOT_FOUND(404),
/**
* 不可訪問(wèn)
*/
NOT_ACCEPTABLE(406),
/**
* 沖突
*/
CONFLICT(409),
/**
* 服務(wù)器發(fā)生異常
*/
ERROR(500);
private final Integer value;
ResponseCode(Integer value) {
this.value = value;
}
public Integer getValue() {
return value;
}
}
統(tǒng)一響應(yīng)實(shí)體類
包含提示信息、響應(yīng)數(shù)據(jù)和響應(yīng)狀態(tài)碼的web響應(yīng)實(shí)體類。
package cn.edu.sgu.www.restful;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import java.io.Serializable;
/**
* 響應(yīng)實(shí)體類
* @param <T>
* @author heyunlin
* @version 1.0
*/
@Data
public class JsonResult<T> implements Serializable {
private static final long serialVersionUID = 18L;
/**
* 響應(yīng)數(shù)據(jù)
*/
private T data;
/**
* 響應(yīng)狀態(tài)碼
*/
private Integer code;
/**
* 響應(yīng)提示信息
*/
private String message;
/**
* 成功提示
*/
private static final String successMessage = "請(qǐng)求成功";
public static JsonResult<Void> success() {
return success(successMessage);
}
public static JsonResult<Void> success(String message) {
return success(message, null);
}
public static <T> JsonResult<T> success(String message, T data) {
JsonResult<T> jsonResult = new JsonResult<>();
jsonResult.setCode(ResponseCode.OK.getValue());
jsonResult.setMessage(message);
jsonResult.setData(data);
return jsonResult;
}
public static JsonResult<Void> error(String message) {
JsonResult<Void> jsonResult = new JsonResult<>();
jsonResult.setCode(ResponseCode.ERROR.getValue());
jsonResult.setMessage(message);
return jsonResult;
}
public static JsonResult<Void> error(ResponseCode responseCode, Throwable e) {
return error(responseCode, e.getMessage() != null ? e.getMessage() : "系統(tǒng)發(fā)生異常,請(qǐng)聯(lián)系管理員!");
}
public static JsonResult<Void> error(ResponseCode responseCode, String message) {
JsonResult<Void> jsonResult = new JsonResult<>();
jsonResult.setCode(responseCode.getValue());
jsonResult.setMessage(message);
return jsonResult;
}
public static <T> JsonResult<JsonPage<T>> restPage(Page<T> page) {
JsonPage<T> jsonPage = JsonPage.restPage(page);
return success(successMessage, jsonPage);
}
}
全局異常處理類
package cn.edu.sgu.www.restful.handler;
import cn.edu.sgu.www.exception.GlobalException;
import cn.edu.sgu.www.restful.JsonResult;
import cn.edu.sgu.www.restful.ResponseCode;
import cn.edu.sgu.www.util.UserUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
/**
* 全局異常處理類
* @author heyunlin
* @version 1.0
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 處理GlobalException
* @param e GlobalException
* @return JsonResult<Void>
*/
@ExceptionHandler
public JsonResult<Void> handleGlobalException(GlobalException e) {
printMessage(e);
HttpServletResponse response = UserUtils.getResponse();
response.setStatus(e.getResponseCode().getValue());
return JsonResult.error(e.getResponseCode(), e);
}
/**
* 處理BindException
* @param e BindException
* @return JsonResult<Void>
*/
@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public JsonResult<Void> handleBindException(BindException e) {
printMessage(e);
BindingResult bindingResult = e.getBindingResult();
FieldError fieldError = bindingResult.getFieldError();
String defaultMessage = Objects.requireNonNull(fieldError).getDefaultMessage();
return JsonResult.error(ResponseCode.BAD_REQUEST, defaultMessage);
}
/**
* 處理Exception
* @param e Exception
* @return JsonResult<Void>
*/
@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public JsonResult<Void> handleException(Exception e) {
printMessage(e);
return JsonResult.error(ResponseCode.ERROR, e);
}
private void printMessage(Exception e) {
e.printStackTrace();
}
}
統(tǒng)一數(shù)據(jù)格式處理類
這個(gè)類需要注意的是,knife4j的接口路徑不能被處理,否則接口文檔的頁(yè)面內(nèi)容不能正常顯示。
# 配置統(tǒng)一數(shù)據(jù)格式返回處理類忽略的路徑
response:
ignore:
- /error
- /v2/api-docs
- /swagger-resources
package cn.edu.sgu.www.restful.handler;
import cn.edu.sgu.www.config.property.ResponseProperties;
import cn.edu.sgu.www.restful.JsonResult;
import cn.edu.sgu.www.util.UserUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.List;
/**
* 統(tǒng)一數(shù)據(jù)格式返回處理類
* @author heyunlin
* @version 1.0
*/
@Slf4j
@RestControllerAdvice
public class GlobalResponseHandler implements ResponseBodyAdvice {
private final List<String> ignore;
@Autowired
public GlobalResponseHandler(ResponseProperties responseProperties) {
ignore = responseProperties.getIgnore();
}
@Override
public boolean supports(MethodParameter parameter, Class type) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter parameter, MediaType mediaType, Class type
, ServerHttpRequest request, ServerHttpResponse response) {
// 返回值類型為JsonResult,則直接返回
if (body instanceof JsonResult) {
return body;
}
// 忽略的請(qǐng)求地址
String requestURI = UserUtils.getRequest().getRequestURI();
if (ignore.contains(requestURI)) {
return body;
}
log.debug("接口{}的返回值為:{}", requestURI, body.toString());
// 將返回值類型修改為JsonResult
JsonResult<Object> jsonResult = JsonResult.success(null, body);
if (body instanceof String) {
return JSON.toJSONString(jsonResult);
}
return jsonResult;
}
}
datagrid數(shù)據(jù)格式對(duì)象
基于easyui的datagrid組件要求返回的數(shù)據(jù)格式,封裝成的對(duì)象。
package cn.edu.sgu.www.restful;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* easyui datagrid數(shù)據(jù)格式對(duì)象
* @param <T>
* @author heyunlin
* @version 1.0
*/
@Data
public class JsonPage<T> implements Serializable {
private static final long serialVersionUID = 18L;
/**
* 總記錄數(shù)
*/
private Long total;
/**
* 查詢結(jié)果
*/
private List<T> rows;
/**
* 頁(yè)腳數(shù)據(jù)
*/
private T footer;
public static <T> JsonPage<T> restPage(Page<T> page) {
JsonPage<T> jsonPage = new JsonPage<>();
jsonPage.setTotal(page.getTotal());
jsonPage.setRows(page.getRecords());
return jsonPage;
}
}
獲取用戶登錄信息的工具類
基于shiro的獲取用戶登錄信息的工具類
package cn.edu.sgu.www.util;
import cn.edu.sgu.www.entity.User;
import cn.edu.sgu.www.exception.GlobalException;
import cn.edu.sgu.www.restful.ResponseCode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 獲取用戶信息的工具類
* @author heyunlin
* @version 1.0
*/
public class UserUtils {
/**
* 得到Subject對(duì)象
* @return Subject
*/
public static Subject getSubject() {
return SecurityUtils.getSubject();
}
/**
* 獲取登錄的用戶信息
* @return User
*/
public static User getUserInfo() {
Object object = getSubject().getPrincipal();
if (object == null) {
throw new GlobalException(ResponseCode.BAD_REQUEST, "獲取登錄信息失敗,當(dāng)前沒(méi)有用戶登錄。");
}
return (User) object;
}
/**
* 獲取登錄用戶的ID
* @return String
*/
public static String getUserId() {
return getUserInfo().getId();
}
/**
* 獲取登錄的用戶名
* @return String
*/
public static String getLoginUsername() {
return getUserInfo().getUsername();
}
public static HttpServletRequest getRequest() {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
if (attributes != null ) {
return ((ServletRequestAttributes) attributes).getRequest();
}
throw new GlobalException(ResponseCode.ERROR, "獲取request對(duì)象失敗");
}
public static HttpServletResponse getResponse() {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
if (attributes != null ) {
return ((ServletRequestAttributes) attributes).getResponse();
}
throw new GlobalException(ResponseCode.ERROR, "獲取response對(duì)象失敗");
}
}
基于easyui的表格過(guò)濾插件功能實(shí)現(xiàn)
package cn.edu.sgu.www.base;
import lombok.Data;
import java.io.Serializable;
/**
* 過(guò)濾規(guī)則
* @author heyunlin
* @version 1.0
*/
@Data
public class FilterRule implements Serializable {
private static final long serialVersionUID = 18L;
/**
* 字段名
*/
private String field;
/**
* 比較符
*/
private Operator op;
/**
* 字段值
*/
private String value;
}
package cn.edu.sgu.www.base;
/**
* 比較符
* @author heyunlin
* @version 1.0
*/
public enum Operator {
/**
* 包含
*/
contains,
/**
* 等于
*/
equal,
/**
* 不等于
*/
notequal,
/**
* 以...開(kāi)始
*/
beginwith,
/**
* 以...結(jié)尾
*/
endwith,
/**
* 小于
*/
less,
/**
* 小于或等于
*/
lessorequal,
/**
* 大于
*/
greater,
/**
* 大于或等于
*/
greaterorequal
}
基礎(chǔ)的分頁(yè)器
提供了分頁(yè)的功能,需要分頁(yè)功能的接口的參數(shù)類型只需要集成該類即可,將自動(dòng)獲得分頁(yè)功能。
package cn.edu.sgu.www.base;
import cn.edu.sgu.www.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.List;
/**
* 基礎(chǔ)分頁(yè)參數(shù)對(duì)象,包含頁(yè)數(shù)和每頁(yè)的記錄數(shù)
* @author heyunlin
* @version 1.0
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class Pager<T> extends Sorter implements Serializable {
private static final long serialVersionUID = 18L;
/**
* 頁(yè)數(shù)
*/
private Integer page = 1;
/**
* 每頁(yè)記錄數(shù)
*/
private Integer rows = 10;
/**
* 過(guò)濾規(guī)則
*/
private List<FilterRule> filterRules;
/**
* 根據(jù)Pager創(chuàng)建Page對(duì)象
* @param pager Pager
* @return Page
*/
public static <T> Page<T> ofPage(Pager<T> pager) {
return new Page<>(pager.getPage(), pager.getRows());
}
/**
* 根據(jù)Pager創(chuàng)建QueryWrapper對(duì)象
* @param pager Pager
* @return QueryWrapper<T>
*/
public static <T> QueryWrapper<T> getQueryWrapper(Pager<T> pager, boolean enableSort) {
QueryWrapper<T> wrapper = new QueryWrapper<>();
List<FilterRule> filterRules = pager.getFilterRules();
if (filterRules != null && !filterRules.isEmpty()) {
for (FilterRule filterRule : filterRules) {
// 字段名:轉(zhuǎn)為小寫字母+下劃線的格式
String field = StringUtils.toLower(filterRule.getField());
// 字段值
String value = filterRule.getValue();
if (StringUtils.isNotEmpty(value)) {
switch (filterRule.getOp()) {
case less:
wrapper.lt(field, value);
break;
case equal:
wrapper.eq(field, value);
break;
case greater:
wrapper.gt(field, value);
break;
case notequal:
wrapper.ne(field, value);
break;
case lessorequal:
wrapper.le(field, value);
break;
case greaterorequal:
wrapper.ge(field, value);
break;
case beginwith:
wrapper.likeLeft(field, value);
break;
case endwith:
wrapper.likeRight(field, value);
break;
case contains:
wrapper.like(field, value);
break;
default:
break;
}
}
}
}
if (enableSort) {
// 得到order by語(yǔ)句
String statement = getOrderByStatement(pager);
if (StringUtils.isNotEmpty(statement)) {
wrapper.last(statement);
}
}
return wrapper;
}
}
基礎(chǔ)的排序器
因?yàn)榍岸说幕A(chǔ)分頁(yè)器Pager已經(jīng)繼承了Sorter,所以開(kāi)啟了分頁(yè)功能后自動(dòng)獲得排序功能。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-804962.html
package cn.edu.sgu.www.base;
import cn.edu.sgu.www.exception.GlobalException;
import cn.edu.sgu.www.restful.ResponseCode;
import cn.edu.sgu.www.util.StringUtils;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 基礎(chǔ)排序?qū)ο?,包含排序字段和排序方? * @author heyunlin
* @version 1.0
*/
@Data
public class Sorter implements Serializable {
private static final long serialVersionUID = 18L;
/**
* 空字符串
*/
private static final String EMPTY_STR = "";
/**
* 分割符
*/
private static final String SEPARATOR = ",";
/**
* 排序方式
*/
private static final List<String> ORDER_STYLES = new ArrayList<>(2);
static {
ORDER_STYLES.add("asc");
ORDER_STYLES.add("desc");
}
/**
* 排序字段
*/
private String sort;
/**
* 排序方式:asc/desc
*/
private String order;
/**
* 根據(jù)查詢條件拼接得到order by語(yǔ)句
* @param sorter 分頁(yè)查詢條件
* @return String
*/
public static String getStatement(Sorter sorter) {
String sort;
String sortColumn = sorter.getSort();
// 處理排序字段
String[] sortArray = {};
if (StringUtils.isNotEmpty(sortColumn)) {
// 駝峰命名轉(zhuǎn)為下劃線
sort = StringUtils.toLower(sortColumn);
if (sort.contains(SEPARATOR)) {
sortArray = sort.split(SEPARATOR);
}
} else {
return EMPTY_STR;
}
// 處理排序方式
String[] orderArray = {};
String order = sorter.getOrder();
if (StringUtils.isNotEmpty(order)) {
if (order.contains(SEPARATOR)) {
orderArray = order.split(SEPARATOR);
}
} else {
return EMPTY_STR;
}
StringBuilder statement = new StringBuilder();
if (sortArray.length > 0 && orderArray.length > 0) {
int length = sortArray.length;
for (int i = 0; i < length; i++) {
String pagerSort = sortArray[i];
String pagerOrder = orderArray[i];
boolean result = validate(pagerSort, pagerOrder);
if (result) {
statement.append(pagerSort);
statement.append(" ");
statement.append(pagerOrder);
if (i < length - 1 ) {
statement.append(", ");
}
}
}
} else {
// " #{sort} #{order}“
statement.append(sort);
statement.append(" ");
statement.append(order);
}
return statement.toString();
}
/**
* 根據(jù)查詢條件拼接得到order by語(yǔ)句
* @param sorter 分頁(yè)查詢條件
* @return String
*/
public static String getOrderByStatement(Sorter sorter) {
String statement = getStatement(sorter);
if (StringUtils.isNotEmpty(statement)) {
return " order by " + statement;
} else {
return EMPTY_STR;
}
}
/**
* 往Pager的排序字段中添加排序
* @param pager Pager Pager對(duì)象
* @param sort String 排序字段
* @param order String 排序方式
* @return Pager<?> 返回重新設(shè)置排序字段和排序方式后的Pager對(duì)象
*/
public static Pager<?> append(Pager<?> pager, String sort, String order) {
boolean result = validatePager(pager);
if (result) {
String pagerSort = pager.getSort();
String pagerOrder = pager.getOrder();
pager.setSort(pagerSort.concat(SEPARATOR).concat(sort));
pager.setOrder(pagerOrder.concat(SEPARATOR).concat(order));
return pager;
}
return null;
}
/**
* 驗(yàn)證Pager對(duì)象的sort和order的值是否合法
* @param pager Pager<?>
* @return boolean
*/
private static boolean validatePager(Pager<?> pager) {
String sort = pager.getSort();
String order = pager.getOrder();
return validate(sort, order);
}
/**
* 驗(yàn)證sort和order的值是否合法
* @param sort 排序字段
* @param order 排序方式
* @return boolean
*/
private static boolean validate(String sort, String order) {
if (StringUtils.isEmpty(sort)) {
throw new GlobalException(ResponseCode.FORBIDDEN, "排序字段不允許為空!");
} else if (StringUtils.isEmpty(order)) {
throw new GlobalException(ResponseCode.FORBIDDEN, "排序方式不允許為空!");
} else if(!ORDER_STYLES.contains(order.toLowerCase())) {
throw new GlobalException(ResponseCode.FORBIDDEN, "排序方式不合法!");
}
return true;
}
}
好了,文章就分享到這里了,自己的一個(gè)小成果,分享給大家,希望對(duì)大家有所幫助~文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-804962.html
到了這里,關(guān)于分享一個(gè)基于easyui前端框架開(kāi)發(fā)的后臺(tái)管理系統(tǒng)模板的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!