首页

教你用面向对象编程写一个烟花爆炸的

前端达人

点击查看原图



想要学会这个漂亮的烟花吗?快来跟着学习吧~

结构

<div class="container"></div>

我们只需要一个盒子表示烟花爆炸范围就可以了

样式

fire是烟花 注意添加绝对定位

 <style>
    .container{
        margin: 0 auto;
        height: 500px;
        width: 1200px;
        background: black;
        position: relative;
        overflow: hidden;
    }
    .fire{
        width: 10px;
        background: white;
        height: 10px;
        /* border-radius: 50%; */
        position: absolute;
        bottom: 0;
    }
    </style>



行为

编写构造函数Firework

需要用到一个鼠标点击的位置,一个div选择器,一个爆炸样式

 function Firework(x,y,selector,type){
        //此处获取对象的方式为单例的思想,避免重复获取相同的元素
        if(Firework.box && selector === Firework.box.selector){
            this.box =  Firework.box.ele;
        }else{
            Firework.box = {
                ele:document.querySelector(selector),
                selector:selector
            }
            this.box = Firework.box.ele;
        }
        this.type = type;
        this.init(x,y)
    }



封装一个运动的方法
function animation(ele,attroptions,callback){
    for(var attr in attroptions){
        attroptions[attr] ={
            target:attroptions[attr],
            inow:parseInt(getComputedStyle(ele)[attr])
        } 
    }
    clearInterval(ele.timer);
    ele.timer = setInterval(function(){
        for(var attr in attroptions ){
            var item = attroptions[attr]
            var target = item.target;
            var inow = item.inow;
            var speed = (target - inow)/10;
            speed = speed>0?Math.ceil(speed):Math.floor(speed);
            if(Math.abs(target - inow) <= Math.abs(speed)){
                ele.style[attr] = target+"px";
                delete attroptions[attr];
                for(var num  in attroptions){
                    return false;
                }
                clearTimeout(ele.timer);
                if(typeof callback === "function")callback();
            }else{
                attroptions[attr].inow += speed;
                ele.style[attr]  = attroptions[attr].inow+"px";
            }
        }
    },30)
}



编写原型方法
Firework.prototype = {
        constructor:Firework,
        //初始化
        init:function(x,y){
            //创建一个烟花
            this.ele = this.createFirework();
            //xy为鼠标落点
            this.x = x ;
            this.y = y;
            //maxXy为最大运动范围
            this.maxX = this.box.offsetWidth - this.ele.offsetWidth;
            this.maxY = this.box.offsetHeight - this.ele.offsetHeight;
            //初始化结束后  烟花随机颜色
            this.randomColor(this.ele);
            //烟花升空
            this.fireworkUp(this.ele);
        },
        //创造烟花
        createFirework:function(){
            var ele = document.createElement("div");
            ele.className = "fire";
            this.box.appendChild(ele);
            return ele;
        },
        //烟花升空
        fireworkUp:function(ele){
            ele.style.left = this.x + "px";
            //此处用到刚刚封装的运动方法
            animation(ele,{top:this.y},function(){
                ele.remove();
                this.fireworkBlast()
            }.bind(this));
        },
        //烟花爆炸
        fireworkBlast:function(){
            for(var i = 0 ; i < 20; i++){
                var ele = document.createElement("div");
                ele.className = "fire";
                ele.style.left = this.x + "px";
                ele.style.top = this.y + "px";
                this.box.appendChild(ele);
                ele.style.borderRadius = "50%";
                this.randomColor(ele);
                //判定一下输入的爆炸方式是原型烟花 还是散落烟花 由此更改获取的烟花位置
                animation(ele,this.type === "circle"?this.circleBlast(i,20): this.randomPosition(),function(cale){
                    cale.remove();
                }.bind(this,ele))
            }
        },
        //圆形爆炸位置
        circleBlast:function(i,total){
            var r = 200;
            var reg = 360 / total *i;
            var deg = Math.PI / 180 *reg;
            return {
                left:r * Math.cos(deg) + this.x ,
                top:r * Math.sin(deg) + this.y 
            }
        },
        //随机颜色
        randomPosition:function(){
            return {
                left : Math.random()*this.maxX,
                top : Math.random()*this.maxY
            }
        },
        randomColor:function(ele){
            var color =  "#" + parseInt(parseInt("ffffff",16)*Math.random()).toString(16).padStart(6,0);
            return ele.style.backgroundColor = color;
        }
    }



绑定事件
document.querySelector(".container").addEventListener("click",function(evt){
    var e = evt||event;
    new Firework(e.offsetX,e.offsetY,".container","circle")
    new Firework(e.offsetX,e.offsetY,".container")
})

全部代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
    .container{
        margin: 0 auto;
        height: 500px;
        width: 1200px;
        background: black;
        position: relative;
        overflow: hidden;
    }
    .fire{
        width: 10px;
        background: white;
        height: 10px;
        /* border-radius: 50%; */
        position: absolute;
        bottom: 0;
    }
    </style>
