基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式
-之动态查询,查询逻辑封装复用
https://www.cnblogs.com/neozhu/p/13174234.html
需求
- 配合EasyUI datagird filter实现多字段(任意字段)的筛选
- 根据业务需求筛选特定的状态或条件,如:查看结案的订单,最近30天的订单,查看属于我的订单.等等,这些逻辑是固定也是可以被重用,但又不想每次写相同的条件,那么下面我会给我的解决方案.
需求1只是一个偷懒的实现方式,因为datagrid自带这个功能,但又不想根据具体的需求来画查询条件,如果需求必须要再datagrid上面做一块查询条件的输入那目前只能在前端自己手工添加,在组织后传入后台,暂时不在这里讨论
需求2可能不太好解释,看完代码就自然理解为什么要这么做了,这么做的好处有哪些
具体实现的方式

默认情况下 datagrid 有几列就可以对这几列进行筛选,对于日期型的字段会采用between,选择2个时间之间进行筛选,数字类型会提供大于小于等符号选择,可以自行尝试,其原理是datagrid 会根据datagrid 头部输入的值生成一个Json字符串发送后台请求数据
JSON:格式
filterRules: [
{field:field,op:op,value:value},{field:field,op:op,value:value},]
- 通常的做法是一个一个判断加条件

var filters = JsonConvert.DeserializeObject<IEnumerable<filterRule>>(filterRules);
foreach (var rule in filters)
{
if (rule.field == "Id" && !string.IsNullOrEmpty(rule.value) && rule.value.IsInt())
{
var val = Convert.ToInt32(rule.value);
switch (rule.op)
{
case "equal":
this.And(x => x.Id == val);
break;
case "notequal":
this.And(x => x.Id != val);
break;
case "less":
this.And(x => x.Id < val);
break;
case "lessorequal":
this.And(x => x.Id <= val);
break;
case "greater":
this.And(x => x.Id > val);
break;
case "greaterorequal":
this.And(x => x.Id >= val);
break;
default:
this.And(x => x.Id == val);
break;
}
}
if (rule.field == "Name" && !string.IsNullOrEmpty(rule.value))
{
this.And(x => x.Name.Contains(rule.value));
}
if (rule.field == "Code" && !string.IsNullOrEmpty(rule.value))
{
this.And(x => x.Code.Contains(rule.value));
} if (rule.field == "Address" && !string.IsNullOrEmpty(rule.value))
{
this.And(x => x.Address.Contains(rule.value));
} if (rule.field == "Contect" && !string.IsNullOrEmpty(rule.value))
{
this.And(x => x.Contect.Contains(rule.value));
} if (rule.field == "PhoneNumber" && !string.IsNullOrEmpty(rule.value))
{
this.And(x => x.PhoneNumber.Contains(rule.value));
} if (rule.field == "RegisterDate" && !string.IsNullOrEmpty(rule.value))
{
if (rule.op == "between")
{
var datearray = rule.value.Split(new char[] { '-' });
var start = Convert.ToDateTime(datearray[]);
var end = Convert.ToDateTime(datearray[]); this.And(x => SqlFunctions.DateDiff("d", start, x.RegisterDate) >= );
this.And(x => SqlFunctions.DateDiff("d", end, x.RegisterDate) <= );
}
}
if (rule.field == "CreatedDate" && !string.IsNullOrEmpty(rule.value))
{
if (rule.op == "between")
{
var datearray = rule.value.Split(new char[] { '-' });
var start = Convert.ToDateTime(datearray[]);
var end = Convert.ToDateTime(datearray[]); this.And(x => SqlFunctions.DateDiff("d", start, x.CreatedDate) >= );
this.And(x => SqlFunctions.DateDiff("d", end, x.CreatedDate) <= );
}
} if (rule.field == "CreatedBy" && !string.IsNullOrEmpty(rule.value))
{
this.And(x => x.CreatedBy.Contains(rule.value));
} if (rule.field == "LastModifiedDate" && !string.IsNullOrEmpty(rule.value))
{
if (rule.op == "between")
{
var datearray = rule.value.Split(new char[] { '-' });
var start = Convert.ToDateTime(datearray[]);
var end = Convert.ToDateTime(datearray[]); this.And(x => SqlFunctions.DateDiff("d", start, x.LastModifiedDate) >= );
this.And(x => SqlFunctions.DateDiff("d", end, x.LastModifiedDate) <= );
}
} if (rule.field == "LastModifiedBy" && !string.IsNullOrEmpty(rule.value))
{
this.And(x => x.LastModifiedBy.Contains(rule.value));
} }
- 新的做法是动态根据field,op,value生成一个linq 表达式,不用再做繁琐的判断,这块代码也可以被其它项目使用,非常好用

