当前位置: 首页 > 编程日记 > 正文

一步一步Asp.Net MVC系列_权限管理总结(附MVC权限管理系统源码)

TZHSWEET:请大家多多反馈问题,我已经在修改中了,已更新版本。。。。。。

如果大家遇到数据库附加问题,EF连接字符串问题,请自行配置,如果有bug反馈可以私聊,我的qq:409180955。

项目已经发布到Google Code上面了,大家如果需要直接去Google Code下载

主页http://code.google.com/p/tzhsweetsourse/

 

在上一节中我们总结了关于权限控制的方式,我们这一节讲解关于权限控制中角色权限的授予处理等等并做本系列的总结.

首先,我们来谈谈权限控制中角色权限的控制,上一节只是针对权限拦截中比较粗的控制,如果我们需要对每一个动作做细致的权限认证,我们仍然进一步设计权限处理.

比如:我们分配给一个角色只有浏览日志的权限,不允许他进行其他动作,针对这种细的粒度,我们就必须专门进行处理,就是关于角色动作验证的处理

image

当然,我们的数据库设计就必须就需要进一步改进.

EntityDesignerDiagram

这是我们的EF关系图:

主要看看关于tbModule,tbPermission部分,都是采用树形设计,为什么这样设计呢?

首先,我们必须要承认,Module也就是模块,应该是多层次的,就像我们的菜单,是很多级的一样,这种多层次需要我们设计成树形,授予权限,我们就可以很轻松的设计成树形进行处理.

其次,关于tbPermssion,这个是权限,但是这个权限应该也是树形结构,比如我们设计一个菜单模块权限细分分为多种,增删改查,访问,等等,一个访问可能对应多种ajax请求,比如一个ajax读取Grid信息,一个ajax读取Tree信息,如果我们要做细致处理就要对应做多级处理,虽然,小型项目用不到,但是,我们的数据库设计拥有很大的灵活性.

image

权限可以细分,我们授权的时候,也不会不方便,只需要前端处理的合理,做好关联的处理,

image

但是,如果一个Update可能有多个子集Action方法,比如Get方法,例如:部门信息管理,我们一个更新动作,是先Get部门信息,然后在进行修改以后Update,所以,Get动作就是Update的子集操作,如果我们这个都控制,小型项目会变得太过复杂,怎么处理这种东西呢?

这时候我们之前的Attribute设计的多种权限处理就派上用场了.

首先,对于多种ajax动作,如果不是对数据库很较大影响的,对于小型项目,我们根本不用管它,直接标记为只要登陆即可访问,比如Get,GetGridTree之类的,读取信息这类的子集动作,直接给他个默认的LoginAllowView标记(登录即可访问),对于更高粒度,我们当然要进行细致的控制.

image

image

这样,我们的小型项目的Action控制基本上就两级,也就是控制在增删改查这个级别,

如果我们需要更高粒度的控制,只需要去掉LoginAllowView标记,在程序中对应添加Permission,并继续给我们的Action添加子集操作,比如Add关联子集的那些动作,全部录入到数据库中,虽然过程会长一点,但是我们可以通过UI设计的更友好来处理它.

image

把每一个具体操作关联的Action都录入处理,我们就可以了,当然我们的数据库设计就必须合理,必须有ParentID字段,用来控制树形结构.

针对权限的处理我们就到一段落,接下来,上演关于LigerUI项目中学到的一个东西,公共查询组件的设计:

曾几何时我们拼接查询语句来设计各种搜索的高级功能,搜索,成了一块心病,这是一年前,刚开始学的时候做一个搜索的设计,拼接查询语句,

每一次的模块都是靠后台手工编码sql来设计逻辑

image

看到这里是不是已经吐了?????

我看了以前的东西都已经受不了了.....

也接触到了LigerUI关于Filter过滤器组件以及后台的设计,也发现一位牛人海南胡勇的组合搜索设计,

image

image

这给了我一个相当大的思路,就是设计一个通用组合搜索组件,提高复用率,设计一种解析翻译规则,我们只需要按照规则提供数据,把sql解析的工作交给组件.

这种设计是相当的震撼,而且web的开发方式可以把where放在客户端,可以在不改变后台代码的前提下,更大程度上去设计查询.

LigerUI的作者那个权限管理,我研究了好久,Filter也看了好久,这里谈谈心得:

image

主要的模块就是这几块:

FilterGroup:查询条件组合数组