</head>
<body>
    <div class="container"></div>
    <script src="./utils.js"></script>
    <script>

    function animation(ele,attroptions,callback){
        for(var attr in attroptions){
            attroptions[attr] ={
                target:attroptions[attr],
                inow:parseInt(getComputedStyle(ele)[attr])
            } 
        }
        clearInterval(ele.timer);
        ele.timer = setInterval(function(){
            for(var attr in attroptions ){
                var item = attroptions[attr]
                var target = item.target;
                var inow = item.inow;
                var speed = (target - inow)/10;
                speed = speed>0?Math.ceil(speed):Math.floor(speed);
                if(Math.abs(target - inow) <= Math.abs(speed)){
                    ele.style[attr] = target+"px";
                    delete attroptions[attr];
                    for(var num  in attroptions){
                        return false;
                    }
                    clearTimeout(ele.timer);
                    if(typeof callback === "function")callback();
                }else{
                    attroptions[attr].inow += speed;
                    ele.style[attr]  = attroptions[attr].inow+"px";
                }
            }
        },30)
    }  

        function Firework(x,y,selector,type){
            if(Firework.box && selector === Firework.box.selector){
                this.box =  Firework.box.ele;
            }else{
                Firework.box = {
                    ele:document.querySelector(selector),
                    selector:selector
                }
                this.box = Firework.box.ele;
            }
            this.type = type;
            this.init(x,y)
        }

        Firework.prototype = {
            constructor:Firework,
            //初始化
            init:function(x,y){
                this.ele = this.createFirework();
                this.x = x ;
                this.y = y;
                this.maxX = this.box.offsetWidth - this.ele.offsetWidth;
                this.maxY = this.box.offsetHeight - this.ele.offsetHeight;
                this.randomColor(this.ele);
                this.fireworkUp(this.ele);
            },
            //创造烟花
            createFirework:function(){
                var ele = document.createElement("div");
                ele.className = "fire";
                this.box.appendChild(ele);
                return ele;
            },
            fireworkUp:function(ele){
                ele.style.left = this.x + "px";
                animation(ele,{top:this.y},function(){
                    ele.remove();
                    this.fireworkBlast()
                }.bind(this));
            },
            //烟花爆炸
            fireworkBlast:function(){
                for(var i = 0 ; i < 20; i++){
                    var ele = document.createElement("div");
                    ele.className = "fire";
                    ele.style.left = this.x + "px";
                    ele.style.top = this.y + "px";
                    this.box.appendChild(ele);
                    ele.style.borderRadius = "50%";
                    this.randomColor(ele);
                    animation(ele,this.type === "circle"?this.circleBlast(i,20): this.randomPosition(),function(cale){
                        cale.remove();
                    }.bind(this,ele))
                }
            },
            circleBlast:function(i,total){
                var r = 200;
                var reg = 360 / total *i;
                var deg = Math.PI / 180 *reg;
                return {
                    left:r * Math.cos(deg) + this.x ,
                    top:r * Math.sin(deg) + this.y 
                }
            },
            randomPosition:function(){
                return {
                    left : Math.random()*this.maxX,
                    top : Math.random()*this.maxY
                }
            },
            randomColor:function(ele){
                var color =  "#" + parseInt(parseInt("ffffff",16)*Math.random()).toString(16).padStart(6,0);
                return ele.style.backgroundColor = color;
            }
        }

        document.querySelector(".container").addEventListener("click",function(evt){
            var e = evt||event;
            new Firework(e.offsetX,e.offsetY,".container","circle")
            new Firework(e.offsetX,e.offsetY,".container")
        })
    </script>
</body>
</html>

————————————————
版权声明:本文为CSDN博主「SpongeBooob」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41383900/article/details/105026768


NodeJS服务总是崩溃的解决办法

seo达人

许多人都有这样一种映像,NodeJS比较快; 但是因为其是单线程,所以它不稳定,有点不安全,不适合处理复杂业务; 它比较适合对并发要求比较高,而且简单的业务场景。 

在Express的作者的TJ Holowaychuk的 告别Node.js一文中列举了以下罪状: 

Farewell NodeJS (TJ Holowaychuk) 

•   you may get duplicate callbacks 
•   you may not get a callback at all (lost in limbo) 
•   you may get out-of-band errors 
•   emitters may get multiple “error” events 
•   missing “error” events sends everything to hell 
•   often unsure what requires “error” handlers 
•   “error” handlers are very verbose 
•   callbacks suck 

其实这几条主要吐嘈了两点: node.js错误处理很扯蛋,node.js的回调也很扯蛋。

 

 

事实上呢?

 


事实上NodeJS里程确实有“脆弱”的一面,单线程的某处产生了“未处理的”异常确实会导致整个Node.JS的崩溃退出,来看个例子, 这里有一个node-error.js的文件: 

 

var http = require('http');

var server = http.createServer(function (req, res) {

  //这里有个错误,params 是 undefined
  var ok = req.params.ok;

  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World
');
});

server.listen(8080, '127.0.0.1');

console.log('Server running at http://127.0.0.1:8080/');


启动服务,并在地址栏测试一下发现 http://127.0.0.1:8080/  不出所料,node崩溃了 


 

$ node node-error
Server running at http://127.0.0.1:8080/

c:githubscript
ode-error.js:5
  var ok = req.params.ok;
                     ^
TypeError: Cannot read property 'ok' of undefined
    at Server.<anonymous> (c:githubscript
ode-error.js:5:22)
    at Server.EventEmitter.emit (events.js:98:17)
    at HTTPParser.parser.onIncoming (http.js:2108:12)
    at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:23)
    at Socket.socket.ondata (http.js:1966:22)
    at TCP.onread (net.js:525:27)



 

怎么解决呢?


其实Node.JS发展到今天,如果连这个问题都解决不了,那估计早就没人用了。 

 

使用uncaughtException


我们可以uncaughtException来全局捕获未捕获的Error,同时你还可以将此函数的调用栈打印出来,捕获之后可以有效防止node进程退出,如: 

 

process.on('uncaughtException', function (err) {
  //打印出错误
  console.log(err);
  //打印出错误的调用栈方便调试
  console.log(err.stack);
});


这相当于在node进程内部进行守护, 但这种方法很多人都是不提倡的,说明你还不能完全掌控Node.JS的异常。 

 

使用 try/catch


我们还可以在回调前加try/catch,同样确保线程的安全。 

 

var http = require('http');