namespace SmartAdmin
{ public static class PredicateBuilder
{ public static Expression<Func<T, bool>> FromFilter<T>(string filtergroup) {
Expression<Func<T, bool>> any = x => true;
if (!string.IsNullOrEmpty(filtergroup))
{
var filters = JsonSerializer.Deserialize<filter[]>(filtergroup); foreach (var filter in filters)
{
if (Enum.TryParse(filter.op, out OperationExpression op) && !string.IsNullOrEmpty(filter.value))
{
var expression = GetCriteriaWhere<T>(filter.field, op, filter.value);
any = any.And(expression);
}
}
} return any;
} #region -- Public methods --
public static Expression<Func<T, bool>> GetCriteriaWhere<T>(Expression<Func<T, object>> e, OperationExpression selectedOperator, object fieldValue)
{
var name = GetOperand<T>(e);
return GetCriteriaWhere<T>(name, selectedOperator, fieldValue);
} public static Expression<Func<T, bool>> GetCriteriaWhere<T, T2>(Expression<Func<T, object>> e, OperationExpression selectedOperator, object fieldValue)
{
var name = GetOperand<T>(e);
return GetCriteriaWhere<T, T2>(name, selectedOperator, fieldValue);
} public static Expression<Func<T, bool>> GetCriteriaWhere<T>(string fieldName, OperationExpression selectedOperator, object fieldValue)
{
var props = TypeDescriptor.GetProperties(typeof(T));
var prop = GetProperty(props, fieldName, true);
var parameter = Expression.Parameter(typeof(T));
var expressionParameter = GetMemberExpression<T>(parameter, fieldName);
if (prop != null && fieldValue != null)
{ BinaryExpression body = null;
switch (selectedOperator)
{
case OperationExpression.equal:
body = Expression.Equal(expressionParameter, Expression.Constant(Convert.ChangeType(fieldValue, Nullable.GetUnderlyingType(prop.PropertyType)?? prop.PropertyType), prop.PropertyType));
return Expression.Lambda<Func<T, bool>>(body, parameter);
case OperationExpression.notequal:
body = Expression.NotEqual(expressionParameter, Expression.Constant(Convert.ChangeType(fieldValue, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType), prop.PropertyType));
return Expression.Lambda<Func<T, bool>>(body, parameter);
case OperationExpression.less:
body = Expression.LessThan(expressionParameter, Expression.Constant(Convert.ChangeType(fieldValue, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType), prop.PropertyType));
return Expression.Lambda<Func<T, bool>>(body, parameter);
case OperationExpression.lessorequal:
body = Expression.LessThanOrEqual(expressionParameter, Expression.Constant(Convert.ChangeType(fieldValue, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType), prop.PropertyType));
return Expression.Lambda<Func<T, bool>>(body, parameter);
case OperationExpression.greater:
body = Expression.GreaterThan(expressionParameter, Expression.Constant(Convert.ChangeType(fieldValue, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType), prop.PropertyType));
return Expression.Lambda<Func<T, bool>>(body, parameter);
case OperationExpression.greaterorequal:
body = Expression.GreaterThanOrEqual(expressionParameter, Expression.Constant(Convert.ChangeType(fieldValue, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType), prop.PropertyType));
return Expression.Lambda<Func<T, bool>>(body, parameter);
case OperationExpression.contains:
var contains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var bodyLike = Expression.Call(expressionParameter, contains, Expression.Constant(Convert.ChangeType(fieldValue, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType), prop.PropertyType));
return Expression.Lambda<Func<T, bool>>(bodyLike, parameter);
case OperationExpression.endwith:
var endswith = typeof(string).GetMethod("EndsWith",new[] { typeof(string) });
var bodyendwith = Expression.Call(expressionParameter, endswith, Expression.Constant(Convert.ChangeType(fieldValue, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType), prop.PropertyType));
return Expression.Lambda<Func<T, bool>>(bodyendwith, parameter);
case OperationExpression.beginwith:
var startswith = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
var bodystartswith = Expression.Call(expressionParameter, startswith, Expression.Constant(Convert.ChangeType(fieldValue, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType), prop.PropertyType));
return Expression.Lambda<Func<T, bool>>(bodystartswith, parameter);
case OperationExpression.includes:
return Includes<T>(fieldValue, parameter, expressionParameter, prop.PropertyType);
case OperationExpression.between:
return Between<T>(fieldValue, parameter, expressionParameter, prop.PropertyType);
default:
throw new Exception("Not implement Operation");
}
}
else
{
Expression<Func<T, bool>> filter = x => true;
return filter;
}
} public static Expression<Func<T, bool>> GetCriteriaWhere<T, T2>(string fieldName, OperationExpression selectedOperator, object fieldValue)
{ var props = TypeDescriptor.GetProperties(typeof(T));
var prop = GetProperty(props, fieldName, true); var parameter = Expression.Parameter(typeof(T));
var expressionParameter = GetMemberExpression<T>(parameter, fieldName); if (prop != null && fieldValue != null)
{
switch (selectedOperator)
{
case OperationExpression.any:
return Any<T, T2>(fieldValue, parameter, expressionParameter); default:
throw new Exception("Not implement Operation");
}
}
else
{
Expression<Func<T, bool>> filter = x => true;
return filter;
}
} public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr, Expression<Func<T, bool>> or)
{
if (expr == null)
{
return or;
} return Expression.Lambda<Func<T, bool>>(Expression.OrElse(new SwapVisitor(expr.Parameters[], or.Parameters[]).Visit(expr.Body), or.Body), or.Parameters);
} public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr, Expression<Func<T, bool>> and)
{
if (expr == null)
{
return and;
} return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(new SwapVisitor(expr.Parameters[], and.Parameters[]).Visit(expr.Body), and.Body), and.Parameters);
} #endregion
#region -- Private methods -- private static string GetOperand<T>(Expression<Func<T, object>> exp)
{
if (!( exp.Body is MemberExpression body ))
{
var ubody = (UnaryExpression)exp.Body;
body = ubody.Operand as MemberExpression;
} var operand = body.ToString(); return operand.Substring(); } private static MemberExpression GetMemberExpression<T>(ParameterExpression parameter, string propName)
{
if (string.IsNullOrEmpty(propName))
{
return null;
} var propertiesName = propName.Split('.');
if (propertiesName.Count() == )
{
return Expression.Property(Expression.Property(parameter, propertiesName[]), propertiesName[]);
} return Expression.Property(parameter, propName);
} private static Expression<Func<T, bool>> Includes<T>(object fieldValue, ParameterExpression parameterExpression, MemberExpression memberExpression ,Type type)
{
var safetype= Nullable.GetUnderlyingType(type) ?? type; switch (safetype.Name.ToLower())
{
case "string":
var strlist = (IEnumerable<string>)fieldValue;
if (strlist == null || strlist.Count() == )
{
return x => true;
}
var strmethod = typeof(List<string>).GetMethod("Contains", new Type[] { typeof(string) });
var strcallexp = Expression.Call(Expression.Constant(strlist.ToList()), strmethod, memberExpression);
return Expression.Lambda<Func<T, bool>>(strcallexp, parameterExpression);
case "int32":
var intlist = (IEnumerable<int>)fieldValue;
if (intlist == null || intlist.Count() == )
{
return x => true;
}
var intmethod = typeof(List<int>).GetMethod("Contains", new Type[] { typeof(int) });
var intcallexp = Expression.Call(Expression.Constant(intlist.ToList()), intmethod, memberExpression);
return Expression.Lambda<Func<T, bool>>(intcallexp, parameterExpression);
case "float":
var floatlist = (IEnumerable<float>)fieldValue;
if (floatlist == null || floatlist.Count() == )
{
return x => true;
}
var floatmethod = typeof(List<int>).GetMethod("Contains", new Type[] { typeof(int) });
var floatcallexp = Expression.Call(Expression.Constant(floatlist.ToList()), floatmethod, memberExpression);
return Expression.Lambda<Func<T, bool>>(floatcallexp, parameterExpression);
default:
return x => true;
} }
private static Expression<Func<T, bool>> Between<T>(object fieldValue, ParameterExpression parameterExpression, MemberExpression memberExpression, Type type)
{ var safetype = Nullable.GetUnderlyingType(type) ?? type;
switch (safetype.Name.ToLower())
{
case "datetime":
var datearray = ( (string)fieldValue ).Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
var start = Convert.ToDateTime(datearray[] + " 00:00:00", CultureInfo.CurrentCulture);
var end = Convert.ToDateTime(datearray[] + " 23:59:59", CultureInfo.CurrentCulture);
var greater = Expression.GreaterThan(memberExpression, Expression.Constant(start, type));
var less = Expression.LessThan(memberExpression, Expression.Constant(end, type));
return Expression.Lambda<Func<T, bool>>(greater, parameterExpression)
.And(Expression.Lambda<Func<T, bool>>(less, parameterExpression));
case "int":
case "int32":
var intarray = ( (string)fieldValue ).Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
var min = Convert.ToInt32(intarray[] , CultureInfo.CurrentCulture);
var max = Convert.ToInt32(intarray[], CultureInfo.CurrentCulture);
var maxthen = Expression.GreaterThan(memberExpression, Expression.Constant(min, type));
var minthen = Expression.LessThan(memberExpression, Expression.Constant(max, type));
return Expression.Lambda<Func<T, bool>>(maxthen, parameterExpression)
.And(Expression.Lambda<Func<T, bool>>(minthen, parameterExpression));
case "decimal":
var decarray = ( (string)fieldValue ).Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
var dmin = Convert.ToDecimal(decarray[], CultureInfo.CurrentCulture);
var dmax = Convert.ToDecimal(decarray[], CultureInfo.CurrentCulture);
var dmaxthen = Expression.GreaterThan(memberExpression, Expression.Constant(dmin, type));
var dminthen = Expression.LessThan(memberExpression, Expression.Constant(dmax, type));
return Expression.Lambda<Func<T, bool>>(dmaxthen, parameterExpression)
.And(Expression.Lambda<Func<T, bool>>(dminthen, parameterExpression));
case "float":
var farray = ((string)fieldValue).Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
var fmin = Convert.ToDecimal(farray[], CultureInfo.CurrentCulture);
var fmax = Convert.ToDecimal(farray[], CultureInfo.CurrentCulture);
var fmaxthen = Expression.GreaterThan(memberExpression, Expression.Constant(fmin, type));
var fminthen = Expression.LessThan(memberExpression, Expression.Constant(fmax, type));
return Expression.Lambda<Func<T, bool>>(fmaxthen, parameterExpression)
.And(Expression.Lambda<Func<T, bool>>(fminthen, parameterExpression));
case "string":
var strarray = ( (string)fieldValue ).Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
var smin = strarray[];
var smax = strarray[]; var strmethod = typeof(string).GetMethod("Contains");
var mm = Expression.Call(memberExpression, strmethod, Expression.Constant(smin, type));
var nn = Expression.Call(memberExpression, strmethod, Expression.Constant(smax, type)); return Expression.Lambda<Func<T, bool>>(mm, parameterExpression)
.Or(Expression.Lambda<Func<T, bool>>(nn, parameterExpression));
default:
return x => true;
} } private static Expression<Func<T, bool>> Any<T, T2>(object fieldValue, ParameterExpression parameterExpression, MemberExpression memberExpression)
{
var lambda = (Expression<Func<T2, bool>>)fieldValue;
var anyMethod = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
.First(m => m.Name == "Any" && m.GetParameters().Count() == ).MakeGenericMethod(typeof(T2)); var body = Expression.Call(anyMethod, memberExpression, lambda); return Expression.Lambda<Func<T, bool>>(body, parameterExpression);
} private static PropertyDescriptor GetProperty(PropertyDescriptorCollection props, string fieldName, bool ignoreCase)
{
if (!fieldName.Contains('.'))
{
return props.Find(fieldName, ignoreCase);
} var fieldNameProperty = fieldName.Split('.');
return props.Find(fieldNameProperty[], ignoreCase).GetChildProperties().Find(fieldNameProperty[], ignoreCase); }
#endregion
} internal class SwapVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public SwapVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node) => node == from ? to : base.Visit(node);
}
public enum OperationExpression
{
equal,
notequal,
less,
lessorequal,
greater,
greaterorequal,
contains,
beginwith,
endwith,
includes,
between,
any
}
}