FilterParam:查询参数集合

FilterRule:规则数组

FilterTranslator:翻译机(专门负责把数据以及条件翻译成sql语句)

重要:当然为了安全性考虑我们必须对翻译机过程中的数据做校验处理

image

   1:    /// <summary>
   2:      /// 用于存放过滤参数,比如一个是名称,一个是值,等价于sql中的Parameters
   3:      /// </summary>
   4:      public class FilterParam
   5:      {
   6:          public FilterParam(string name, object value)
   7:          {
   8:              this.Name = name;
   9:              this.Value = value;
  10:          }
  11:          public string Name { get; set; }
  12:          public object Value { get; set; }
  13:          /// <summary>
  14:          /// 转化为ObjectParameter可变参数
  15:          /// </summary>
  16:          /// <returns></returns>
  17:          public ObjectParameter ToObjParam()
  18:          {
  19:              ObjectParameter param = new ObjectParameter(this.Name,this.Value);
  20:              return param;
  21:          }
  22:          /// <summary>
  23:          /// 为查询语句添加参数
  24:          /// </summary>
  25:          /// <param name="commandText">查询命令</param>
  26:          /// <returns></returns>
  27:          public static string AddParameters(string commandText,IEnumerable<FilterParam> listfilter)
  28:          {
  29:              foreach (FilterParam param in listfilter)
  30:              {
  31:                  if (param.Value.IsValidInput())
  32:                  {
  33:                    commandText=commandText.Replace("@"+param.Name,"'"+ param.Value.ToString()+"'");
  34:                  }
  35:   
  36:              }
  37:              return commandText;
  38:          }
  39:          /// <summary>
  40:          /// 转化为ObjectParameter可变参数
  41:          /// </summary>
  42:          /// <param name="listfilter"></param>
  43:          /// <returns></returns>
  44:          public static ObjectParameter[] ConvertToListObjParam(IEnumerable<FilterParam> listfilter)
  45:          {
  46:              List<ObjectParameter> list = new List<ObjectParameter>();
  47:              foreach (FilterParam param in listfilter)
  48:              {
  49:                  list.Add(param.ToObjParam());
  50:              }
  51:              return list.ToArray();
  52:          }
   1:   /*  作者:       tianzh
   2:   *  创建时间:   2012/7/22 22:05:45
   3:   *
   4:   */
   5:   /*  作者:       tianzh
   6:   *  创建时间:   2012/7/22 15:34:19
   7:   *
   8:   */
   9:  namespace TZHSWEET.Common
  10:  {
  11:      public class FilterRule
  12:      {
  13:          /// <summary>
  14:          /// 过滤规则
  15:          /// </summary>
  16:          public FilterRule()
  17:          {
  18:          }
  19:          /// <summary>
  20:          /// 过滤规则
  21:          /// </summary>
  22:          /// <param name="field">参数</param>
  23:          /// <param name="value">值</param>
  24:          public FilterRule(string field, object value)
  25:              : this(field, value, "equal")
  26:          {
  27:          }
  28:          /// <summary>
  29:          /// 实例化
  30:          /// </summary>
  31:          /// <param name="field">参数</param>
  32:          /// <param name="value">值</param>
  33:          /// <param name="op">操作</param>
  34:          public FilterRule(string field, object value, string op)
  35:          {
  36:              this.field = field;
  37:              this.value = value;
  38:              this.op = op;
  39:          }
  40:          /// <summary>
  41:          /// 字段
  42:          /// </summary>
  43:          public string field { get; set; }
  44:          /// <summary>
  45:          /// 值
  46:          /// </summary>
  47:          public object value { get; set; }
  48:          /// <summary>
  49:          /// 操作
  50:          /// </summary>
  51:          public string op { get; set; }
  52:          /// <summary>
  53:          /// 类型
  54:          /// </summary>
  55:          public string type { get; set; }
  56:      }
  57:  }

剩下个工作就是交给翻译机进行翻译:(对作者的版本做了修改)

   1:   /*  作者:       tianzh
   2:   *  创建时间:   2012/7/22 22:05:49
   3:   *
   4:   */
   5:  using System;
   6:  using System.Collections;
   7:  using System.Collections.Generic;
   8:  using System.Text;
   9:  using System.Linq;
  10:  using System.Data.Objects;
  11:  namespace TZHSWEET.Common
  12:  {
  13:   
  14:   
  15:      /// <summary>
  16:      /// 将检索规则 翻译成 where sql 语句,并生成相应的参数列表
  17:      /// 如果遇到{CurrentUserID}这种,翻译成对应的参数
  18:      /// </summary>
  19:      public class FilterTranslator
  20:      {
  21:          //几个前缀/后缀
  22:          /// <summary>
  23:          /// 左中括号[(用于表示数据库实体前的标识)
  24:          /// </summary>
  25:          protected char leftToken = '[';
  26:          /// <summary>
  27:          /// 用于可变参替换的标志
  28:          /// </summary>
  29:          protected char paramPrefixToken = '@';
  30:          /// <summary>
  31:          /// 右中括号(用于表示数据库实体前的标识)
  32:          /// </summary>
  33:          protected char rightToken = ']';
  34:          /// <summary>
  35:          /// 组条件括号
  36:          /// </summary>
  37:          protected char groupLeftToken = '(';
  38:          /// <summary>
  39:          /// 右条件括号
  40:          /// </summary>
  41:          protected char groupRightToken = ')';
  42:          /// <summary>
  43:          /// 模糊查询符号
  44:          /// </summary>
  45:          protected char likeToken = '%';
  46:          /// <summary>
  47:          /// 参数计数器
  48:          /// </summary>
  49:          private int paramCounter = 0;
  50:   
  51:          //几个主要的属性
  52:          public FilterGroup Group { get; set; }
  53:          /// <summary>
  54:          /// 最终的Where语句(包括可变参占位符)
  55:          /// </summary>
  56:          public string CommandText { get; private set; }
  57:          /// <summary>
  58:          /// 查询语句可变参数数组
  59:          /// </summary>
  60:          public IList<FilterParam> Parms { get; private set; }
  61:          /// <summary>
  62:          /// 是否为Entity To Sql 生成where翻译语句(Entity To Sql就需要在实体前面加it,例如it.ID=@ID and it.Name-@Name)
  63:          /// 否则为普通的SQL语句可变参拼接
  64:          /// </summary>
  65:          public bool IsEntityToSql { get; set; }
  66:          public FilterTranslator()
  67:              : this(null)
  68:          {
  69:              IsEntityToSql = false;
  70:          }
  71:          /// <summary>
  72:          /// 构造函数
  73:          /// </summary>
  74:          /// <param name="group"></param>
  75:          public FilterTranslator(FilterGroup group)
  76:          {
  77:              this.Group = group;
  78:              this.Parms = new List<FilterParam>();
  79:          }
  80:      
  81:          /// <summary>
  82:          /// 翻译语句成sql的where查询条件
  83:          /// </summary>
  84:          public void Translate()
  85:          {
  86:              this.CommandText = TranslateGroup(this.Group);
  87:          }
  88:          /// <summary>
  89:          /// 对多组规则进行翻译解析
  90:          /// </summary>
  91:          /// <param name="group">规则数组</param>
  92:          /// <returns></returns>
  93:          public string TranslateGroup(FilterGroup group)
  94:          {
  95:              StringBuilder bulider = new StringBuilder();
  96:              if (group == null) return " 1=1 ";
  97:              var appended = false;
  98:              bulider.Append(groupLeftToken);
  99:              if (group.rules != null)
 100:              {
 101:                  foreach (var rule in group.rules)
 102:                  {
 103:                      if (appended)
 104:                          bulider.Append(GetOperatorQueryText(group.op));
 105:                      bulider.Append(TranslateRule(rule));
 106:                      appended = true;
 107:                  }
 108:              }
 109:              if (group.groups != null)
 110:              {
 111:                  foreach (var subgroup in group.groups)
 112:                  {
 113:                      if (appended)
 114:                          bulider.Append(GetOperatorQueryText(group.op));
 115:                      bulider.Append(TranslateGroup(subgroup));
 116:                      appended = true;
 117:                  }
 118:              }
 119:              bulider.Append(groupRightToken);
 120:              if (appended == false) return " 1=1 ";
 121:              return bulider.ToString();
 122:          }
 123:   
 124:          /// <summary>
 125:          /// 注册用户匹配管理,当不方便修改ligerRM.dll时,可以通过这种方式,在外部注册
 126:          ///  currentParmMatch.Add("{CurrentUserID}",()=>UserID);
 127:          /// currentParmMatch.Add("{CurrentRoleID}",()=>UserRoles.Split(',')[0].ObjToInt());
 128:          /// </summary>
 129:          /// <param name="match"></param>
 130:          public static void RegCurrentParmMatch(string key,Func<int> fn)
 131:          {
 132:              if (!currentParmMatch.ContainsKey(key))
 133:                  currentParmMatch.Add(key, fn);
 134:          }
 135:   
 136:          /// <summary>
 137:          /// 匹配当前用户信息,都是int类型
 138:          /// 对于CurrentRoleID,只返回第一个角色
 139:          /// 注意这里是用来定义隐藏规则,比如,用户只能自己访问等等,
 140:          /// </summary>
 141:          private static Dictionary<string, Func<int>> currentParmMatch = new Dictionary<string, Func<int>>()
 142:          {};
 143:          /// <summary>
 144:          /// 翻译规则
 145:          /// </summary>
 146:          /// <param name="rule">规则</param>
 147:          /// <returns></returns>
 148:          public string TranslateRule(FilterRule rule)
 149:          {
 150:            
 151:              StringBuilder bulider = new StringBuilder();
 152:              if (rule == null) return " 1=1 ";
 153:   
 154:              //如果字段名采用了 用户信息参数
 155:              if (currentParmMatch.ContainsKey(rule.field))
 156:              {
 157:                  var field = currentParmMatch[rule.field]();
 158:                  bulider.Append(paramPrefixToken + CreateFilterParam(field, "int"));
 159:              }
 160:              else //这里实现了数据库实体条件的拼接,[ID]=xxx的形式
 161:              {
 162:                 
 163:                 //如果是EF To Sql
 164:                  if (IsEntityToSql)
 165:                  {
 166:                      bulider.Append(" it." + rule.field+" ");
 167:                  }
 168:                  else
 169:                  {
 170:                      bulider.Append(leftToken + rule.field + rightToken);
 171:                  }
 172:              }
 173:              //操作符
 174:              bulider.Append(GetOperatorQueryText(rule.op));
 175:   
 176:              var op = rule.op.ToLower();
 177:              if (op == "like" || op == "endwith")
 178:              {
 179:                  var value = rule.value.ToString();
 180:                  if (!value.StartsWith(this.likeToken.ToString()))
 181:                  {
 182:                      rule.value = this.likeToken + value;
 183:                  }
 184:              }
 185:              if (op == "like" || op == "startwith")
 186:              {
 187:                  var value = rule.value.ToString();
 188:                  if (!value.EndsWith(this.likeToken.ToString()))
 189:                  {
 190:                      rule.value = value + this.likeToken;
 191:                  }
 192:              }
 193:              if (op == "in" || op == "notin")
 194:              {
 195:                  var values = rule.value.ToString().Split(',');
 196:                  var appended = false;
 197:                  bulider.Append("(");
 198:                  foreach (var value in values)
 199:                  {
 200:                      if (appended) bulider.Append(",");
 201:                      //如果值使用了 用户信息参数 比如: in ({CurrentRoleID},4)
 202:                      if (currentParmMatch.ContainsKey(value))
 203:                      {
 204:                          var val = currentParmMatch[value]();
 205:                          bulider.Append(paramPrefixToken + CreateFilterParam(val, "int"));
 206:                      }
 207:                      else
 208:                      {
 209:                          bulider.Append(paramPrefixToken + CreateFilterParam(value, rule.type)); 
 210:                      }
 211:                      appended = true;
 212:                  }
 213:                  bulider.Append(")");
 214:              } 
 215:              //is null 和 is not null 不需要值
 216:              else if (op != "isnull" && op != "isnotnull")
 217:              {
 218:                  //如果值使用了 用户信息参数 比如 [EmptID] = {CurrentEmptID}
 219:                  if (rule.value != null && currentParmMatch.ContainsKey(rule.value.ObjToStr()))
 220:                  {
 221:                      var value = currentParmMatch[rule.value.ObjToStr()]();
 222:                      bulider.Append(paramPrefixToken + CreateFilterParam(value, "int"));
 223:                  }
 224:                  else
 225:                  {
 226:                      bulider.Append(paramPrefixToken + CreateFilterParam(rule.value, rule.type));
 227:   
 228:                  }
 229:              } 
 230:              return bulider.ToString();
 231:          }
 232:          /// <summary>
 233:          /// 创建过滤规则参数数组
 234:          /// </summary>
 235:          /// <param name="value"></param>
 236:          /// <param name="type"></param>
 237:          /// <returns></returns>
 238:          private string CreateFilterParam(object value,string type)
 239:          {
 240:             
 241:              string paramName = "p" + ++paramCounter;
 242:              object val = value;
 243:             
 244:           
 245:              原版在这里要验证类型
 246:              //if (type.Equals("int", StringComparison.OrdinalIgnoreCase) || type.Equals("digits", StringComparison.OrdinalIgnoreCase))
 247:              //    val = val.ObjToInt ();
 248:              //if (type.Equals("float", StringComparison.OrdinalIgnoreCase) || type.Equals("number", StringComparison.OrdinalIgnoreCase))
 249:              //    val = type.ObjToDecimal();
 250:   
 251:              FilterParam param = new FilterParam(paramName, val);
 252:              this.Parms.Add(param);
 253:              return paramName;
 254:          }
 255:         
 256:          /// <summary>
 257:          /// 获取解析的参数
 258:          /// </summary>
 259:          /// <returns></returns>
 260:          public override string ToString()
 261:          {
 262:              StringBuilder bulider = new StringBuilder();
 263:              bulider.Append("CommandText:");
 264:              bulider.Append(this.CommandText);
 265:              bulider.AppendLine();
 266:              bulider.AppendLine("Parms:");
 267:              foreach (var parm in this.Parms)
 268:              {
 269:                  bulider.AppendLine(string.Format("{0}:{1}", parm.Name, parm.Value));
 270:              }
 271:              return bulider.ToString();
 272:          }
 273:     
 274:          #region 公共工具方法
 275:          /// <summary>
 276:          /// 获取操作符的SQL Text
 277:          /// </summary>
 278:          /// <param name="op"></param>
 279:          /// <returns></returns> 
 280:          public static string GetOperatorQueryText(string op)
 281:          {
 282:              switch (op.ToLower())
 283:              {
 284:                  case "add":
 285:                      return " + ";
 286:                  case "bitwiseand":
 287:                      return " & ";
 288:                  case "bitwisenot":
 289:                      return " ~ ";
 290:                  case "bitwiseor":
 291:                      return " | ";
 292:                  case "bitwisexor":
 293:                      return " ^ ";
 294:                  case "divide":
 295:                      return " / ";
 296:                  case "equal":
 297:                      return " = ";
 298:                  case "greater":
 299:                      return " > ";
 300:                  case "greaterorequal":
 301:                      return " >= ";
 302:                  case "isnull":
 303:                      return " is null ";
 304:                  case "isnotnull":
 305:                      return " is not null ";
 306:                  case "less":
 307:                      return " < ";
 308:                  case "lessorequal":
 309:                      return " <= ";
 310:                  case "like":
 311:                      return " like ";
 312:                  case "startwith":
 313:                      return " like ";
 314:                  case "endwith":
 315:                      return " like ";
 316:                  case "modulo":
 317:                      return " % ";
 318:                  case "multiply":
 319:                      return " * ";
 320:                  case "notequal":
 321:                      return " <> ";
 322:                  case "subtract":
 323:                      return " - ";
 324:                  case "and":
 325:                      return " and ";
 326:                  case "or":
 327:                      return " or ";
 328:                  case "in":
 329:                      return " in ";
 330:                  case "notin":
 331:                      return " not in ";
 332:                  default:
 333:                      return " = ";
 334:              }
 335:          }
 336:          #endregion
 337:   
 338:      }
 339:  }

可能大家说,这玩意怎么用呀?LigerUI做了一个专门针对组合查询的组件,也可以自己去写,有了开源的代码,相信我们自己也可以写出自己的组件.

我们前台的搜索设计就更容易了:

看看我的日志搜索模块怎么设置的搜索

   1:        //搜索表单应用ligerui样式
   2:        $("#formsearch").ligerForm({
   3:            fields: [
   4:             {display: "用户名", name: "UserName", newline: true, labelWidth: 100, width: 220, space: 30, type: "text",
   5:                  attr: { op: "equal" }, cssClass: "field"}
   6:                  ,
   7:             { display: "IP地址", name: "IPAddress", newline: false, labelWidth: 100, width: 220, space: 30, type: "text", cssClass: "field"},
   8:             { display: "开始时间", name: "CreateDate", newline: true, labelWidth: 100, width: 220, space: 30, type: "date", cssClass: "field", attr: { "op": "greaterorequal"}},
   9:             { display: "结束时间", name: "CreateDate", newline:false , labelWidth: 100, width: 220, space: 30, type: "date", cssClass: "field", attr: { "op": "lessorequal"}}
  10:             ],
  11:            appendID: false,
  12:            toJSON: JSON2.stringify
  13:        });
  14:   
  15:        //增加搜索按钮,并创建事件
  16:        LG.appendSearchButtons("#formsearch", grid);

也就是说,我们只需要设置规则,甚至可以自己去按照json格式传递给后台我们的规则就可以了,比如:

如果我们的Grid想设计条件,可以直接这么加

image

直接把这个where条件json化传递给后台就可以实现我们的按照条件查询Grid功能了.

这时候,大家想到了什么?

我们把条件where的部分更多的分担在UI层,我们的后台业务逻辑只需要解析where就可以再不改变业务逻辑的的条件下实现更复杂的业务逻辑.

其实,海南胡勇那位牛人设计的winform查询组件也是这个道理.

如果你还停留在拼接查询语句阶段,可以看看他们的设计.

最后,整个项目实际上,我非常不满意的是架构,这部分太差了,没有真正的公司工作经验,仅仅是粗浅的理解,深入学习,<<企业架构模式>>这本书买了也看不懂,缺少真正的工作经验,谈架构就是扯淡,所以,大家见谅.

如果觉得不错就推荐一下,支持一下吧!呵呵!

感谢,博客园的众多牛人提供了太多的学习资料和项目,让我们这些没有毕业的学生也有更多的学习资料.

这里也提供源码分享给更多学习的人.

注:推荐使用IE9,或者谷歌!IE8出现了BUG......呃!另外忘了说了,这个是vs2010开发,数据库是sql2005。。请确保安装mvc3,vs2010,sql2005。。。。。额。。。

 

目前1.1下载版本

附带源码网盘地址:http://pan.baidu.com/netdisk/singlepublic?fid=511632_114595096

设计的主要截图:

QQ截图20120807160843QQ截图20120807160852QQ截图20120807160740QQ截图20120807160809QQ截图20120807160818QQ截图20120807160827QQ截图20120807160835

转载于:https://www.cnblogs.com/mysweet/archive/2012/08/07/2626954.html

相关文章:

电脑壁纸励志_励志壁纸 | 要乖 要长大 要努力 要不负众望

全世界只有不到1%的人关注了壁纸阿姨你真是个特别的人2020.4.17要乖 要长大 要努力 要不负众望励志壁纸全文字数&#xff1a;236阅读时间&#xff1a;1分钟图片数目&#xff1a;361“我不懂什么年少轻狂&#xff0c;我只知道胜者为王。”点击图片 长按保存高清原图♥2“愿你以渺…

ubuntu自定义命令

ubuntu中通过alias可以自定义快捷命令 在.bashrc中加入alias指令可以定义快捷命令&#xff0c;以下为我常用快捷命令 alias watwatch -n 1 nvidia-smi alias gohomecd /home/B/gaoye alias cdcodecd /home/B/gaoye/code 转载于:https://www.cnblogs.com/yeran/p/11367988.html

OSPF LSA 类型

路由器LSA&#xff1a;每台路由器都创建1类LSA&#xff0c;用于向连接的每个区域描述自己&#xff0c;在每台路由器中&#xff0c;每个区域的LSDB都包含一个1类LSA&#xff0c;它指出了当前路由器的RID和所有接口的IP地址。1类LSA还用于描述末节网络。网络LSA&#xff1a;每个中…

配件商城项目总结

---恢复内容开始--- 一、在首页导航栏上有一个自动摇晃的手机图标 &#xff0c;而我一开始设置的是悬浮摇晃 由于将悬浮设置在图片外面的容器&#xff08;a&#xff09;上导致效果没出来&#xff0c;而且动画效果一直没出来。 解决方法&#xff1a;将悬浮改成自动播放&#xff…

006本周总结报告

这周基本学完了java的基础中的基础&#xff0c;还不会灵活的应用&#xff0c;相关概念仍然有些模糊。为此&#xff0c;自己将自己学到的知识点做了下系统的复习&#xff0c;并作了相关的笔记。这周编程的大部分时间主要用于小学期PTA的编程作业中&#xff08;用C语言&#xff0…

excel小写转大写公式_【Excel函数贴】五个技巧性函数小套路

来吧 来吧 来吧 一起舞蹈 什么烦恼可以将我打扰…………1&#xff0c;字母大小写。一个做外贸的朋友问&#xff0c;Excel有没有函数可以把英文从小写变大写&#xff1f;他可能碰到蛮多洋人的人名或者货名需要大小写转换的。小写转大写&#xff1a;UPPER("excel")大写…

DevExpress A field with the name '' was not found on the selected data source.

绑定控件时发现的错误&#xff0c;找了很久终于找到原因了&#xff0c;可能也是大家没注意的地方&#xff0c;希望能给大家带来一些帮助。 自己在找的时候发现&#xff0c;明明是有的。 结果应该是这样的 上面定义实体类的字段写法有缺陷 这样再重新编译运行后就不会出错了。转…

刚申请了Blog,首贴庆祝!

刚申请了Blog&#xff0c;首贴庆祝&#xff01;转载于:https://www.cnblogs.com/ele-eye/archive/2011/11/17/2252654.html

ReentrantLock实现原理分析

ReentrantLock主要利用CASCLH队列来实现。它支持公平锁和非公平锁&#xff0c;两者的实现类似。 CAS&#xff1a;Compare and Swap&#xff0c;比较并交换。CAS有3个操作数&#xff1a;内存值V、预期值A、要修改的新值B。当且仅当预期值A和内存值V相同时&#xff0c;将内存值V修…

python编码

Unicode字符集中收录110多万个字符集合。UTF-8&#xff08;8-bit Unicode Transformation Format&#xff09;&#xff0c;是一种针对 Unicode 的可变长度字符编码方式。使用一到四个字节来编码 Unicode 字符 在计算机内存中统一使用Unicode编码&#xff0c;当需要保存到硬盘或…

MySQL性能测试工具 mysqlslap

先看参数介绍 FormatOption FileDescriptionIntroduced--auto-generate-sqlauto-generate-sqlGenerate SQL statements automatically when they are not supplied in files or using command options --auto-generate-sql-add-autoincrementauto-generate-sql-add-autoincreme…

atlas单机模式代码_用代码玩太无聊,这样玩海盗游戏《ATLAS》单机模式才是正确玩法...

在各大单机游戏中&#xff0c;存在很多的代码给玩家使用&#xff0c;利用这些代码&#xff0c;玩家就能和开了挂似得快速通关。这让不少玩家沉迷于代码的世界而无心享受游戏的乐趣&#xff0c;因此在游戏界中经常有代码毁了一款游戏的说法。这点放在最近才上线的海盗冒险生存游…

iSCSI软件套件 介绍

http://blog.csdn.net/do2jiang/article/details/5062586 iSCSI&#xff08;Internet SCSI&#xff09;是2003年IETF&#xff08;InternetEngineering Task Force&#xff0c;互联网工程任务组&#xff09;制订的一项标准&#xff0c;这种指令集合可以实现在IP网络上运行SCSI协…

【Computer Vision】 复现分割网络(1)——SegNet

目录 Tags: ComputerVision编译数据处理训练结果ReferenceTags: ComputerVision 编译 src/caffe/layers/contrastive_loss_layer.cpp:56:30: error: no matching function for call to ‘max(double, float)’ Dtype dist std::max(margin - sqrt(dist_sq_.cpu_data()[i]), Dt…

kotlin + springboot 整合redis,Redis工具类编写及单元测试

参考自&#xff1a; https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html 1、maven依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://…

:before和::before的区别

在一次项目中&#xff0c;有一次要用到::selection伪元素&#xff0c;然后开发同学问我&#xff0c;CSS中一个冒号和两个冒号有神马区别&#xff1f; 这好像真的是个问题&#xff0c;或许很多前端同学对此都有疑惑&#xff0c;查了些资料&#xff0c;证实了下两个符号的区别&am…

python下载大文件mp4_python合并大量ts文件成mp4格式(ps:上限是450,亲测)

原博文 2018-08-22 17:34 − 1 import os 2 #exec_str rcopy /b ts/c9645620628078.tsts/c9645620628079.ts ts/1.ts 3 #os.system(exec_str) 4 f open(index.m3u8, r, encod...08595 相关推荐 2019-12-19 14:27 − ts readonly name "xxx"; updateValueAndValidi…

提高网站页面收录的几个方法 返回列表 发新帖回复

首先是清楚网站总体有多少页面。 可以用xenu扫描出所有的页面。 1.html地图 网页数量不是太多&#xff0c;可以用网站地图来增加收录&#xff0c;分成几个地图页面。 2.随机文章模块 在不影响用户体验的情况下&#xff0c;在栏目中增加随机文章模块&#xff0c;增加链接曝光度&…

JSP+Servlet+JavaBean

JSP相当于在HTML页面中加上Java代码&#xff0c;一般在<body>标签中放入主要代码。 在JSP里用<%...%>把Java代码包含起来的。 Servlet的生命周期&#xff1a; ①被服务器实例化后&#xff0c;容器运行init方法。 ②当请求&#xff08;Request&#xff09;到达时&am…

logistic回归 如何_第七章:利用Python实现Logistic回归分类模型

免责声明&#xff1a;本文是通过网络收集并结合自身学习等途径合法获取&#xff0c;仅作为学习交流使用&#xff0c;其版权归出版社或者原创作者所有&#xff0c;并不对涉及的版权问题负责。若原创作者或者出版社认为侵权&#xff0c;请联系及时联系&#xff0c;我将立即删除文…

多年没有管理的技术博客了,即日起开始管理起技术博客

多年没有管理的技术博客了&#xff0c;即日起开始管理起技术博客&#xff0c;希望朋友们一如既往的支持转载于:https://www.cnblogs.com/flashicp/archive/2012/08/14/2639054.html

GNS3的默认Telnet程序改成secureCRT

编辑-首选项-一般里的“终端命令”改为C:\Users\ldy\AppData\Local\VanDyke Software\SecureCRT\SecureCRT.exe /t /telnet %h %p 前面是SecureCRT程序的目录&#xff0c; /t是指建立一个新标签 &#xff0c; /telnet的意思是走Telnet协议&#xff0c; %h是要telnet到的主机&am…

关于Vue实例的生命周期created和mounted的区别

关于作者 程序开发人员&#xff0c;不拘泥于语言与技术&#xff0c;目前主要从事PHP和前端开发&#xff0c;使用Laravel和VueJs&#xff0c;App端使用Apicloud混合式开发。合适和够用是最完美的追求。 个人网站&#xff1a;http://www.linganmin.cn 最近刚写了一个手机在线播放…

UVa 10112 - Myacm Triangles

UVa第一卷最后一题。 求内部不含点并且面积最大的三角形。 暴力。 代码如下&#xff1a; 1 #include<iostream>2 #include<cstdio>3 #include<cmath>4 #include<cstring>5 6 using namespace std;7 8 typedef struct node9 { 10 char ch; 11 i…

[转]ASP.NET1.0升级ASP.NET2.0问题总结

来自&#xff1a;http://www.enet.com.cn/article/2006/0310/A20060310510518.shtml1&#xff0e;Global.asax文件的处理形式不一样&#xff0c;转化后将出现错误 在vs2003中Global.asax具有代码后置文件&#xff0c;2.0下, 将代码分离文件移到 App_Code 目录下&#xff0c;以便…

python文本编码转换_Python: 转换文本编码

最近在做周报的时候&#xff0c;需要把csv文本中的数据提取出来制作表格后生产图表。 在获取csv文本内容的时候&#xff0c;基本上都是用with open(filename, encoding UTF-8) as f:来打开csv文本&#xff0c;但是实际使用过程中发现有些csv文本并不是utf-8格式&#xff0c;从而…

ipone 网页版的iphone

本文摘自&#xff1a;http://www.cocoachina.com/bbs/m/list.php?fid6#list

import static

import static&#xff08;静态导入&#xff09;是JDK1.5中的新特性&#xff0c;一般我们导入一个类都用 import com.....ClassName;而静态导入是这样&#xff1a;import static com.....ClassName.*;这里多了个static&#xff0c;还有就是类名ClassName后面多了个 .* &#xf…

poj1423

http://acm.pku.edu.cn/JudgeOnline/problem?id1423n!(log10(sqrt(4.0*acos(0.0)*n))n*(log10(n)-log10(exp(1.0)))1);n1 除外 转载于:https://www.cnblogs.com/FCWORLD/archive/2011/03/12/1982355.html

python缩进在程序中长度统一且强制使用_Python习题纠错1

February, 1991 0.9.1 2.Python语言的缩进只要统一即可&#xff0c;不一定是4个空格&#xff08;尽管这是惯例&#xff09;。 Python缩进在程序中长度统一且强制使用. 3.IPO&#xff1a;Input Process Output 4.Python合法命名的首字符不能是数字。 5.Python保留字&#xff1a;…