http.createServer(function(req, res) {
  try {
    handler(req, res);
  } catch(e) {
    console.log('
', e, '
', e.stack);
    try {
      res.end(e.stack);
    } catch(e) { }
  }
}).listen(8080, '127.0.0.1');

console.log('Server running at http://127.0.0.1:8080/');

var handler = function (req, res) {
  //Error Popuped
  var name = req.params.name;

  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello ' + name);
};


这种方案的好处是,可以将错误和调用栈直接输出到当前发生的网页上。 

 

集成到框架中


标准的HTTP响应处理会经历一系列的Middleware(HttpModule),最终到达Handler,如下图所示: 

\ 


这 些Middleware和Handler在NodeJS中都有一个特点,他们都是回调函数,而回调函数中是唯一会让Node在运行时崩溃的地方。根据这个 特点,我们只需要在框架中集成一处try/catch就可以相对完美地解决异常问题,而且不会影响其它用户的请求request。 

事实上现在的NodeJS WEB框架几乎都是这么做的,如 OurJS开源博客所基于的 WebSvr 

就有这么一处异常处理代码: 

 

Line: 207

  try {
    handler(req, res);
  } catch(err) {
    var errorMsg
      = '
'
      + 'Error ' + new Date().toISOString() + ' ' + req.url
      + '
'
      + err.stack || err.message || 'unknow error'
      + '
'
      ;

    console.error(errorMsg);
    Settings.showError
      ? res.end('<pre>' + errorMsg + '</pre>')
      : res.end();
  }


那么不在回调中产生的错误怎么办?不必担心,其实这样的node程序根本就起不起来。 

此外node自带的 cluster 也有一定的容错能力,它跟nginx的worker很类似,但消耗资源(内存)略大,编程也不是很方便,OurJS并没有采用此种设计。 

 

守护NodeJS进程和记录错误日志


现 在已经基本上解决了Node.JS因异常而崩溃的问题,不过任何平台都不是100%可靠的,还有一些错误是从Node底层抛出的,有些异常 try/catch和uncaughtException都无法捕获。之前在运行ourjs的时侯,会偶尔碰到底层抛出的文件流读取异常,这就是一个底层 libuv的BUG,node.js在0.10.21中进行了修复。 

面对这种情况,我们就应该为nodejs应用添加守护进程,让NodeJS遭遇异常崩溃以后能马上复活。 

另外,还应该把这些产生的异常记录到日志中,并让异常永远不再发生。 

 

使用node来守护node


node-forever 提供了守护的功能和LOG日志记录功能。 

安装非常容易 

 

[sudo] npm install forever


使用也很简单 

 

$ forever start simple-server.js
$ forever list
  [0] simple-server.js [ 24597, 24596 ]


还可以看日志 

 

forever -o out.log -e err.log my-script.js


 

使用shell启动脚本守护node


使用node来守护的话资源开销可能会有点大,而且也会略显复杂,OurJS直接在开机启动脚本来进程线程守护。 

如在debian中放置的 ourjs 开机启动文件: /etc/init.d/ourjs 

这个文件非常简单,只有启动的选项,守护的核心功能是由一个无限循环 while true; 来实现的,为了防止过于密集的错误阻塞进程,每次错误后间隔1秒重启服务 

 

WEB_DIR='/var/www/ourjs'
WEB_APP='svr/ourjs.js'

#location of node you want to use
NODE_EXE=/root/local/bin/node

while true; do
    {
        $NODE_EXE $WEB_DIR/$WEB_APP config.magazine.js
        echo "Stopped unexpected, restarting 

"
    } 2>> $WEB_DIR/error.log
    sleep 1
done


 

错误日志记录也非常简单,直接将此进程控制台当中的错误输出到error.log文件即可: 2>> $WEB_DIR/error.log  这一行, 2 代表 Error。

JSP的刨根问底

前端达人

JSP的刨根问底

  • 一.概念
  • 二.原理
  • 三.脚本
  • 四.内置对象
  • 五.注释
  • 六.编译指令
  • 七.动作指令


  • 点击查看原图


    这篇文章从一个初学者的角度,复习一波JSP。






    一.概念
    Java Server Pages: java服务器端页面

    可以理解为:一个特殊的页面,其中既可以指定定义html标签,又可以定义java代码
    用于简化书写!!!
    二.原理
    本质是一个Servlet

    三.脚本
    定义:Jsp定义java代码的方式

    <% 代码 %>:定义的java代码,在service方法中。service方法中可以定义什么,该脚本中就可以定义什么。
    <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置。
    <%= 代码 %>:定义的java代码,会输出到页面上。输出语句中可以定义什么,该脚本中就可以定义什么。
    四.内置对象
    对象名 实现接口或继承类 作用
    PageContext 当前页面共享数据,还可以获取其他八个内置对象
    request HttpServletRequest 一次请求访问的多个资源(转发)
    session HttpSession 一次会话的多个请求间
    application ServletContext 所有用户间共享数据
    response HttpServletResponse 响应对象
    page Object 当前页面(Servlet)的对象 this
    out JspWriter 输出对象,数据输出到页面上
    config ServletConfig Servlet的配置对象
    expection Throwable 异常对象
    五.注释
    1.html注释
    <!-- -->:只能注释html代码片段
    2.jsp注释
    <%-- --%>:可以注释所有

    六.编译指令
    作用
    用于配置JSP页面,导入资源文件

    格式
    <%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
    分类
    1.page
    配置JSP页面的
    1. contentType:等同于response.setContentType()
    *设置响应体的mime类型以及字符集
    * 设置当前jsp页面的编码(只能是高级的IDE才能生效,如果使用低级工具,则需要设置pageEncoding属性设置当前页面的字符集)
    2.import:导包
    3. errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
    4.isErrorPage:标识当前也是是否是错误页面。
    * true:是,可以使用内置对象exception
    * false:否。默认值。不可以使用内置对象exception
    2.include
    页面包含的。导入页面的资源文件

     <%@include file="top.jsp"%>
    3.导入资源
    导入资源

     <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      prefix:前缀,自定义的
    1
    七.动作指令
    作用
    动作指令与编译指令不间,编译指令是通知 Servlet 引擎的处理消息,而动作指令只是运行时的脚本动作。编译指令在将JSP 编译成 Servlet 时起作用:处理指令通常可替换成 Java脚本,是 JSP脚本的标准化写法。

    分类
    指令 作用
    jsp:forward 执行页面转向,将请求的处理转发到下一个页面。
    jsp:param 用于传递参数,必须与其他支持参数曲标签一起使用。
    jsp:include 用于动态引入一个 JSP 页面。
    jsp:plugin 用于下载 JavaBean 或 Applet 到客户端执行。
    jsp:useBean 使用 JavaBean。
    jsp:setProperty 修改 JavaBean 实例的属性值。
    jsp:getProperty 获取 JavaBean 实例的属性值。
    具体细节:
    jsp:forward:
    动作把请求转到另外的页面。可以转发静态的HTML页面,也可以转发动态的JSP页面,或者转发到容器中的servlet jsp:forward标记只有一个属性page。 page属性包含的是一个相对URL。 page的值既可以直接给出,也可以在请求的时候动态计算。

    jsp:param
    用于设定参数值,这个指令不能单独使用 可以与以下三个指令结合使用:
    jsp:include :用于将参数值出入被导入页面
    jsp:forword : 用于将参数值传入被转向页面
    jsp:plugin : 用于将参数值传入页面中javaBean的实例

    jsp:include
    (拿目标页面插入原有页面)该动作是一个动态的include指令,也用于带入某个页面,他不会导入被include页面的编译指令,仅仅导入页面的body内容插入到本页面
    该动作把指定文件插入正在生成的页面。其语法如下:   flush:用于指定输出缓存是否转移到被导入的文件中, true:包含在被导入的文件中 false:包含在源文件中
    前面已经介绍过include指令,它是在JSP文件被转换成Servlet的时候引入文件,而这里的jsp:include动作不同,插入文件的时间是在页面被请求的时候。j
    sp:include动作的文件引入时间决定了它的效率要稍微差一点,而且被引用文件不能包含某些JSP代码(例如不能设置HTTP头),但它的灵活性却要好得多。
    jsp:plugin

    用于下载服务器端的javaBean或applet到客户端)
    jsp:plugin动作用来根据浏览器的类型,插入通过Java插件运行Java Applet所必需的OBJECT或EMBED元素。

    <jsp:plugin  
      type="bean | applet"   : 被执行的java程序的类型
      code="classFileName" :被执行的文件名,必须以  .class 结尾
      codebase="classFileDirectoryName"   :被执行文件的所在目录
      [ name="instanceName" ] :给程序起一个名字用来标识该程序
      [ archive="URIToArchive, ..." ] :指向一些要预先载入的将要使用到的类
      [ align="bottom | top | middle | left | right" ] :
      [ height="displayPixels" ]
      [ width="displayPixels" ]
      [ hspace="leftRightPixels" ] 
      [ vspace="topBottomPixels" ]
      [ jreversion="JREVersionNumber | 1.1" ]   :能正确运行改程序必须的JRE的版本
      [ nsplug inurl="URLToPlugin" ]  
      [ iepluginurl="URLToPlugin" ] >
      [ <jsp:params>
      [ <jsp:param name="parameterName" value="{parameterValue | <%= expression %>}" /> ]+
      </jsp:params> ]
      [ <jsp:fallback> text message for user </jsp:fallback> ]  :当不能正确显示该Applet时,显示该指令中的文本提示
     <jsp:plugin>
    



    jsp:useBean
    useBean:用于在jsp页面中初始化一个java实例(如果多个jsp中需要重复使用某段代码,可以把这段代码定义成java类在页面中引用)
    jsp:useBean动作用来装载一个将在JSP页面中使用的JavaBean。这个功能非常有用,因为它使得我们既可以发挥Java组件重用的优势,同时也避免了损失JSP区别于Servlet的方便性。
    jsp:useBean动作最简单的语法为:<jsp:useBean id=“JavaBean的名称” class=“package.class"包名.类名” scope=“有效范围”/>

    这行代码的含义是:“创建一个由class属性指定的类的实例,然后把它绑定到其名字由id属性给出的变量上”。不过,就象我们接下来会看到的,定义一个scope属性可以让Bean关联到更多的页面,它可接受四个值:request、session、page、application。此时,jsp:useBean动作只有在不存在同样id和scope的Bean时才创建新的对象实例,同时,获得现有Bean的引用就变得很有必要。
    获得Bean实例之后,要修改Bean的属性既可以通过jsp:setProperty动作进行,也可以在Scriptlet中利用id属性所命名的对象变量,通过调用该对象的方法显式地修改其属性。这使我们想起,当我们说“某个Bean有一个类型为X的属性foo”时,就意味着“这个类有一个返回值类型为X的getFoo方法,还有一个setFoo方法以X类型的值为参数”。  有关jsp:setProperty动作的详细情况在后面讨论。但现在必须了解的是,我们既可以通过jsp:setProperty动作的value属性直接提供一个值,也可以通过param属性声明Bean的属性值来自指定的请求参数,还可以列出Bean属性表明它的值应该来自请求参数中的同名变量。
    在JSP表达式或Scriptlet中读取Bean属性通过调用相应的getXXX方法实现,或者更一般地,使用jsp:getProperty动作。
    注意,包含Bean的类文件应该放到服务器正式存放Java类的目录下,而不是保留给修改后能够自动装载的类的目录。例如,对于Java Web
    Server来说,Bean和所有Bean用到的类都应该放入classes目录,或者封装进jar文件后放入lib目录,但不应该放到servlets下。
    id:javaBean的实例名 class: javaBean的实现类 scope:指定javaBean实例的生存范围
    page:javaBean仅在该页面有效 request:javaBean在本次请求中有效 session:
    javaBean在本次session内有效 application:
    javaBean在本应用内一直有效  下面是一个很简单的例子,它的功能是装载一个Bean,然后设置/读取它的message属性。
    关于jsp:useBean的进一步说明   使用Bean最简单的方法是先用下面的代码装载Bean:   <jsp:useBean id=“name” class=“package.class” />
    然后通过jsp:setProperty和jsp:getProperty修改和提取Bean的属性。 不过有两点必须注意。   第一,我们还可以用下面这种格式实例化Bean: <jsp:useBean …>   Body   </jsp:useBean>
    它的意思是,只有当第一次实例化Bean时才执行Body部分,如果是利用现有的Bean实例则不执行Body部分。正如下面将要介绍的,jsp:useBean并非总是意味着创建一个新的Bean实例。
    第二,除了id和class外,jsp:useBean还有其他三个属性,即:scope、type、beanName。
    id:命名引用该Bean的变量。如果能够找到id和scope相同的Bean实例,jsp:useBean动作将使用已有的Bean实例而不是创建新的实例。
    class:指定Bean的完整包名。
    scope:指定Bean在哪种上下文内可用,可以取下面的四个值之一:page、request、session和application。  默认值是page,表示该Bean只在当前页面内可用(保存在当前页面的PageContext内)。
    request表示该Bean在当前的客户请求内有效(保存在ServletRequest对象内)。
    session表示该Bean对当前HttpSession内的所有页面都有效。
    最后,如果取值application,则表示该Bean对所有具有相同ServletContext的页面都有效。
    scope之所以很重要,是因为jsp:useBean只有在不存在具有相同id和scope的对象时才会实例化新的对象;
    如果已有id和scope都相同的对象则直接使用已有的对象,此时jsp:useBean开始标记和结束标记之间的任何内容都将被忽略。
    type:指定引用该对象的变量的类型,它必须是Bean类的名字、超类名字、该类所实现的接口名字之一。请记住变量的名字是由id属性指定的。
    beanName:指定Bean的名字。如果提供了type属性和beanName属性,允许省略class属性。

    jsp:setProperty
    jsp:setProperty用来设置已经实例化的Bean对象的属性,有两种用法。
    首先,你可以在jsp:useBean元素的外面(后面)使用jsp:setProperty,    …

    第二种用法是把jsp:setProperty放入jsp:useBean元素的内部, …

    jsp:setProperty动作有下面四个属性:name:表示要设置属性的是哪个Bean。  property:表示要设置哪个属性。有一个特殊用法:如果property的值是"",表示所有名字和Bean属性名字匹配的请求参数都将被传递给相应的属性set方法。  value:value属性是可选的。该属性用来指定Bean属性的值。字符串数据会在目标类中通过标准的valueOf方法自动转换成数字、boolean、Boolean、byte、Byte、char、Character。例如,boolean和Boolean类型的属性值(比如“true”)通过Boolean.valueOf转换,int和Integer类型的属性值(比如"42")通过Integer.valueOf转换。  value和param不能同时使用,但可以使用其中任意一个。  Param:param是可选的。它指定用哪个请求参数作为Bean属性的值。如果当前请求没有参数,则什么事情也不做,系统不会把null传递给Bean属性的set方法。因此,你可以让Bean自己提供默认属性值,只有当请求参数明确指定了新值时才修改默认属性值。  例如,下面的代码片断表示:如果存在numItems请求参数的话,把numberOfItems属性的值设置为请求参数numItems的值;否则什么也不做。    如果同时省略value和param,其效果相当于提供一个param且其值等于property的值。进一步利用这种借助请求参数和属性名字相同进行自动赋值的思想,你还可以在property(Bean属性的名字)中指定“”,然后省略value和param。此时,服务器会查看所有的Bean属性和请求参数,如果两者名字相同则自动赋值。  下面是一个利用JavaBean计算素数的例子。如果请求中有一个numDigits参数,则该值被传递给Bean的numDigits属性;numPrimes也类似。  JspPrimes.jsp

    20200321215032100.jpg
    jsp:getProperty
    jsp:getProperty动作提取指定Bean属性的值,转换成字符串,然后输出。
    jsp:getProperty有两个必需的属性,即:name,表示Bean的名字;property,表示要提取哪个属性的值。

    END!!!有什么意见可以提出来!
    长路漫漫,JAVA为伴!!!
    ————————————————
    版权声明:本文为CSDN博主「福尔摩东」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_43688587/article/details/105017469