public async Task<JsonResult> GetData(int page = , int rows = , string sort = "Id", string order = "asc", string filterRules = "")
{
try
{
var filters = PredicateBuilder.FromFilter<Company>(filterRules);
var total = await this.companyService
.Query(filters)
.AsNoTracking()
.CountAsync()
;
var pagerows = (await this.companyService
.Query(filters)
.AsNoTracking()
.OrderBy(n => n.OrderBy(sort, order))
.Skip(page - ).Take(rows)
.SelectAsync())
.Select(n => new
{
Id = n.Id,
Name = n.Name,
Code = n.Code,
Address = n.Address,
Contect = n.Contect,
PhoneNumber = n.PhoneNumber,
RegisterDate = n.RegisterDate.ToString("yyyy-MM-dd HH:mm:ss")
}).ToList();
var pagelist = new { total = total, rows = pagerows };
return Json(pagelist);
}
catch(Exception e) {
throw e;
} }
配合使用的代码
- 对于固定查询逻辑的封装和复用,当然除了复用还可以明显的提高代码的可读性.

public class OrderSalesQuery : QueryObject<Order>
{
public decimal Amount { get; set; }
public string Country { get; set; }
public DateTime FromDate { get; set; }
public DateTime ToDate { get; set; } public override Expression<Func<Order, bool>> Query()
{
return (x =>
x.OrderDetails.Sum(y => y.UnitPrice) > Amount &&
x.OrderDate >= FromDate &&
x.OrderDate <= ToDate &&
x.ShipCountry == Country);
}
}
查看订单的销售情况,条件 金额,国家,日期

