分享一个基于easyui前端框架开发的后台管理系统模板

这是博主自己在使用的一套easyui前端框架的后台管理系统模版,包含了后端的Java代码,已经实现了菜单控制、权限控制功能,可以直接拿来使用。

springboot + mybatis + mybatis-plus实现的增删查改完整项目,前端使用了easyui前端框架。icon-default.png?t=N7T8https://gitee.com/he-yunlin/easyui-crud.git

目录

功能介绍

一、菜单管理

菜单列表

角色-菜单列表

二、权限管理

权限列表

角色-权限列表

三、用户管理

用户列表

用户-角色列表

四、歌曲管理

歌曲列表

五、系统功能

系统设置

初始化权限

代码介绍

响应状态码

统一响应实体类

全局异常处理类

统一数据格式处理类

datagrid数据格式对象

获取用户登录信息的工具类

基于easyui的表格过滤插件功能实现

基础的分页器

基础的排序器


功能介绍

这是对本系统的一些简单的功能介绍。

一、菜单管理

菜单列表

点击表格头部工具栏的【添加】按钮,会添加一条模板数据

/*** 添加*/
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的表格行内编辑完成的,鼠标选择一行数据,点击头部工具栏的【修改】按钮,会开启该行的编辑。

点击保存会向后台控制器提交修改后的数据,点击取消则只会取消行内编辑。

通过给表格添加结束编辑事件,当表格行结束编辑,也就是调用了endEdit方法时触发事件,会把data修改为修改后的行数据。