label和span标签设置宽度width无效的解决办法

前端达人

如何用CSS使label标签等宽?

<div><label>密码</label><input type="password" /></div>
<div><label>确认密码</label><input type="password" /></div>
如何对齐呢?加空格的方法不好哦。(因为label中的字数不一样,所以页面显示效果不对齐)
问题原因及解决办法:

label默认为内联元素,元素前后没有换行符,并且不可以设置宽度。

如果要为label设置宽度,则需要改变label的display属性,使其变为一个块级元素。

方法如下:

1.增加inline-block属性值,将label标签变为行内块元素(css2.1新增)

     {display:inline-block;}

2.增加width属性,如将宽度设置为100px
    label{width:100px;display:inline-block;}

3.添加好后页面上所有的label标签会变为100pxv



JavaScript中的混淆器

随着 AJAX 和富界面技术的发展,Javascript 在 Web 应用上的重要性越来越高,Javascript 代码的复杂性、功能和技术含量也越来越高,对Javascript 代码保护的需要也越来越迫切。



压缩 compress: 去掉空格,换行,注释等,格式紧凑,节约存储空间。



混淆 obfuscate/garble:替换变量名或方法名,让js不容易看懂。也做到了压缩的效果。



加密 encrypt:一般用eval方法加密,效果与混淆相似。也做到了压缩的效果。