var orderRepository = new Repository<Order>(this); var orders = orderRepository
.Query(new OrderSalesQuery(){
Amount = ,
Country = "USA",
FromDate = DateTime.Parse("01/01/1996"),
ToDate = DateTime.Parse("12/31/1996" )
})
.Select();
调用查询方法

public class CustomerLogisticsQuery : QueryObject<Customer>
{
public CustomerLogisticsQuery FromCountry(string country)
{
Add(x => x.Country == country);
return this;
} public CustomerLogisticsQuery LivesInCity(string city)
{
Add(x => x.City == city);
return this;
}
}
客户查询 根据国家和城市查询

public class CustomerSalesQuery : QueryObject<Customer>
{
public CustomerSalesQuery WithPurchasesMoreThan(decimal amount)
{
Add(x => x.Orders
.SelectMany(y => y.OrderDetails)
.Sum(z => z.UnitPrice * z.Quantity) > amount); return this;
} public CustomerSalesQuery WithQuantitiesMoreThan(decimal quantity)
{
Add(x => x.Orders
.SelectMany(y => y.OrderDetails)
.Sum(z => z.Quantity) > quantity); return this;
}
}
客户的销售情况,金额和数量

var customerRepository = new Repository<Customer>(this); var query1 = new CustomerLogisticsQuery()
.LivesInCity("London"); var query2 = new CustomerSalesQuery()
.WithPurchasesMoreThan()
.WithQuantitiesMoreThan(); customerRepository
.Query(query1.And(query2))
.Select()
.Dump();
复用上面的定义的查询方法
以上这些都是改项目提供的方法,非常的好用
基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式的更多相关文章
- 基于领域驱动设计(DDD)超轻量级快速开发架构
smartadmin.core.urf 这个项目是基于asp.net core 3.1(最新)基础上参照领域驱动设计(DDD)的理念,并参考目前最为了流行的abp架构开发的一套轻量级的快速开发web ...
- 领域驱动设计(DDD)
领域驱动设计(DDD)实现之路 2004年,当Eric Evans的那本<领域驱动设计——软件核心复杂性应对之道>(后文简称<领域驱动设计>)出版时,我还在念高中,接触到领域驱 ...
- 领域驱动设计(DDD:Domain-Driven Design)
领域驱动设计(DDD:Domain-Driven Design) Eric Evans的"Domain-Driven Design领域驱动设计"简称DDD,Evans DDD是一套 ...
- python 全栈开发,Day116(可迭代对象,type创建动态类,偏函数,面向对象的封装,获取外键数据,组合搜索,领域驱动设计(DDD))
昨日内容回顾 1. 三个类 ChangeList,封装列表页面需要的所有数据. StarkConfig,生成URL和视图对应关系 + 默认配置 AdminSite,用于保存 数据库类 和 处理该类的对 ...
- 关于领域驱动设计 DDD(Domain-Driven Design)
以下旨在 理解DDD. 1. 什么是领域? 妈妈好是做母婴新零售的产品,应该属于电商平台,那么电商平台就是一个领域. 同一个领域的系统都有相同的核心业务. eg: 电商领域都有:商品浏览.购物 ...
- 分享我对领域驱动设计(DDD)的学习成果
本文内容提要: 1. 领域驱动设计之领域模型 2. 为什么建立一个领域模型是重要的 3. 领域通用语言(Ubiquitous Language) 4.将领域模型转换为代码实现的最佳实践 5. 领域建模 ...
- 我对领域驱动设计(DDD)的学习成果
领域驱动设计之领域模型 2004年Eric Evans发表Domain-Driven Design – Tackling Complexity in the Heart of Software (领域 ...
- 领域驱动设计(DDD)实践之路(一)
本文首发于 vivo互联网技术 微信公众号 链接: https://mp.weixin.qq.com/s/gk-Hb84Dt7JqBRVkMqM7Eg 作者:张文博 领域驱动设计(Domain Dr ...
- 领域驱动设计(DDD)实现之路
2004年,当Eric Evans的那本<领域驱动设计——软件核心复杂性应对之道>(后文简称<领域驱动设计>)出版时,我还在念高中,接触到领域驱动设计(DDD)已经是8年后的事 ...
随机推荐
- HomeLede 2020.5.27更新 UPnP+NAS+多拨+网盘+DNS优化+帕斯沃/Clash 无缝集成+软件包
交流群:QQ 1030484865 电报 t.me/t_homelede 固件说明 基于Lede OpenWrt R2020.5.20版本(源码截止2020.5.27)及若干自行维护的软件包 结合 ...
- html5学习之路_001
安装环境 安装intellij idea作为开发环境 打开环境 新建一个html文件,打开之后出现代码框架,再次基础上继续编码即可,例如: <!DOCTYPE html> <html ...
- Misdirection: 1靶机writeup
看下端口 nmap -A 172.16.61.131 一些坑3306无法访问,80,web2py漏洞无法利用 利用dirb遍历网站路径 得到下面命令执行漏洞 http://172.16.61.131: ...
- 深入理解Mybatis(第一讲)——手写ORM框架(简易版Mybatis)
我们来自定义一个持久层框架,也就是Mybatis的简易版. 使用端的搭建 idea中新建maven工程IPersistence_test: 在resources目录下新建sqlMapConfig.xm ...
- 微信小程序路由跳转(navigateTo,redirectTo ,switchTab ,reLaunch )
navigateTo, redirectTo 只能打开非 tabBar 页面. switchTab 只能打开 tabBar 页面. reLaunch 可以打开任意页面. 通过redirect重定向的页 ...
- Beta冲刺——5.26
这个作业属于哪个课程 软件工程 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.组员一起学习Git分支管 ...
- Java实现 蓝桥杯VIP 算法训练 大小写判断
问题描述 给定一个英文字母判断这个字母是大写还是小写. 输入格式 输入只包含一个英文字母c. 输出格式 如果c是大写字母,输出"upper",否则输出"lower&quo ...
- Java实现蓝桥杯VIP 算法训练 P0504
试题 算法训练 P0504 资源限制 时间限制:1.0s 内存限制:256.0MB Anagrams指的是具有如下特性的两个单词:在这两个单词当中,每一个英文字母(不区分大小写)所出现的次数都是相同的 ...
- Java实现 蓝桥杯VIP 算法提高 最长字符序列
算法提高 最长字符序列 时间限制:1.0s 内存限制:256.0MB 最长字符序列 问题描述 设x(i), y(i), z(i)表示单个字符,则X={x(1)x(2)--x(m)},Y={y(1)y( ...
- java实现第六届蓝桥杯格子中输出
格子中输出 格子中输出 stringInGrid方法会在一个指定大小的格子中打印指定的字符串. 要求字符串在水平.垂直两个方向上都居中. 如果字符串太长,就截断. 如果不能恰好居中,可以稍稍偏左或者偏 ...