let data = {};/*** 保存*/
function save() {if (editingId != null) {let datagrid = $("#menu_list");// 只有结束编辑才能获取到最新的值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};},.....};};

删除功能比较简单,就不介绍了~

角色-菜单列表

就是对角色的菜单进行管理,目前只是基于父级菜单实现,只需要给角色添加对应的父类菜单即可让该角色获得该菜单下的所有子菜单的权限。

二、权限管理

权限列表

对系统资源权限(也就是控制器接口权限)进行管理

父级权限的编号格式为为服务名_控制器名,子级权限的编号为服务名_控制器名_方法名。

权限初始化功能:一键自动完成权限的初始化功能,会先删除原来的权限,然后扫描控制器类的包,获取所有控制器接口信息,并保存到数据库。

涉及的后端代码

    @Overridepublic void resources() throws ClassNotFoundException {// 删除原来的权限permissionMapper.delete(null);// 扫描路径String basePackage = "cn.edu.sgu.www.controller";// 获取扫描结果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 {/*** 服务名*/@Value("${spring.application.name}")private String SERVICE_NAME;private static List<String> classPaths = new ArrayList<>();private static final List<Permission> resources = new ArrayList<>();/*** 扫描controller包下的目录,生成权限* @param basePackage controller包* @return List<Permission>* @throws ClassNotFoundException 类找不到时抛出异常*/public List<Permission> scan(String basePackage) throws ClassNotFoundException {// 删除掉上一次的数据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));// 通过反射获取类的信息Class<?> cls = Class.forName(classpath);// 获取标注在类上的@RequestMapping注解RequestMapping requestMapping = cls.getAnnotation(RequestMapping.class);// 构建父权限Permission parent = new Permission();// 控制器类上的路径String prefix = "";if(requestMapping != null) {// path或者valueprefix = requestMapping.value().length > 0 ? requestMapping.value()[0] : requestMapping.path()[0];parent.setType(0);parent.setUrl(prefix);parent.setId(SERVICE_NAME + "_" + cls.getSimpleName());// 设置nameif (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 父级权限ID*/public void getClassAnnotation(Method method, String prefix, String controllerName, String parentId) {// 构建子权限Permission permission = new Permission();String url = null;// 获取urlif (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());}// 处理URLif(url != null && url.endsWith("/")) {url = url.substring(0, url.length() - 1);}permission.setUrl(url);// 设置valueif (method.isAnnotationPresent(ApiOperation.class)) {ApiOperation operation = method.getAnnotation(ApiOperation.class);if (operation != null) {String name = operation.value();permission.setName(name);}}// 默认值0permission.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;}}

角色-权限列表

角色权限的维护,包括简单的增删改和基于easyui树实现的授权功能,以及超管账户的权限初始化功能。

授权功能:通过简单的复选框勾选/取消勾选来给角色分配权限

权限初始化功能:其实非常简单,就是查询所有的资源权限,然后分配给超管用户。

    @Overridepublic void init(String userId) {// 删除用当前户所有角色的权限rolePermissionMapper.deleteByUserId(userId);// 查询全部子权限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);});}

三、用户管理

因为这个部分的功能很简单,只有简单的crud,不做过多介绍。

用户列表

用户-角色列表

四、歌曲管理

歌曲列表

歌曲的维护、歌单导入/导出功能。

五、系统功能

系统设置

鼠标移动到右上方的下拉菜单,点击【系统设置】打开系统设置窗口。

修改密码功能

 对密码进行加密存储

    @Overridepublic void updatePassword(UserPassUpdateDTO userPassUpdateDTO) {// 用户名String username = userPassUpdateDTO.getUsername();// 旧密码String oldPass = userPassUpdateDTO.getOldPass();// 新密码String password = userPassUpdateDTO.getPassword();// 验证两次输入的密码是否相等if (password.equals(userPassUpdateDTO.getRePass())) {// 查询用户信息String encodedPassword = selectByUsername(username).getPassword();// 验证输入的旧密码是否正确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, "两次输入的密码不一样");}}

菜单控制功能:就是控制左侧菜单的显示,勾选/取消勾选对应的菜单,然后点击窗口右下角的【确定】按钮提交修改。

初始化权限

这个按钮的功能和权限列表的【初始化】按钮是一样的。

代码介绍

前面已经对这个系统做了一些简单的介绍,接下来介绍一下博主经过多次实践产出的一部分公共的Java代码,可以直接使用。

响应状态码

在枚举中自定义了几种响应状态码

package cn.edu.sgu.www.restful;/*** 响应状态码* @author heyunlin* @version 1.0*/
public enum ResponseCode {/*** 请求成功*/OK(200),/*** 失败的请求*/BAD_REQUEST(400),/*** 未授权*/UNAUTHORIZED(401),/*** 禁止访问*/FORBIDDEN(403),/*** 找不到*/NOT_FOUND(404),/*** 不可访问*/NOT_ACCEPTABLE(406),/*** 冲突*/CONFLICT(409),/*** 服务器发生异常*/ERROR(500);private final Integer value;ResponseCode(Integer value) {this.value = value;}public Integer getValue() {return value;}}

统一响应实体类

包含提示信息、响应数据和响应状态码的web响应实体类。

package cn.edu.sgu.www.restful;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;import java.io.Serializable;/*** 响应实体类* @param <T>* @author heyunlin* @version 1.0*/
@Data
public class JsonResult<T> implements Serializable {private static final long serialVersionUID = 18L;/*** 响应数据*/private T data;/*** 响应状态码*/private Integer code;/*** 响应提示信息*/private String message;/*** 成功提示*/private static final String successMessage = "请求成功";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() : "系统发生异常,请联系管理员!");}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>*/@ExceptionHandlerpublic 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();}}

统一数据格式处理类

这个类需要注意的是,knife4j的接口路径不能被处理,否则接口文档的页面内容不能正常显示。

# 配置统一数据格式返回处理类忽略的路径
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;/*** 统一数据格式返回处理类* @author heyunlin* @version 1.0*/
@Slf4j
@RestControllerAdvice
public class GlobalResponseHandler implements ResponseBodyAdvice {private final List<String> ignore;@Autowiredpublic GlobalResponseHandler(ResponseProperties responseProperties) {ignore = responseProperties.getIgnore();}@Overridepublic boolean supports(MethodParameter parameter, Class type) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter parameter, MediaType mediaType, Class type, ServerHttpRequest request, ServerHttpResponse response) {// 返回值类型为JsonResult,则直接返回if (body instanceof JsonResult) {return body;}// 忽略的请求地址String requestURI = UserUtils.getRequest().getRequestURI();if (ignore.contains(requestURI)) {return body;}log.debug("接口{}的返回值为:{}", requestURI, body.toString());// 将返回值类型修改为JsonResultJsonResult<Object> jsonResult = JsonResult.success(null, body);if (body instanceof String) {return JSON.toJSONString(jsonResult);}return jsonResult;}}

datagrid数据格式对象

基于easyui的datagrid组件要求返回的数据格式,封装成的对象。

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数据格式对象* @param <T>* @author heyunlin* @version 1.0*/
@Data
public class JsonPage<T> implements Serializable {private static final long serialVersionUID = 18L;/*** 总记录数*/private Long total;/*** 查询结果*/private List<T> rows;/*** 页脚数据*/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对象* @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, "获取登录信息失败,当前没有用户登录。");}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对象失败");}public static HttpServletResponse getResponse() {RequestAttributes attributes = RequestContextHolder.getRequestAttributes();if (attributes != null ) {return ((ServletRequestAttributes) attributes).getResponse();}throw new GlobalException(ResponseCode.ERROR, "获取response对象失败");}}

基于easyui的表格过滤插件功能实现

package cn.edu.sgu.www.base;import lombok.Data;import java.io.Serializable;/*** 过滤规则* @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,/*** 以...开始*/beginwith,/*** 以...结尾*/endwith,/*** 小于*/less,/*** 小于或等于*/lessorequal,/*** 大于*/greater,/*** 大于或等于*/greaterorequal
}

基础的分页器

提供了分页的功能,需要分页功能的接口的参数类型只需要集成该类即可,将自动获得分页功能。

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;/*** 基础分页参数对象,包含页数和每页的记录数* @author heyunlin* @version 1.0*/
@EqualsAndHashCode(callSuper = true)
@Data
public class Pager<T> extends Sorter implements Serializable {private static final long serialVersionUID = 18L;/*** 页数*/private Integer page = 1;/*** 每页记录数*/private Integer rows = 10;/*** 过滤规则*/private List<FilterRule> filterRules;/*** 根据Pager创建Page对象* @param pager Pager* @return Page*/public static <T> Page<T> ofPage(Pager<T> pager) {return new Page<>(pager.getPage(), pager.getRows());}/*** 根据Pager创建QueryWrapper对象* @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) {// 字段名:转为小写字母+下划线的格式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语句String statement = getOrderByStatement(pager);if (StringUtils.isNotEmpty(statement)) {wrapper.last(statement);}}return wrapper;}}

基础的排序器

因为前端的基础分页器Pager已经继承了Sorter,所以开启了分页功能后自动获得排序功能。

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;/*** 基础排序对象,包含排序字段和排序方式* @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;/*** 根据查询条件拼接得到order by语句* @param sorter 分页查询条件* @return String*/public static String getStatement(Sorter sorter) {String sort;String sortColumn = sorter.getSort();// 处理排序字段String[] sortArray = {};if (StringUtils.isNotEmpty(sortColumn)) {// 驼峰命名转为下划线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();}/*** 根据查询条件拼接得到order by语句* @param sorter 分页查询条件* @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对象* @param sort String 排序字段* @param order String 排序方式* @return Pager<?> 返回重新设置排序字段和排序方式后的Pager对象*/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;}/*** 验证Pager对象的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);}/*** 验证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;}}

好了,文章就分享到这里了,自己的一个小成果,分享给大家,希望对大家有所帮助~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/633631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文件系统和IO流

目录 ​文件系统和IO流 一:文件的认知 认识文件 树型结构组织和⽬录: 文件路径&#xff08;Path): 文件形式: 二:File的方法 File的概述: File的属性 File的构造方法 File常用的get系列方法 ⽰例一:观察get系列的特点和差异 File常用的增,删方法 示例二:普通文件…

Unity 编辑器篇|(十)Handles (全面总结 | 建议收藏)

目录 1. 前言2 参数总览3 Handles两种使用方式3.1 基于Editor类的OnSceneGUI3.2 基于EditorWindow 4 Handles绘制4.1 Draw&#xff1a;绘制元几何体(点、线、面)4.1.1 抗锯齿&#xff1a; DrawAAPolyLine 、 DrawAAConvexPolygon4.1.2 绘制实线: DrawLine 、 DrawLines 、DrawP…

排序:非递归的归并排序

目录 递归与非递归的思想对比&#xff1a; 递归&#xff1a; 非递归&#xff1a; 代码解析&#xff1a; 完整代码&#xff1a; 递归与非递归的思想对比&#xff1a; 递归&#xff1a; 在之前的归并排序&#xff0c;它的核心思想是通过不断的分割&#xff0c;从一个数组变…

HTML 表单

文章目录 表单什么是表单GET和POST两种提交方式有什么不同?表单元素表单项外文本单行文本输入框单行文本密码框单选框复选框下拉列表框上传文件隐藏域填写邮箱填写电话填写数字填写日期进度条多行文本输入框提交按钮取消按钮 用户注册案例 表单 什么是表单 form:表单元素 此…

机器人强化学习-双机械臂

概要 基于 robosuite 库&#xff0c;进行双臂机器人学习训练 环境测试 下面展示下分别控制两个机械手随机运动的画面&#xff1a; 双臂显示场景如下&#xff1a;双臂调用代码如下&#xff1a; import numpy as np import robosuite as suite import robomimic import rob…

【vue2】状态管理之 Vuex

文章目录 一、介绍1、概念 2、工作示意图3、安装4、简单示例 二、核心1、State1.1 组件中获取 Vuex 的状态1.2 mapState 辅助函数1.3 对象展开运算符 2、Getter2.1 基本使用2.2 通过属性访问2.3 通过方法访问2.4 mapGetters 辅助函数 3、Mutation3.1 定义 mutation3.2 commit 提…

多线程排序(java版)

&#x1f4d1;前言 本文主要是【排序】——多线程排序的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&#x…

Docker-02-镜像项目部署

Docker-02-镜像&项目部署 文章目录 Docker-02-镜像&项目部署一、镜像①&#xff1a;镜像结构②&#xff1a;Dockerfile③&#xff1a;构建镜像01&#xff1a;构建02&#xff1a;查看镜像列表03&#xff1a;运行镜像 二、网络①&#xff1a;容器的网络IP地址②&#xff…

数据中心负载测试的常用工具和技术有哪些?

数据中心负载测试是评估系统在高负载下的性能和稳定性的重要手段。通过模拟大量用户并发访问&#xff0c;可以检测系统的瓶颈和潜在问题&#xff0c;为优化系统性能提供依据。以下是一些常用的数据中心负载测试工具和技术&#xff1a; Apache JMeter&#xff1a;JMeter是一个开…

《世界之外》提前开测,网易打响国乙大战

1月18日&#xff0c;国乙市场迎来了一场大战。 原定于1月26日开服的网易新乙游《世界之外》&#xff0c;突然宣布在1月18日进行不删档、不限量测试&#xff0c;从某种意义上来说&#xff0c;其实就等同于提前公测。 而同一天开服的还有叠纸的全新3D乙游《恋与深空》&#xff…

基于R语言的NDVI的Sen-MK趋势检验

本实验拟分析艾比湖地区2010年至2020年间的NDVI数据&#xff0c;数据从MODIS遥感影像中提取的NDVI值&#xff0c;在GEE遥感云平台上将影像数据下载下来。代码如下&#xff1a; import ee import geemap geemap.set_proxy(port7890)# 设置全局网络代理 Map geemap.Map()# 指定…

2024年宜昌市中级职称评定条件能力业绩要求是什么?

1.参与完成 4 项中型以上工程建筑项目的勘察、设计&#xff0c;并通过审查 2.参与完成标准&#xff08;含国家标准、行业标准、地方标准、团体、标准&#xff09;、省级标准设计&#xff0c;参与工法、管理办法、规定、规程细则的编写&#xff0c;并正式发布实施 3.参与完成新技…

文件上传时报413错误

原因&#xff1a;nginx上传文件大小有限制&#xff0c;如果不配置nginx上传文件大小&#xff0c;则上传时会出现 413 (Request Entity Too Large) 异常&#xff08;请求实体过大&#xff09; 解决方案&#xff1a;1、打开nginx主配置文件nginx.conf&#xff0c;找到http{ }&…

go语言(三)----函数

1、函数单变量返回 package mainimport "fmt"func fool(a string,b int) int {fmt.Println("a ",a)fmt.Println("b ",b)c : 100return c}func main() {c : fool("abc",555)fmt.Println("c ",c)}2、函数多变量返回 pack…

表的增删改查CURD(基础)

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;MySql&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 新增&#xff08;Create&#xff09; 全列插入 指定列…

高校教务系统登录页面JS分析——河北地质大学

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密码加…

鹅厂有料有趣的程序员交流圈重磅官宣!加入立享福利

号外&#xff01;腾讯云开发者社区重磅上线海量社群&#xff0c;覆盖开发者技术学习交流、工作成长、生活分享等多元场景需求&#xff0c;用最新鲜的内容&#xff0c;最好玩的互动&#xff0c;与你一起共创最有料有趣的技术人交流圈&#xff5e; 最有料有趣交流圈在这里你可以畅…

Git学习笔记(第5章):Git团队协作机制

目录 5.1 团队内协作 5.2 跨团队协作 Git进行版本控制都是在本地库操作的。若想使用Git进行团队协作&#xff0c;就必须借助代码托管中心。 5.1 团队内协作 问题引入&#xff1a;成员1&#xff08;大佬&#xff09;利用Git在宿主机上初始化本地库&#xff0c;完成代码的整体…

thinkphp+vue+mysql大学生心理健康测试分析系统g4i4o

学生心里测试分析系统由管理员和学生、教师交互构成。学生对于本系统的使用&#xff0c;学生可以通过系统注册、登录&#xff0c;修改个人信息&#xff0c;查看交流区、心理测试卷、新闻资讯等功能。 教师对于本系统的使用&#xff0c;教师可以通过系统注册、登录&#xff0c;修…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷6

某企业根据自身业务需求&#xff0c;实施数字化转型&#xff0c;规划和建设数字化平台&#xff0c;平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”&#xff0c;拟采用开源OpenStack搭建企业内部私有云平台&#xff0c;开源Kubernetes搭建云原生服务平台&#xff0c;选…