我们可以通过工具进行混淆,通过工具也是目前最好的方式。推荐一个很好的混淆工具: JSObfuscator By Unest


20200321102359879.png


————————————————

版权声明:本文为CSDN博主「刘亦枫」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/liuyifeng0000/article/details/105004732




"从客户端中检测到有潜在危险的 Request.Form 值"的解决方案汇总

seo达人

在一个asp.net 的项目中,前端通过ajax将富文本中的文字内容post到服务端的一个ashx中,在ashx中尝试读取参数值时,

结果报错:“从客户端中检测到有潜在危险的 Request.Form 值”

#事故分析
由于在asp.net中,Request提交时出现有html代码字符串时,程序系统会认为其具有潜在危险的值。会报出“从客户端 中检测到有潜在危险的Request.Form值”这样的Error。

而富文本中的内容是包含html代码的,所以...

#解决方案:
1、前端对富文本字符串进行encodeURI编码,服务端进行HttpUtility.UrlDecode解码操作;
前端代码:

var str = '<p><span style="color: #00B0F0;"><em><strong>我想留在你的身边,</strong></em></span><br/></p><p><span style="color: #7030A0;"><strong><span style="text-decoration: underline;">深情款款多么可怜;</span></strong></span></p>';
    $(function() {
        $.ajax({
            type: "post",
            url: "TestHandle.ashx",
            data: { Title: 'jack', Content: encodeURI(str) },
            success: function (data) {
                $("#div").html(data);
            }
        });
    });
后端代码:

    public void ProcessRequest(HttpContext context)
    {
        string str = context.Request["content"];
        string content = HttpUtility.UrlDecode(str);
        context.Response.ContentType = "text/plain";
        context.Response.Write(content);
    }
效果图:

2、前端不以form的方式提交,直接以json方式提交,服务端从request的body中读取数据,然后反序列化,得到信息;
前端代码:

    var str = '<p><span style="color: #00B0F0;"><em><strong>我想留在你的身边,</strong></em></span><br/></p><p><span style="color: #7030A0;"><strong><span style="text-decoration: underline;">深情款款多么可怜;</span></strong></span></p>';
    var temp = { Title: 'jack', Content: str };
    $.ajax({
        type: "post",
        url: "TestHandle.ashx",
        contentType:"application/json;charset=utf-8",
        data: JSON.stringify(temp),
        success: function (data) {
            $("#div").html(data);
        }
    });
后端代码:

    string bodyText;
    using (var bodyReader = new System.IO.StreamReader(context.Request.InputStream))
    {
        bodyText = bodyReader.ReadToEnd();
    }
    dynamic bodyObj = JsonConvert.DeserializeObject(bodyText);
 
    context.Response.ContentType = "text/plain";
    context.Response.Write(bodyObj.Content);
效果图:

#其他场景的解决方案:
1、aspx页面,当前页面进行form提交
打开当前.aspx页面,页头加上代码:validateRequest=”false”,如:

<%@ Page Language="C#" ValidateRequest="false" AutoEventWireup="false" CodeFile="default.aspx.cs" Inherits="default" %>
该方法不推荐,还有一种修改web.config配置文件的方法,强烈不推荐,就不写在这里了;

2、在ASP.NET MVC中的解决方案
1)、针对某个实体类的单个字段设置 [AllowHtml] ,这样提交的时候,系统就会放过该字段。

2)、前端代码:

    var str = '<p><span style="color: #00B0F0;"><em><strong>我想留在你的身边,</strong></em></span><br/></p><p><span style="color: #7030A0;"><strong><span style="text-decoration: underline;">深情款款多么可怜;</span></strong></span></p>';
    $(function () {
        $.ajax({
            type: "post",
            url: "Home/Test",
            data: { Title: 'jack', Content: str },
            success: function (data) {
                $("#div").html(data.ok);
            }
        });
    });
3)、后端代码:

    public class NewInfo
    {
        public string Title { get; set; }
        [AllowHtml]
        public string Content { get; set; }
    }
 #写在最后
 该文只是浅显的总结一下,其中涉及的xss方面,没有详细考虑,欢迎指正!

JavaScript中Array数组的some()函数的详解

seo达人

前言

开发中,经常会用到js的Array数组的各种迭代函数map(),filter(),some(),every(),forEach(),find() findIndex(),也是在ES6中新增一些遍历函数。同样是不是也是一道面试题,说说ES6新增的一些新特性????



✍开始正文some()函数



✍一、对some()函数的定义:



some():用于检测数组中的元素是否满足指定条件(函数提供);

some()方法会依次执行数组中的每一个元素:



如果有一个元素满足条件,则表达式返回true,剩余的元素不会再执行检测。

如果没有满足条件的元素,则返回false。

注意:



some()不会对空数组进行检测。

some() 不会改变原始数组。

✍二、浏览器支持

表格中的数字表示支持该方法的第一个浏览器的版本号。



✍三、语法



array.some(function(currentValue,index,arr),thisValue)

1

参数说明:



✍三、示例



<script>

var ages = [4, 12, 16, 20];



function checkAdult(age) {

    return age >= document.getElementById("ageToCheck").value;

}



function myFunction() {

    document.getElementById("demo").innerHTML = ages.some(checkAdult);

}

</script>


通过JavaScript制作table表格隔行变色

seo达人

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>隔行变色</title>

</head>

<body>

<table id="mytable" align="center" width="80%" border="1">

<tr bgcolor="#cccccc">

<td>aaa</td>

<td>aaa</td>

<td>aaa</td>

</tr>

<tr>

<td>bbb</td>

<td>bbb</td>

<td>bbb</td>

</tr>

<tr>

<td>ccc</td>

<td>ccc</td>

<td>ccc</td>

</tr>

</table>

<script type="text/javascript">

window.onload=function(){

//获取mytable中标签名为tr的字节点

mytable=document.getElementById("mytable");

trs=mytable.getElementsByTagName("tr");

len=trs.length;

flag=true;

for(i=0;i<len;i++){

if(flag){

//每隔一行设置背景色

var tr=document.getElementsByTagName("tr")[i].setAttribute("bgcolor","#cccccc");

flag=false;

}else{

flag=true;

}

}

}

</script>

</body>

</html>


js_判断浏览器内核与修改元素样式

前端达人

/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);



<script type="text/javascript">
var Sys = {};
var ua = navigator.userAgent.toLowerCase();
var s;
(s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] :
(s = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] :
(s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] :
(s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] :
(s = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0;
//以下进行测试
if (Sys.ie) document.write('IE: ' + Sys.ie);
if (Sys.firefox) document.write('Firefox: ' + Sys.firefox);
if (Sys.chrome) document.write('Chrome: ' + Sys.chrome);
if (Sys.opera) document.write('Opera: ' + Sys.opera);
if (Sys.safari) document.write('Safari: ' + Sys.safari);
</script>


PC端只有Chrome有Safari字段吗?为什么不需要判断其他浏览器?
其实360,QQ等浏览器的userAgent字段也会带有Safari字段,但是由于他们基于Chrome二次开发的,所有也会携带有Chrome字段。
所以「匹配规则:拥有Safari字段,并且没有Chrome字段」就可以了。


接下来是修改元素样式





<html>
<head>
    <style>
     #a{
        width:700px;
        height:300px;
        font-size:50px;
        color:red;
        background-color:grey;
        z-index:2;
        position:absolute;
        top:1300px;
        left:200px;
        display:none;
    } 
    </style>
</head>
<body>
    <div id="a"></div>
</body>
<script type="text/javascript">
    //假设想修改display为block
    function modify(){
        //1.原生Js法
        var a= document.getElementById("a");
        a.style.display="block";
        //2.用JQuery的css方法
        var a =$("#a");
        a.css("display","block");
        //3.用JQuery的attr方法
        var a =$("#a");
        a.attr("style","display:block");
    }
</script>
</html>


这样就可以根据不同浏览器写出不同的样式适配啦



JS中数据类型转换

seo达人

JS中数据类型转换

目前为止,我了解到的JavaScript中共有6种类型。通过typeof关键字可以查看类型名称。



数据的类型:

字符串:若值为字符串,则显示为String。字符串使用单引号或双引号括起来。在控制台显示为黑色。

数字:若值为数字,则显示为Number。在控制台显示为蓝色。

布尔值:若值为布尔值,则显示为Boolean。它的值只有”true”和”false”。

对象:若值为对象,则显示为Object。

未定义:若值未定义,也就是仅仅声明,但未进行赋值,则显示为Undefined。

空值:若值为指向不引用对象的指针,则显示为Null,它与Undefined不同,以后慢慢深入了解。



以下表格详细写出了各种情况下相互转换的结果,可作为辅助记忆。



转换为字符串 转换为数字 转换为布尔值 转换为对象

undefined “undefined” NaN false throw TypeError

null “null” 0 false throw TypeError

true “true” 1 new Boolean(“true”)

false “false” 0 new Boolean(“false”)

“” 0 false new String("")

“1.2” 1.2 true new String(“1.2”)

“1.2a” NaN true new String(“1.2a”)

“aaa” NaN true new String(“aaa”)

0 “0” false new Number(0)

1 “1” true new Number(1)

NaN “NaN” false new Number(NaN)

Infinity “Infinity” true new Number(Infinity)

[] “” 0 true

[9] “9” 9 true

[“a”“b”] “a,b” NaN true

在Js中,数据类型可以相互转换,转换的方式有两种,隐式转换和强制转换,首先来说一些隐式转换。在进行代码书写时,要经常提醒自己所使用的元素是什么数据类型,在进行某些操作后是否会导致数据类型的变化,原因就是Js会对数据进行类型的隐式转换。



隐式转换举例:

(+)加法运算的隐式转换:加号两边只要出先了字符串,就自动将两者均转化为字符串,使两个字符串发生“拼接”,最后生成的结果也是一个字符串;如果前后都不是字符串,则转化为数字类型进行计算。



(-、*、/、%)其他算数运算的隐式转换:前后都转化为数字类型进行计算。



(!)逻辑非的隐式转换:他会将他后面的变量或表达式转换为布尔值。



(<,>)比较运算符的转换:如果前后存在一个数字,会对另一个转化为数字进行比较;如果前后均为字符串,会依次比较对应字符的编码大小,老大比老大,老二比老二,依次进行。



(&&,||)逻辑运算符的转换:先将前后都转化为布尔值再进行判断,要记住的是,只有undefined,null,0,””,NaN会转化成为false,其他都是true。



(== 、===)这里作为补充说明,null与Undefined相等但不全等,NaN与任何都不相等。



强制转换的方式:

1.转化为字符串

String(里面写待转化的内容):没什么好解释的,就是强制将你所看到的转化为你所看到的。

toString(里面写目标数字是几进制),写法为:待转化内容.toString(目标内容是几进制)。括号内不写时默认为10。

toFixed(保留小数的位数),写法为待转化内容.toFixed(保留小数的位数),存在精度误差。



2.转化为数字

Number(),只有所转化内容在肉眼看到的全是数字,才会正常转化;false会转化为0,true会转化为1;null会转化为0;undefined会转化为NaN;其他情况均为NaN。

parseInt(待转化内容,待转化内容的进制方式),与toString互为逆运算,不写的话默认为10。如果待转化内容为字符串,若以数字开头,可以从开始转换到字符前为止变成数值。布尔值,undefined,null经过转化均为NaN。

ParseFloat(),与上面一致,不赘述。



3.转化为布尔值

书写方式为Boolean(),如果上面的隐式转换你有好好看,这里很得不需要再写了。


密码验证 : 密码强度验证

前端达人

密码强度验证

需求

首先我们需要知道需求是什么? 这很重要!



要知道 我们写的一切逻辑都是建立在需求之上



当输入框聚焦时提示密码要求



当密码符合要求时 隐藏提示 并给予反馈



密码等级低时 提示密码等级为低



密码等级一般时 提示密码等级为中



密码等级高时 提示密码等级为高



当密码不符合要求时 重新打开提示



思考如何构建函数
通过上面的需求 你能想到的函数时什么?你能想到的逻辑又是什么?

首先 提示的显示隐藏我们可以用事件绑定或者事件监听来做

其次 我们需要利用正则来判断密码等级

当密码等级为低时 显示红色

当密码等级为中时 显示黄色

当密码等级为高时 显示绿色

最后 根据密码等级来渲染页面 也就是反馈给用户的样式

建议 :

在这里 尽量把每个函数的功能区分好 构思好

不仅要让自己能看懂 还要让别人能看懂

这样的代码才是好的代码 可读性更好 可维护性更高


实现功能 实现需求

HTML结构

在提示盒子的内部写3个div 不同等级给予不同颜色不同数量的提示

 密码 : <input type="text" id="ipt">
    <p id="p">请输入6-20位的带有数字字母或者特殊符号的密码</p>
    <div class="box">
        <span></span>
        <div></div>
        <div></div>
        <div></div>
    </div>


点击查看原图



不管样式行为再怎么花里胡哨 也一定要先把结构里要出现的元素写出来



CSS样式

由于考虑到等级分为三种 所以给提示盒子分3中不同的class类名

每一个类名对应的子元素的样式也不同

到js部分我们只需要操作class类名就可以了

   <style>
        *{
            margin : 0 ;
            padding : 0 ;
        }
        //提示盒子
        .box{
            position : absolute;
            top : 2px;
            left : 200px;
        }
        .box div,
        .box span{
            margin-right : 5px;
            width : 20px;
            height : 20px;
            float : left;
        }
        //低等级
        .box.low :nth-child(2){
            background : red;
        }
        //中等级
        .box.middle div{
            background : yellow;
        }
        .box.middle :last-child{
            background: #fff;
        }
        //高等级
        .box.high div{
            background : green;
        }
        //提示文字默认隐藏
        p{
            display : none;
        }
    </style>



20200315203557273.png

JS行为

 <script>
        //获取需要操作的元素
        let ipt = document.getElementById('ipt');
        let p = document.getElementById('p');
        let div = document.getElementsByClassName('box')[0];
        var tip = false; //聚焦显示提示的开关
        //添加聚焦事件
        ipt.addEventListener('focus' , () => {
            //由于存在用户输入正确的密码失焦再操作的可能 所以需要验证开关
            if(!tip) {
                p.style.display = 'block';
            }
            //默认选中文字 提升用户体验
            ipt.select();
        })
        //添加输入时的事件
        ipt.addEventListener('input' , () => {
            //拿到用户输入的密码字符串
            let str = ipt.value;
            //当密码不符合要求时 要及时给予反馈 及时清除样式
            if(str.length < 6 ||str.length > 20 || /[^(\da-zA-Z\_\#\@\$\^\%\*\&\!\~\+\-)]/.test(str) || str === "") {
                p.style.display = 'block';
                removeClass(div);
                div.children[0].innerHTML = "";
                tip = true;
                //如果不符合要求 就没必要判断等级了 直接结束判断
                return false;
            }else{
                p.style.display = 'none';
            }
            //判断密码等级
            let res = level(str);
            //根据等级添加样式
            randerLevel(res);
        })
        //判断密码等级函数
        function level (str) {
            let level = 0;
            //当用户输入的字符串符合一定规则 让等级+1
            if(/\d+/.test(str)) {
                level ++;
            }
            if(/[a-zA-Z]+/.test(str)) {
                level ++;
            }
            if(/[\_\#\@\$\^\%\*\&\!\~\+\-]+/.test(str)) {
                level ++;
            }
            return level;
        }
        //添加样式函数
        function randerLevel (level) {
            //在添加样式前先清空样式
            removeClass(div);
            div.children[0].innerHTML = "";
            //根据等级添加对应的类名
            switch (level) {
                case 1 :
                    div.children[0].innerHTML = '低';
                    //元素存在不止一个类名 用 += 更好
                    div.className += ' low';
                    break;
                case 2 :
                    div.children[0].innerHTML = '中';
                    div.className += ' middle';
                    break;
                case 3 :
                    div.children[0].innerHTML = '高';
                    div.className += ' high';
                    break;
            }
        }
        //去等级类名函数
        function removeClass(ele){
            let reg = /low|middle|high/g;
            if(reg.test(ele.className)) {
                //不要忘记把值赋回去 replace返回的是新字符串
                ele.className = ele.className.replace(reg , "");
            }
        }
    </script>

当密码等级为低时 给予红色反馈

2020031520385174.png


  • 当密码等级为中时 给予黄色反馈
    20200315203928450.png
  • 当密码等级为高时 给予绿色反馈
    20200315203952860.png
  • 当密码长度太短或太长时 不给予颜色反馈 给予文字反馈
20200315204030964.png


————————————————
版权声明:本文为CSDN博主「豆浆不好喝」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45178648/article/details/104885417

日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档