首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

有关自定义View的学习知识点

在android中Rect和RextF都是用来创建一个矩形的, Rect的参数是 int型 , RectF的参数是float型,由此可以看出RectF比Rect的精确度更高。,他们都是通过四个坐标参数来确定矩形的区域。 RectF一共有四个构造方法: RectF()构造一个无参的矩形 RectF(float left,float top,float right,float bottom)构造一个指定了4个参数的矩形 RectF(Rect F r)根据指定的RectF对象来构造一个RectF对象(对象的左边坐标不变) RectF(Rect r)根据给定的Rect对象来构造一个RectF对象 RectF提供了很多方法,下面介绍几个方法: Public Boolean contain(RectF r);判断一个矩形是否在此矩形内,如果在这个矩形内或者和这个矩形等价则返回true, 同样类似的方法还有public Boolean contain(float left,float top,float right,float bottom)和public Boolean contain(float x,float y)。 Public void union(float x,float y)更新这个矩形,使它包含矩形自己和(x,y)这个点。 Rect和RecF的用法基本类似,只是参数为int类型,Rect(int left,int top,int right,int bottom),所取得的图形区域为 weight(right - left),height(bottom - top),在绘制的时候要注意这四个坐标之间的关系。 RectF四个参数具体是怎么确定矩形的

优秀的个人博客,低调大师

day18_文件的上传和下载学习笔记

一、文件的上传和下载 1、文件上传的原理分析 什么是文件上传? 要将客户端(浏览器)数据存储到服务器端,而不将数据直接存储到数据库中,而是要将数据存储到服务器所在的磁盘上,这就要使用文件上传。为什么使用文件上传? 通过文件上传,可以将浏览器端的数据直接保存到服务器端。不将数据保存到数据库中,而是保存到服务器磁盘上,这样减少了数据库服务器的压力,对数据的操作更加灵活。 1.1 文件上传的必要前提 a、提供form表单,method必须是post提交方式。 b、form表单必须设置为enctype="multipart/form-data"。 c、提供input type="file"类的上传输入域。 1.2 enctype属性 作用:告知服务器请求正文的MIME类型(文件类型)。(与请求消息头中:Content-Type作用是一致的) 可选值: application/x-www-form-urlencoded(默认) 请求消息正文:name=tom&photo=a.txt 服务器获取数据:String name = request.getParameter("name"); multipart/form-data 请求消息正文: 服务器获取数据:request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不再是字符内容,而是字节内容,所以失效,所以需要字节流的方式。 文件上传:解析请求正文的每部分的内容。 2、借助第三方的上传组件实现文件上传 2.1 fileupload概述 fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()。 使用步骤,导入commons-fileupload相关jar包 commons-fileupload.jar,核心包。 commons-io.jar,依赖包。 2.2 fileupload的核心类有 DiskFileItemFactory、ServletFileUpload、FileItem。 a、解析原理 2.3 fileupload简单应用 使用fileupload组件的步骤如下: 1. 创建工厂类DiskFileItemFactory对象 DiskFileItemFactory factory = new DiskFileItemFactory(); 2. 使用工厂创建解析器对象 ServletFileUpload fileUpload = new ServletFileUpload(factory); 3. 使用解析器来解析request对象 List< FileItem > list = fileUpload.parseRequest(request); FileItem对象对应一个表单项(表单字段)。可以是文件字段或普通字段。 FileItem接口的方法: boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,则说明是文件字段。 String getFieldName():获取字段名称,例如:< input type="text" name="username" />,返回的是username。 String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件。 String getName():获取文件字段的文件名称(如:a.txt)。 String getContentType():获取上传的文件的MIME类型,例如:text/plain、image/pjpeg。 int getSize():获取上传文件的大小。 InputStream getInputStream():获取上传文件对应的输入流。 void write(File file):把上传的文件保存到指定文件中。 void delete(); 3、文件上传时要考虑的几个问题(经验分享) a、保证服务器的安全 把保存上传文件的目录放在用户直接访问不到的地方。 b、避免文件被覆盖 让文件名唯一即可。 c、避免同一个文件夹中的文件过多 方案一:按照日期进行打散存储目录 方案二:用文件名的hashCode计算打散的存储目录:二级目录 d、限制文件的大小:web方式不适合上传大的文件 设置单个文件大小: ServletFileUpload.setFileSizeMax(字节); 设置总文件大小:(多文件上传时) ServletFileUpload.setSizeMax(字节); e、上传字段用户没有上传的问题 通过判断文件名是否为空即可。 f、临时文件的问题 DiskFileItemFactory: 作用:产生FileItem对象。 DiskFileItemFactory内部有一个缓存,缓存大小默认是10Kb。如果上传的文件超过10Kb,就用磁盘作为缓存。 存放缓存文件的目录在哪里?答:默认是系统的临时目录。 FileItem.delete(); FileItem.delete(); 如果自己用IO流实现的文件上传,则要在流关闭后,清理临时文件。 FileItem.write(File file); 把上传的文件保存到指定文件,该方式会自动删除临时文件,注意:实际操作不能够自动删除临时文件(即:使用 FileItem自带的方法上传文件)。 完整的示例代码如下: package com.itheima.upload;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.UnsupportedEncodingException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;import java.util.UUID;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileUploadBase;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;import org.apache.commons.io.FilenameUtils;public class UploadServlet2 extends HttpServlet {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// request.setCharacterEncoding("UTF-8"); // 解决服务器接收请求的编码问题,该方式的优先级不高,不好!// 要执行文件上传的操作// 首先判断表单是否支持文件上传。即:判断 enctype="multipart/form-data"boolean isMultipartContent = ServletFileUpload.isMultipartContent(request);if (!isMultipartContent) {throw new RuntimeException("your form is not multipart/form-data"); }// 创建一个DiskFileItemfactory工厂类对象 DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setRepository(new File("e:\\")); // 指定临时文件的存储目录// 使用工厂创建解析器ServletFileUpload核心对象 ServletFileUpload sfu = new ServletFileUpload(factory);// 解决上传文件表单项出现乱码问题 sfu.setHeaderEncoding("UTF-8");// 使用解析器来解析request对象 ,并得到一个表单项的List集合try {// 限制上传文件的大小// sfu.setFileSizeMax(1024 * 1024 * 3); // 表示3M大小的文件// sfu.setSizeMax(1024 * 1024 * 6); // 多个文件上传时 List<FileItem> fileItems = sfu.parseRequest(request);// 遍历表单项数据for (FileItem fileitem : fileItems) {if (fileitem.isFormField()) {// 文本表单项,普通文本字段(字符串) processFormField(fileitem); } else {// 文件表单项,文件字段(使用字节流读取) processUploadField(fileitem); } } } catch (FileUploadBase.FileSizeLimitExceededException e) {// throw new RuntimeException("文件过大,不能超过3M"); System.out.println("文件过大,不能超过3M"); // 自定义异常 } catch (FileUploadBase.SizeLimitExceededException e) { System.out.println("总文件大小不能超过6M"); // 自定义异常 } catch (FileUploadException e) { e.printStackTrace(); } }@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }// 文本表单项,普通文本字段(字符串)private void processFormField(FileItem fileitem) {try { String fieldname = fileitem.getFieldName(); // 获取字段名 String fieldvalue = fileitem.getString("UTF-8"); // 获取字段值,并解决上传普通文本表单出的乱码问题// 解决上传普通文本表单项出现的乱码问题// fieldvalue = new String(fieldvalue.getBytes("iso-8859-1"), "utf-8"); System.out.println(fieldname + "=" + fieldvalue); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }// 文件表单项,文件字段(使用字节流读取)private void processUploadField(FileItem fileitem) {try {// 得到文件输入流 InputStream is = fileitem.getInputStream();// 创建一个文件存盘的目录 String directoryRealPath = this.getServletContext().getRealPath("/WEB-INF/upload"); File storeDirectory = new File(directoryRealPath); // 既代表文件又代表目录if (!storeDirectory.exists()) { storeDirectory.mkdirs(); // 就创建一个指定的目录 }// 获取文件字段的文件名称 String filename = fileitem.getName(); // 文件项框中的值 F:\图片素材\小清新\43.jpg 或者 43.jpg// 处理文件名问题 F:\apache-tomcat-7.0.52\webapps\day18_00_upload\ upload\F:\图片素材\小清新\43.jpgif (filename != null) {// filename = filename.substring(filename.lastIndexOf(File.separator) + 1); filename = FilenameUtils.getName(filename); // 效果同上 }// 解决文件同名的问题 filename = UUID.randomUUID() + "_" + filename;// 法一:按日期打散(创建)目录// String childDirectory = makeChildDirectory(storeDirectory); // 2015-10-19// 法二:用文件名的hashCode计算打散的存储目录:即二级目录 String childDirectory = makeChildDirectory(storeDirectory, filename); // a/b// 在storeDirectory目录下,创建完整目录下的文件 File file = new File(storeDirectory, childDirectory + File.separator + filename); // 绝对目录/日期目录/文件名// 通过文件输出流将上传的文件保存到服务器的磁盘 FileOutputStream fos = new FileOutputStream(file);int len = 0;byte[] b = new byte[1024];while ((len = is.read(b)) != -1) { fos.write(b, 0, len); } fos.close(); is.close(); fileitem.delete(); // 如果自己用IO流实现的文件上传,则要在流关闭后,清除临时文件// 把上传的文件保存到指定文件(使用 FileItem自带的方法上传文件)// fileitem.write(new File(storeDirectory, childDirectory + File.separator + filename));// fileitem.delete(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }// 用文件名的hashCode计算打散的存储目录:二级目录private String makeChildDirectory(File storeDirectory, String filename) {int hashcode = filename.hashCode(); // 返回字符串转换的32位hashcode码 System.out.println(hashcode); String code = Integer.toHexString(hashcode); // 把hashcode码转换为16进制的字符 System.out.println(code); // 例如:abdsaf2131safsd String childDirectory = code.charAt(0) + File.separator + code.charAt(1); // 取前两位,作为二级目录,例如:a/b// 创建指定目录 File file = new File(storeDirectory, childDirectory);if (!file.exists()) { file.mkdirs(); }return childDirectory; }/* // 按日期打散目录 private String makeChildDirectory(File storeDirectory) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String dateDirectory = sdf.format(new Date()); // 创建指定目录 File file = new File(storeDirectory, dateDirectory); if (!file.exists()) { file.mkdirs(); } return dateDirectory; }*/} 一次上传一个文件的form表单代码upload.jsp <%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><form enctype="multipart/form-data"action="${pageContext.request.contextPath }/servlet/uploadServlet2"method="post"><input type="text" name="name" /><br /> <input type="file" name="photo" /><br /> <input type="submit" value="上传" /><br /></form></body></html> 一次上传两个文件的form表单代码upload2.jsp <%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><form enctype="multipart/form-data"action="${pageContext.request.contextPath }/servlet/uploadServlet2"method="post"><input type="text" name="name" /><br /> <input type="file" name="photo" /><br /> <input type="file" name="photo" /><br /> <input type="submit" value="上传" /><br /></form></body></html> 动态添加上传按钮上传多个文件upload3.jsp <%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><script type="text/javascript">function addFile() {// 得到div容器var div1 = document.getElementById("div1"); div1.innerHTML += "<div><input type='file' name='photo'/><input type='button' value='删除' onclick='delFile(this)'/></div>"; }function delFile(input) {// 使用input对象的爷爷删除他的爸爸 input.parentNode.parentNode.removeChild(input.parentNode); }</script><body><form enctype="multipart/form-data"action="${pageContext.request.contextPath }/servlet/uploadServlet2"method="post"><input type="text" name="name" /><br /><div id="div1"><div><input type="file" name="photo"/><input type="button" value="添加" onclick="addFile()"/><br /></div></div><input type="submit" value="上传" /><br /></form></body></html> 4、文件的下载 注意:在web开发中,不适合大的数据下载,通过浏览器进行大的数据下载,不合适,此时需要借助下载软件进行下载,比如:迅雷、电驴、百度网盘等等。 web开发中,文件下载的应用场景是:从数据库表里面查找数据,动态的生成所需的文件。 文件下载的示例代码如下: package com.itheima.servlet;import java.io.IOException;import java.io.PrintWriter;import java.net.URLEncoder;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class DownloadServlet extends HttpServlet {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 设置一个要下载的文件 String filename = "销售榜单.csv"; // csv文件可以用excle打开// 设置文件名的编码if (request.getHeader("user-agent").toLowerCase().contains("msie")) { filename = URLEncoder.encode(filename, "UTF-8"); // 将不安全的文件名改为UTF-8格式 } else { filename = new String(filename.getBytes("UTF-8"), "iso-8859-1"); // 火狐浏览器 }// 告知浏览器要下载的文件 response.setHeader("content-disposition", "attachment;filename=" + filename);// response.setHeader("content-type", "image/jpeg"); response.setContentType(this.getServletContext().getMimeType(filename)); // 告知浏览器根据文件名的后缀自动获得文件类型 response.setCharacterEncoding("UTF-8"); // 设置服务器使用什么编码,去向外输出下面文件输出流的内容// 创建一个文件输出流 PrintWriter out = response.getWriter(); out.write("电视机, 20\n"); // 以后连接数据库即可 out.write("洗衣机, 10\n"); out.write("冰箱, 8\n"); }@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }} 重构添加图书信息的示例代码: package com.itheima.web.servlet;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;import org.apache.commons.io.FilenameUtils;import com.itheima.domain.Book;import com.itheima.service.BookServiceImpl;import com.itheima.util.UUIDUtil;public class AddBookServlet extends HttpServlet {@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 创建一个DiskFileItemFactory工厂 DiskFileItemFactory factory = new DiskFileItemFactory();// 创建一个ServletFileUpload对象 ServletFileUpload sfu = new ServletFileUpload(factory);// 解决上传文件的乱码 sfu.setHeaderEncoding("UTF-8"); // 解析request对象,返回所有表单项 List<FileItem> fileItems = new ArrayList<FileItem>(0);// 用于封装普通表单项的数据 Map<String, String[]> map = new HashMap<String, String[]>();try { fileItems = sfu.parseRequest(request);// 迭代遍历fileItems表单项for (FileItem fileItem : fileItems) {if (fileItem.isFormField()) {// 普通表单项 String name = fileItem.getFieldName(); // 得到字段名 String value = fileItem.getString("UTF-8"); // 得到字段值 map.put(name, new String[] { value }); // 向map中赋值 } else {// 文件表单项 InputStream inputStream = fileItem.getInputStream(); String filename = fileItem.getName(); // 得到上传的文件名 String extension = FilenameUtils.getExtension(filename);if (!("jsp".equals(extension) || "exe".equals(extension))) { // 上传的文件不能是jsp、exe// 创建一个文件存盘的目录 File storeDirectory = new File(this.getServletContext().getRealPath("/upload"));if (!storeDirectory.exists()) { storeDirectory.mkdirs(); // 如果该目录不存在,就创建 }// 处理文件名问题if (filename != null) { filename = FilenameUtils.getName(filename); }// 目录打散 String childDirectory = makeChildDirectory(storeDirectory, filename); // a/b// 把上传的文件保存到指定文件(使用 FileItem自带的方法上传文件) filename = childDirectory + File.separator + filename; fileItem.write(new File(storeDirectory, filename)); fileItem.delete(); // 删除临时文件 } map.put(fileItem.getFieldName(), new String[] { filename }); // 将图片表单项的name和value保存到map中 } } Book book = new Book(); BeanUtils.populate(book, map); book.setId(UUIDUtil.getUUID()); // 设置图书编号// 调用业务逻辑 BookServiceImpl bs = new BookServiceImpl(); bs.addBook(book);// 分发转向// 不写/代表相对路径,相对于本类的路径 request.getRequestDispatcher("bookListServlet").forward(request, response); } catch (FileUploadException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }// request.setCharacterEncoding("UTF-8"); // 获取表单数据 // Book book = new Book();// try {// BeanUtils.populate(book, request.getParameterMap());// book.setId(UUIDUtil.getUUID()); // 手动生成一个随机ID// } catch (Exception e) {// e.printStackTrace();// } // // // 调用业务逻辑 // BookServiceImpl bs = newBookServiceImpl();// bs.addBook(book);//// // 分发转向 // // 不写/代表相对路径,相对于本类的路径// request.getRequestDispatcher("bookListServlet").forward(request, response);@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }// 目录打散private String makeChildDirectory(File storeDirectory, String filename) {int hashcode = filename.hashCode(); // 返回字符转换的32位hashcode码 System.out.println(hashcode); String code = Integer.toHexString(hashcode); // 把hashcode转换为16进制的字符 System.out.println(code); // abdsaf2131safsd String childDirectory = code.charAt(0) + File.separator + code.charAt(1); // a/b// 创建指定目录 File file = new File(storeDirectory, childDirectory);if (!file.exists()) { file.mkdirs(); }return childDirectory; }} product_list.jsp <div class="divbookpic"><p><a href="#"><img src="${pageContext.request.contextPath}/upload/${b.img_url}" width="115" height="129" border="0" /> </a></p></div> 我的GitHub地址: https://github.com/heizemingjun 我的博客园地址: http://www.cnblogs.com/chenmingjun 我的蚂蚁笔记博客地址: http://blog.leanote.com/chenmingjun Copyright ©2018 黑泽明军 【转载文章务必保留出处和署名,谢谢!】

优秀的个人博客,低调大师

JavaScript高级程序设计学习(六)之设计模式

每种编程语言都有其自己的设计模式。不禁让人疑惑设计模式是用来做什么?有什么用? 简单的说,设计模式是为了让代码更简洁,更优雅,更完美。 同时设计模式也会让软件的性能更好,同时也会让程序员们更轻松。设计模式可谓是编程界的“葵花宝典”或“辟邪剑法”。如果一旦练成,必可在编程界中来去自如,游刃有余。 下面进入正题 (1)工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程(本书后 面还将讨论其他设计模式及其在 JavaScript中的实现)。考虑到在 ECMAScript中无法创建类,开发人员 就发明了一种函数,用函数来封装以特定接口创建对象的细节。 <html> <meta charset="utf-8"> <head> <script> function createPerson(name,age,job){ var o = new Object(); o.name=name; o.age=age; o.job=job; o.sayName=function(){ alert(this.name); }; return o; } var person1 = createPerson("a",20,"java"); var person2 = createPerson("b",20,"c++"); alert(person1.name); alert(person2.name); </script> </head> <body> </body> </html> 工厂模式,和Java的工厂模式差异不大,就是为了批量生产对象,上述函数我只需写一遍,我就能通过调用函数源源不断的进行复用传参。 简单的说工厂模式就是为了提高函数复用率,写一遍的东西我不要写好几遍就可以调用。 函数 createPerson()能够根据接受的参数来构建一个包含所有必要信息的 Person 对象。可以无 数次地调用这个函数,而每次它都会返回一个包含三个属性一个方法的对象。工厂模式虽然解决了创建 多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。 任何模式都有其局限性,所以诞生了一个构造函数模式。 (2)构造函数模式 构造函数与其他函数的唯一区别,就在于调用它们的方式不同。不过,构造函数毕竟也是函数,不存在定义构造函数的特殊语法。任何函数,只要通过 new 操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过 new 操作符来调用,那它跟普通函数也不会有什么两样。例如,前面例子中定义 的 Person()函数可以通过下列任何一种方式来调用。 <html> <meta charset="utf-8"> <head> <script> function createPerson(name,age,job){ var o = new Object(); o.name=name; o.age=age; o.job=job; o.sayName=function(){ alert(this.name); }; return o; } var person = new Person("zs",20,"java"); person.sayName(); Person("ls",20,"c++"); window.sayName(); </script> </head> <body> </body> </html> 构造函数模式虽然好用,但也并非没有缺点。使用构造函数的主要问题,就是每个方法都要在每个 实例上重新创建一遍。在前面的例子中,person1 和 person2 都有一个名为 sayName()的方法,但那 两个方法不是同一个 Function 的实例。不要忘了——ECMAScript中的函数是对象,因此每定义一个 函数,也就是实例化了一个对象 (3)原型模式 我们创建的每个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象, 而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。如果按照字面意思来理解,那 么 prototype 就是通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处是可以 让所有对象实例共享它所包含的属性和方法。换句话说,不必在构造函数中定义对象实例的信息,而是 可以将这些信息直接添加到原型对象中。 a.理解原型模型 无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个 constructor (构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。就拿前面的例子来说, Person.prototype. constructor 指向 Person。而通过这个构造函数,我们还可继续为原型对象 添加其他属性和方法。 创建了自定义的构造函数之后,其原型对象默认只会取得 constructor 属性;至于其他方法,则 都是从 Object 继承而来的。当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部 属性),指向构造函数的原型对象。ECMA-262第 5版中管这个指针叫[[Prototype]]。虽然在脚本中 没有标准的方式访问[[Prototype]],但 Firefox、Safari 和 Chrome 在每个对象上都支持一个属性 __proto__;而在其他实现中,这个属性对脚本则是完全不可见的。不过,要明确的真正重要的一点就 是,这个连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。 b.原型与 in 操作符 有两种方式使用 in 操作符:单独使用和在 for-in 循环中使用。在单独使用时,in 操作符会在通 过对象能够访问给定属性时返回 true,无论该属性存在于实例中还是原型中。 <html> <meta charset="utf-8"> <head> <script> function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); alert(person1.hasOwnProperty("name")); //false alert("name" in person1); //true person1.name = "Greg"; alert(person1.name); //"Greg" ——来自实例 alert(person1.hasOwnProperty("name")); //true alert("name" in person1); //true alert(person2.name); //"Nicholas" ——来自原型 alert(person2.hasOwnProperty("name")); //false alert("name" in person2); //true delete person1.name; alert(person1.name); //"Nicholas" ——来自原型 alert(person1.hasOwnProperty("name")); //false alert("name" in person1); //true </script> </head> <body> </body> </html> 在以上代码执行的整个过程中,name 属性要么是直接在对象上访问到的,要么是通过原型访问到 的。因此,调用"name" in person1 始终都返回 true,无论该属性存在于实例中还是存在于原型中。 同时使用 hasOwnProperty()方法和 in 操作符,就可以确定该属性到底是存在于对象中,还是存在于原型中。 由于 in 操作符只要通过对象能够访问到属性就返回 true,hasOwnProperty()只在属性存在于 实例中时才返回 true,因此只要 in 操作符返回 true 而 hasOwnProperty()返回 false,就可以确 定属性是原型中的属性。 c.更简单的原型语法 <html> <meta charset="utf-8"> <head> <script> function Person(){ } Person.prototype = { name : "Nicholas", age : 29, job: "Software Engineer", sayName : function () { alert(this.name); } }; </script> </head> <body> </body> </html> d.原型的动态性 由于在原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能够立即从实例上 反映出来——即使是先创建了实例后修改原型也照样如此。 var friend = new Person(); Person.prototype.sayHi = function(){ alert("hi"); }; friend.sayHi(); //"hi"(没有问题!) 以上代码先创建了 Person 的一个实例,并将其保存在 person 中。然后,下一条语句在 Person. prototype 中添加了一个方法 sayHi()。即使 person 实例是在添加新方法之前创建的,但它仍然可 以访问这个新方法。其原因可以归结为实例与原型之间的松散连接关系。当我们调用 person.sayHi() 时,首先会在实例中搜索名为 sayHi 的属性,在没找到的情况下,会继续搜索原型。因为实例与原型 之间的连接只不过是一个指针,而非一个副本,因此就可以在原型中找到新的 sayHi 属性并返回保存 在那里的函数。 尽管可以随时为原型添加属性和方法,并且修改能够立即在所有对象实例中反映出来,但如果是重 写整个原型对象,那么情况就不一样了。我们知道,调用构造函数时会为实例添加一个指向初原型的 [[Prototype]]指针,而把原型修改为另外一个对象就等于切断了构造函数与初原型之间的联系。 请记住:实例中的指针仅指向原型,而不指向构造函数。 例如: function Person(){ } var friend = new Person(); Person.prototype = { constructor: Person, name : "Nicholas", age : 29, job : "Software Engineer", sayName : function () { alert(this.name); } }; friend.sayName(); //error 看图: e.原型对象问题 原型模式也不是没有缺点。首先,它省略了为构造函数传递初始化参数这一环节,结果所有实例在 默认情况下都将取得相同的属性值。虽然这会在某种程度上带来一些不方便,但还不是原型的大问题。 原型模式的大问题是由其共享的本性所导致的。 原型中所有属性是被很多实例共享的,这种共享对于函数非常合适。对于那些包含基本值的属性倒 也说得过去,毕竟(如前面的例子所示),通过在实例上添加一个同名属性,可以隐藏原型中的对应属 性。然而,对于包含引用类型值的属性来说,问题就比较突出了. <html> <meta charset="utf-8"> <head> <script> function Person(){ } Person.prototype = { constructor: Person, name : "Nicholas", age : 29, job : "Software Engineer", friends : ["Shelby", "Court"], sayName : function () { alert(this.name); } }; var person1 = new Person(); var person2 = new Person(); person1.friends.push("Van"); alert(person1.friends); //"Shelby,Court,Van" alert(person2.friends); //"Shelby,Court,Van" alert(person1.friends === person2.friends); //true </script> </head> <body> </body> </html> 在此,Person.prototype 对象有一个名为 friends 的属性,该属性包含一个字符串数组。然后, 创建了 Person 的两个实例。接着,修改了 person1.friends 引用的数组,向数组中添加了一个字符 串。由于 friends 数组存在于 Person.prototype 而非 person1 中,所以刚刚提到的修改也会通过 person2.friends(与 person1.friends 指向同一个数组)反映出来。假如我们的初衷就是像这样 在所有实例中共享一个数组,那么对这个结果我没有话可说。可是,实例一般都是要有属于自己的全部 属性的。而这个问题正是我们很少看到有人单独使用原型模式的原因所在。 (4)组合使用构造函数模式和原型模式 创建自定义类型的常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实 例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本, 但同时又共享着对方法的引用,大限度地节省了内存。另外,这种混成模式还支持向构造函数传递参 数;可谓是集两种模式之长。 <html> <meta charset="utf-8"> <head> <script> function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"]; } Person.prototype = { constructor : Person, sayName : function(){ alert(this.name); } } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1.friends.push("Van"); alert(person1.friends); //"Shelby,Count,Van" alert(person2.friends); //"Shelby,Count" alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true </script> </head> <body> </body> </html> 在这个例子中,实例属性都是在构造函数中定义的,而由所有实例共享的属性 constructor 和方 法 sayName()则是在原型中定义的。而修改了 person1.friends(向其中添加一个新字符串),并不 会影响到 person2.friends,因为它们分别引用了不同的数组。 这种构造函数与原型混成的模式,是目前在 ECMAScript中使用广泛、认同度高的一种创建自 定义类型的方法。可以说,这是用来定义引用类型的一种默认模式。 (5)动态原型模式 有其他 OO语言经验的开发人员在看到独立的构造函数和原型时,很可能会感到非常困惑。动态原 型模式正是致力于解决这个问题的一个方案,它把所有信息都封装在了构造函数中,而通过在构造函数 中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的优点。换句话说,可以通过 检查某个应该存在的方法是否有效,来决定是否需要初始化原型。 示例如下: <html> <meta charset="utf-8"> <head> <script> function Person(name, age, job){ //属性 this.name = name; this.age = age; this.job = job; //------ if (typeof this.sayName != "function"){ Person.prototype.sayName = function(){ alert(this.name); }; } } //------ var friend = new Person("Nicholas", 29, "Software Engineer"); friend.sayName(); </script> </head> <body> </body> </html> 注意构造函数代码中//------部分。这里只在 sayName()方法不存在的情况下,才会将它添加到原 型中。这段代码只会在初次调用构造函数时才会执行。此后,原型已经完成初始化,不需要再做什么修 改了。不过要记住,这里对原型所做的修改,能够立即在所有实例中得到反映。因此,这种方法确实可 以说非常完美。其中,if 语句检查的可以是初始化之后应该存在的任何属性或方法——不必用一大堆 if 语句检查每个属性和每个方法;只要检查其中一个即可。对于采用这种模式创建的对象,还可以使 用 instanceof 操作符确定它的类型。 (6)寄生构造函数模式 通常,在前述的几种模式都不适用的情况下,可以使用寄生(parasitic)构造函数模式。这种模式 的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象;但 从表面上看,这个函数又很像是典型的构造函数。 <html> <meta charset="utf-8"> <head> <script> function Person(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var friend = new Person("Nicholas", 29, "Software Engineer"); friend.sayName(); //"Nicholas" </script> </head> <body> </body> </html> 在这个例子中,Person 函数创建了一个新对象,并以相应的属性和方法初始化该对象,然后又返 回了这个对象。除了使用 new 操作符并把使用的包装函数叫做构造函数之外,这个模式跟工厂模式其实 是一模一样的。构造函数在不返回值的情况下,默认会返回新对象实例。 而通过在构造函数的末尾添加一个 return 语句,可以重写调用构造函数时返回的值。 这个模式可以在特殊的情况下用来为对象创建构造函数。假设我们想创建一个具有额外方法的特殊 数组。由于不能直接修改 Array 构造函数,因此可以使用这个模式。 示例: <html> <meta charset="utf-8"> <head> <script> function SpecialArray(){ //创建数组 var values = new Array(); //添加值 values.push.apply(values, arguments); //添加方法 values.toPipedString = function(){ return this.join("|"); }; //返回数组 return values; } var colors = new SpecialArray("red", "blue", "green"); alert(colors.toPipedString()); //"red|blue|green" </script> </head> <body> </body> </html> 在这个例子中,我们创建了一个名叫 SpecialArray 的构造函数。在这个函数内部,首先创建了 一个数组,然后 push()方法(用构造函数接收到的所有参数)初始化了数组的值。随后,又给数组实 例添加了一个 toPipedString()方法,该方法返回以竖线分割的数组值。后,将数组以函数值的形 式返回。接着,我们调用了 SpecialArray 构造函数,向其中传入了用于初始化数组的值,此后又调 用了 toPipedString()方法。 关于寄生构造函数模式,有一点需要说明:首先,返回的对象与构造函数或者与构造函数的原型属 性之间没有关系;也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。为此, 不能依赖 instanceof 操作符来确定对象类型。由于存在上述问题,我们建议在可以使用其他模式的情 况下,不要使用这种模式。 (7)稳妥构造函数模式 道格拉斯·克罗克福德(Douglas Crockford)发明了 JavaScript中的稳妥对象(durable objects)这 个概念。所谓稳妥对象,指的是没有公共属性,而且其方法也不引用 this 的对象。稳妥对象适合在 一些安全的环境中(这些环境中会禁止使用 this 和 new),或者在防止数据被其他应用程序(如 Mashup 程序)改动时使用。稳妥构造函数遵循与寄生构造函数类似的模式,但有两点不同:一是新创建对象的 实例方法不引用 this;二是不使用 new 操作符调用构造函数。按照稳妥构造函数的要求,可以将前面 的 Person 构造函数重写如下 <html> <meta charset="utf-8"> <head> <script> function Person(name, age, job){ //创建要返回的对象 var o = new Object(); //可以在这里定义私有变量和函数 //添加方法 o.sayName = function(){ alert(name); }; //返回对象 return o; } </script> </head> <body> </body> </html> 注意,在以这种模式创建的对象中,除了使用 sayName()方法之外,没有其他办法访问 name 的值。 可以像下面使用稳妥的 Person 构造函数。 var friend = Person("Nicholas", 29, "Software Engineer"); friend.sayName(); //"Nicholas" 这样,变量 friend 中保存的是一个稳妥对象,而除了调用 sayName()方法外,没有别的方式可 以访问其数据成员。即使有其他代码会给这个对象添加方法或数据成员,但也不可能有别的办法访问传 入到构造函数中的原始数据。稳妥构造函数模式提供的这种安全性,使得它非常适合在某些安全执行环 境——例如,ADsafe(www.adsafe.org)和 Caja(http://code.google.com/p/google-caja/)提供的环境—— 下使用。 注意: 与寄生构造函数模式类似,使用稳妥构造函数模式创建的对象与构造函数之间也 没有什么关系,因此 instanceof 操作符对这种对象也没有意义。 js的工厂模式,构造函数模式,原型模式,组合使用构造函数合原型模式,动态原型模式,寄生构造函数模式,稳妥构造函数模式等 大家有没有从中发现,js的设计模式基本围绕着构造和原型这两个主要点。 该篇只是对js的设计模式作出相应的讲解和知识普及,不熟悉该概念的可以参考此文,大家可以将上述例子,自己动手敲着看,哪怕有经验的Java开发或者js,一起敲敲吧,保证有不一样的体会。

优秀的个人博客,低调大师

深度学习中的正则化技术(附Python代码)

数据科学家面临的常见问题之一是如何避免过拟合。你是否碰到过这样一种情况:你的模型在训练集上表现异常好,却无法预测测试数据。或者在一个竞赛中你排在public leaderboard的顶端,但是在最终排名中却落后了几百名?那么这篇文章就是为你而准备的! (译者注: 在kaggle这样的数据竞赛中, public leaderboard排名是根据一部分测试集来计算的,用于给选手提供及时的反馈和动态展示比赛的进行情况;而private leaderboard是根据测试集的剩余部分计算而来,用于计算选手的最终得分和排名。 通常我们可以把public LB理解为在验证集上的得分,private LB为真正未知数据集上的得分,这样做的目的是提醒参赛者,我们建模的目标是获取一个泛化能力好的模型) 避免过拟合可以提高我们模型的性能。 目录 1. 什么是正

优秀的个人博客,低调大师

《第一本Docker书》(学习笔记一)

1、简介、安装、入门、镜像与仓库、构建服务、fig配置docker、使用docker api 2 docker核心组件:docker客户端和服务器、docker镜像、registry、docker容器 3 docker架构: docker不支持32位 linux3.8以上内核 内核必须支持cgroup和命名空间功能 1、uname -a 检查安装device-mapper modprobe dm_mod yum install -y docker 启动:dockerd & 获取docker信息:docker info 搜索容器:docker search centos 容器安装: docker run -i -t centos /bin/bash #i开启标准化输入 t开启tty docker run -i -t docker.io/centos /bin/bash 查看正在运行的容器:docker ps 查看所有容器:docker ps -a 安装带名字的容器: docker run --name centostest -i -t centos /bin/bash 删除容器: docker rm wonderful_blackwell 启动容器:docker start centostest 付着到容器:docker attach centostest 创建守护进程容器:docker run --name centos1 -d centos /bin/sh 查看日志:docker logs centostest docker logs --tail 10 -t centostest #获取最后10行日志,带时间 查看容器内的进程:docker top centostest 启动交互式进程: docker exec -t -i centostest /bin/bash 在容器内运行一个新的后台进程:docker exec -d centostest touch /xxx 重启容器:docker run --restart=always --name centostest -d centos /bin/sh --restart=on-failure --restart=on-failure:5 #最多重启5次 获得容器的详细信息:docker inspect centostest docker镜像: docker images 列出镜像 docker pull centos:laste 提交自己创建的镜像: docker commit -m="xxxx" --author="xxx" idxjljldkjf name/name:biaoqian 查看镜像的每一层: docker history centostest 指定端口映射: docker run -d -p 80:80 --name mynginx xxx/xxx docker run -d -P --name mynginx xxx/xxxx #公开所有端口 CMD ["/bin/bash","-l"] 运行时覆盖工作目录:docker run -ti -w /var/log xxx pwd USER nginx USER www:www 添加卷: VOLUME ["/opt/project","/data"] ADD有解压,COPY没有解压 docker push xxxxx/xxxx docker rmi xx/xx 运行自己的registry docker run -p 5000:5000 registry 传容器到自己的镜像: docker tag xxx docker.image.com:5000/xxx/xxx docker push docker.image.com:5000/xx/xxx docker run -t -i docker.image.com:5000/xxx/xx

优秀的个人博客,低调大师

jQuery学习笔记--效果,操作html元素,遍历DOM树

参考W3school: http://www.w3school.com.cn/jquery/jquery_hide_show.asp jQuery效果: 隐藏: 基础语句: $(selector).hide(speed,callback); 可选的 speed 参数规定隐藏/显示的速度,可以取以下值:”slow”、”fast” 或毫秒。 可选的 callback 参数是隐藏或显示完成后所执行的函数名称。 实现:单击p标签的文字 文字消失 <script> $(document).ready(function(){ $("p").click(function(){ $(this).hide(); }); }); </script> 实现:单击button按钮 文字在2秒内消失 <script type="text/javascript"> $(document).ready(function(){ $("button").click(function(){ $("p").hide(2000); }); }); </script> 实现:单击按钮 包含按钮的div缓慢隐藏 <!DOCTYPE html> <html> <head> <script src="/jquery/jquery-1.11.1.min.js"></script> <script type="text/javascript"> $(document).ready(function(){ $(".ex .hide").click(function(){ $(this).parents(".ex").hide("slow"); }); }); </script> <style type="text/css"> div.ex { background-color:#e5eecc; padding:7px; border:solid 1px #c3c3c3; } </style> </head> <body> <div class="ex"> <button class="hide" type="button">隐藏</button> <p>大家好<br /> 我是小莫<br /> 哈哈</p> </div> </body> </html> 注意: parents(“.ex”)父亲节点中class为ex的元素 div.ex表示 又是div又是class为ex的元素 div .ex则表示 div中 class为ex的元素 区别 中间空格 而#ex则表示id为ex的元素 $(“.ex .hide”)表示class为ex元素中的class为hide的元素 hide(“slow”)是缓慢消失的意思 显示: 基础语句: $(selector).show(speed,callback); 可选的 speed 参数规定隐藏/显示的速度,可以取以下值:”slow”、”fast” 或毫秒。 可选的 callback 参数是隐藏或显示完成后所执行的函数名称。 实现:单击id为show的元素时候p文本文件显示 <script type="text/javascript"> $(document).ready(function(){ $("#show").click(function(){ $("p").show(); }); }); </script> 那有没有方法实现hide和show转换的呢? 有,还真有 那就是toggle()函数: 显示被隐藏的元素,并隐藏已显示的元素: 语法: $(selector).toggle(speed,callback); 可选的 speed 参数规定隐藏/显示的速度,可以取以下值:”slow”、”fast” 或毫秒。 可选的 callback 参数是 toggle() 方法完成后所执行的函数名称。 <script type="text/javascript"> $(document).ready(function(){ $("button").click(function(){ $("p").toggle(); }); }); </script> 淡入淡出: 淡入: 实现:单击按钮 id为div1的淡入 id为div2缓慢淡入 id为div3 3秒内淡入 前提三个div中style:display:none fadeIn() <script> $(document).ready(function(){ $("button").click(function(){ $("#div1").fadeIn(); $("#div2").fadeIn("slow"); $("#div3").fadeIn(3000); }); }); </script> 淡出: fadeOut()类似fadeIn() <script type="text/javascript"> $(document).ready(function(){ $("button").click(function(){ $("#div1").fadeOut(); $("#div2").fadeOut("slow"); $("#div3").fadeOut(3000); }); }); </script> 转换淡入淡出: fadeToggle()类似于上文的toggle() <script> $(document).ready(function(){ $("button").click(function(){ $("#div1").fadeToggle(); $("#div2").fadeToggle("slow"); $("#div3").fadeToggle(3000); }); }); </script> 可以指定淡出的透明度: fadeTo(速度,透明度); <script> $(document).ready(function(){ $("button").click(function(){ $("#div1").fadeTo("slow",0.1); $("#div2").fadeTo("slow",0.4); $("#div3").fadeTo("slow",0.7); }); }); </script> 总结: 通过 jQuery,您可以实现元素的淡入淡出效果。 jQuery 拥有下面四种 fade 方法: fadeIn() 淡入 fadeOut() 淡出 fadeToggle() 转换淡入淡出 fadeTo() 指定淡出透明度 jQuery fadeToggle() 方法可以在 fadeIn() 与 fadeOut() 方法之间进行切换。 如果元素已淡出,则 fadeToggle() 会向元素添加淡入效果。 如果元素已淡入,则 fadeToggle() 会向元素添加淡出效果。 语法: $(selector).fadeIn(speed,callback); $(selector).fadeOut(speed,callback); $(selector).fadeToggle(speed,callback); 可选的 speed 参数规定效果的时长。它可以取以下值:”slow”、”fast” 或毫秒。 可选的 callback 参数是 fading 完成后所执行的函数名称。 fadeTo有点不同: $(selector).fadeTo(speed,opacity,callback); fadeTo() 方法中必需的 opacity 参数将淡入淡出效果设置为给定的不透明度(值介于 0 与 1 之间)。 滑动: jQuery 拥有以下滑动方法: slideDown() slideUp() slideToggle() slideDown() 向下滑动显示: div.panel { height:120px; display:none; } <script type="text/javascript"> $(document).ready(function(){ $(".flip").click(function(){ $(".panel").slideDown("slow"); }); }); </script> slideUp() 向上滑动隐藏 div.panel { height:120px; } <script type="text/javascript"> $(document).ready(function(){ $(".flip").click(function(){ $(".panel").slideUp("slow"); }); }); </script> 转换滑动方向也相当于 转换显示和隐藏 slideToggle() 如果元素向下滑动,则 slideToggle() 可向上滑动它们。 如果元素向上滑动,则 slideToggle() 可向下滑动它们。 div.panel { height:120px; display:none; } <script type="text/javascript"> $(document).ready(function(){ $(".flip").click(function(){ $(".panel").slideToggle("slow"); }); }); </script> 语法: $(selector).slideDown(speed,callback); (selector).slideUp(speed,callback);(selector).slideUp(speed,callback);(selector).slideToggle(speed,callback); 可选的 speed 参数规定效果的时长。它可以取以下值:”slow”、”fast” 或毫秒。 可选的 callback 参数是滑动完成后所执行的函数名称。 动画: animate() 方法用于创建自定义动画 语法: $(selector).animate({params},speed,callback); 必需的 params 参数定义形成动画的 CSS 属性。 可选的 speed 参数规定效果的时长。它可以取以下值:”slow”、”fast” 或毫秒。 可选的 callback 参数是动画完成后所执行的函数名称。 单击按钮 div元素移动到离左端100px的地方 <script> $(document).ready(function(){ $("button").click(function(){ $("div").animate({left:'100px'}); }); }); </script> <div style="background:#98bf21;height:100px;width:100px;position:absolute;"> 也可以操作多个属性: {params}中有多个属性 里面是最终的状态 举个栗子: 离左端250px 透明度50% 高度150px 宽150px <script> $(document).ready(function(){ $("button").click(function(){ $("div").animate({ left:'250px', opacity:'0.5', height:'150px', width:'150px' }); }); }); </script> 可以使用相对值: <script> $(document).ready(function(){ $("button").click(function(){ $("div").animate({ left:'250px', height:'+=150px', width:'+=150px' }); }); }); </script> 使用预定义的值: 把属性的动画值设置为 “show”、”hide” 或 “toggle” 高度显示和隐藏通过按钮转换 <script> $(document).ready(function(){ $("button").click(function(){ $("div").animate({ height:'toggle' }); }); }); </script> 队列功能: 依次执行animate <script> $(document).ready(function(){ $("button").click(function(){ var div=$("div"); div.animate({height:'300px',opacity:'0.4'},"slow"); div.animate({width:'300px',opacity:'0.8'},"slow"); div.animate({height:'100px',opacity:'0.4'},"slow"); div.animate({width:'100px',opacity:'0.8'},"slow"); }); }); </script> 总结: 默认情况下,所有 HTML 元素的位置都是静态的,并且无法移动。如需对位置进行操作,记得首先把元素的 CSS position 属性设置为 relative、fixed 或 absolute。 注意: 提示:可以用 animate() 方法来操作所有 CSS 属性吗? 是的,几乎可以!不过,需要记住一件重要的事情:当使用 animate() 时,必须使用 Camel 标记法书写所有的属性名,比如,必须使用 paddingLeft 而不是 padding-left,使用 marginRight 而不是 margin-right,等等。 同时,色彩动画并不包含在核心 jQuery 库中。 如果需要生成颜色动画,您需要从 jQuery.com 下载 Color Animations 插件。 stop() stop() 方法用于停止动画或效果,在它们完成之前。 stop() 方法适用于所有 jQuery 效果函数,包括滑动、淡入淡出和自定义动画。 id为panel动画下滑的时候 单击id为panel的按钮暂停 单击id为flip的按钮继续 <script> $(document).ready(function(){ $("#flip").click(function(){ $("#panel").slideDown(5000); }); $("#stop").click(function(){ $("#panel").stop(); }); }); </script> 注意: stop语法 $(selector).stop(stopAll,goToEnd); 可选的 stopAll 参数规定是否应该清除动画队列。默认是 false,即仅停止活动的动画,允许任何排入队列的动画向后执行。 可选的 goToEnd 参数规定是否立即完成当前动画。默认是 false。 Callback 函数 在当前动画 100% 完成之后执行。 实现:单击按钮 文字文本1秒内隐藏后 输出”hahaha” <script type="text/javascript"> $(document).ready(function(){ $("button").click(function(){ $("p").hide(1000,function(){ alert("hahaha"); }); }); }); </script> 一种名为链接(chaining)的技术,允许我们在相同的元素上运行多条 jQuery 命令,一条接着另一条。 举个栗子: “p1” 元素首先会变为红色,然后向上滑动,然后向下滑动 $("#p1").css("color","red").slideUp(2000).slideDown(2000); 等效于: $("#p1").css("color","red") .slideUp(2000) .slideDown(2000); jQuery 会抛掉多余的空格,并按照一行长代码来执行上面的代码行。 jQuery操作DOM 三个简单实用的用于 DOM 操作的 jQuery 方法: text() - 设置或返回所选元素的文本内容 html() - 设置或返回所选元素的内容(包括 HTML 标记) val() - 设置或返回表单字段的值 举个栗子: <script> $(document).ready(function(){ $("#btn1").click(function(){ alert("Text: " + $("#test").text()); }); $("#btn2").click(function(){ alert("HTML: " + $("#test").html()); }); }); </script> <p id="test">这是段落中的<b>粗体</b>文本。</p> 第一个alert返回的是 这是段落中的粗体文本。 第二个alert返回的是 这是段落中的<b>粗体</b>文本。 <script> $(document).ready(function(){ $("button").click(function(){ alert("Value: " + $("#test").val()); }); }); </script> 返回的是表单的内容 如果是text返回的是 输入的值或者默认值 attr() 方法用于获取属性值。 返回的是id为w3s的href属性值 <script> $(document).ready(function(){ $("button").click(function(){ alert($("#w3s").attr("href")); }); }); </script> 也可直接通过上述方法修改内容 举个栗子: 修改id为test1的文本文件值为”Hello world!” 修改id为test2的html内容为<b>Hello world!</b> 修改id为test3的内容为Dolly Duck <script> $(document).ready(function(){ $("#btn1").click(function(){ $("#test1").text("Hello world!"); }); $("#btn2").click(function(){ $("#test2").html("<b>Hello world!</b>"); }); $("#btn3").click(function(){ $("#test3").val("Dolly Duck"); }); }); </script> 设置属性 - attr() 修改id为w3s的href属性为 http://www.w3school.com.cn/jquery $("button").click(function(){ $("#w3s").attr("href","http://www.w3school.com.cn/jquery"); }); attr() 方法也允许您同时设置多个属性。 $("button").click(function(){ $("#w3s").attr({ "href" : "http://www.w3school.com.cn/jquery", "title" : "hhaha" }); }); attr其实有个问题 如果涉及到复选框之类的设置true false值的时候就不可靠 要用prop 使用attr获取checked属性时返回”checked”和”“,现在使用prop方法获取属性则统一返回true和false。 那么,什么时候使用attr(),什么时候使用prop()? 1.添加属性名称该属性就会生效应该使用prop(); 2.是有true,false两个属性使用prop(); 3.其他则使用attr(); 参考: https://www.cnblogs.com/smartXiang/p/5686800.html text()、html() 以及 val() 的回调函数 回调函数由两个参数:被选元素列表中当前元素的下标,以及原始(旧的)值。然后以函数新值返回您希望使用的字符串。 $("#btn1").click(function(){ $("#test1").text(function(i,origText){ return "Old text: " + origText + " New text: Hello world! (index: " + i + ")"; }); }); $("#btn2").click(function(){ $("#test2").html(function(i,origText){ return "Old html: " + origText + " New html: Hello <b>world!</b> (index: " + i + ")"; }); }); $("button").click(function(){ $("#w3s").attr("href", function(i,origValue){ return origValue + "/jquery"; }); }); 添加新的 HTML 内容 append() - 在被选元素的结尾插入内容 prepend() - 在被选元素的开头插入内容 after() - 在被选元素之后插入内容 before() - 在被选元素之前插入内容 append(): 元素结尾插入 在p结尾添加粗体 在ol列表中结尾添加一行 <script> $(document).ready(function(){ $("#btn1").click(function(){ $("p").append(" <b>Appended text</b>."); }); $("#btn2").click(function(){ $("ol").append("<li>Appended item</li>"); }); }); </script> appendTo跟append相反 prepend():元素开头插入 <script> $(document).ready(function(){ $("#btn1").click(function(){ $("p").prepend("<b>Prepended text</b>. "); }); $("#btn2").click(function(){ $("ol").prepend("<li>Prepended item</li>"); }); }); </script> append和prepend可以一次性添加多个 function appendText() { var txt1="<p>Text.</p>"; // 以 HTML 创建新元素 var txt2=$("<p></p>").text("Text."); // 以 jQuery 创建新元素 var txt3=document.createElement("p"); // 以 DOM 创建新元素 txt3.innerHTML="Text."; $("p").append(txt1,txt2,txt3); // 追加新元素 } after() 和 before() 元素前面和元素后面添加元素 <script> $(document).ready(function(){ $("#btn1").click(function(){ $("img").before("<b>Before</b>"); }); $("#btn2").click(function(){ $("img").after("<i>After</i>"); }); }); </script> 通过 after() 和 before() 方法添加若干新元素 <script> function afterText() { var txt1="<b>I </b>"; // 以 HTML 创建元素 var txt2=$("<i></i>").text("love "); // 通过 jQuery 创建元素 var txt3=document.createElement("big"); // 通过 DOM 创建元素 txt3.innerHTML="jQuery!"; $("img").after(txt1,txt2,txt3); // 在 img 之后插入新元素 } </script> 删除元素 remove() - 删除被选元素(及其子元素) empty() - 从被选元素中删除子元素 举个栗子: 删除id为div1的元素 删除id为div2的元素中的子元素 $("#div1").remove(); $("#div2").empty(); 过滤被删除的元素 添加参数即可 删除 class=”italic” 的所有 元素 $("p").remove(".italic"); 获取并设置 CSS 类 addClass() - 向被选元素添加一个或多个类 removeClass() - 从被选元素删除一个或多个类 toggleClass() - 对被选元素进行添加/删除类的切换操作 css() - 设置或返回样式属性 addClass() 向元素添加css样式 也可向多个元素添加同一个css样式 $("button").click(function(){ $("h1,h2,p").addClass("blue"); $("div").addClass("important"); }); removeClass() 移除一个或者多个类的css样式 $("button").click(function(){ $("h1,h2,p").removeClass("blue"); }); toggleClass() 该方法对被选元素进行添加/删除类的切换操作 先添加blue样式 后删除blue样式 $("button").click(function(){ $("h1,h2,p").toggleClass("blue"); }); 返回 CSS 属性 css() 设置或返回被选元素的一个或多个样式属性 $(“p”).css(“background-color”); 如果有多个p则返回首个匹配元素的 background-color 值 设置 CSS 属性 所有匹配元素设置 background-color 值为yellow $("p").css("background-color","yellow"); 设置多个 CSS 属性 为所有匹配元素设置 background-color 和 font-size $("p").css({"background-color":"yellow","font-size":"200%"}); jQuery 提供多个处理尺寸的重要方法: width()不包括内边距、边框或外边距 height()不包括内边距、边框或外边距 innerWidth()包括内边距 innerHeight()包括内边距 outerWidth()包括内边距和边框 outerHeight()包括内边距和边框 outerWidth(true) 方法返回元素的宽度(包括内边距、边框和外边距)。 outerHeight(true) 方法返回元素的高度(包括内边距、边框和外边距)。 设置指定的 <div >元素的宽度和高度 $("button").click(function(){ $("#div1").width(500).height(500); }); 返回文档(HTML 文档)和窗口(浏览器视口)的宽度和高度 $("button").click(function(){ var txt=""; txt+="Document width/height: " + $(document).width(); txt+="x" + $(document).height() + "\n"; txt+="Window width/height: " + $(window).width(); txt+="x" + $(window).height(); alert(txt); }); 遍历: 向上遍历 DOM 树 parent() 返回被选元素的直接父元素 返回span元素的直接父类 $("span").parent(); parents() 方法返回被选元素的所有祖先元素,它一路向上直到文档的根元素 ()。 所有的span的祖先元素的css元素都设置为红色 $("span").parents().css("color":"red"); 返回所有 元素的所有祖先,并且它是 <ul>>元素 $(document).ready(function(){ $("span").parents("ul"); }); span的所有祖先父类 但是低于div元素父类 就是介于span和div之间的所有元素 $(document).ready(function(){ $("span").parentsUntil("div"); }); 向下遍历 DOM 树 children() 方法返回被选元素的所有直接子元素 返回每个 <div>元素的所有直接子元素 $(document).ready(function(){ $("div").children(); }); 可以使用可选参数来过滤对子元素的搜索 比如: 返回类名为 “1” 的所有 <p> 元素,并且它们是 <div>的直接子元素 $("div").children("p.1"); find() 返回被选元素的后代元素,一路向下直到最后一个后代。 比如: <div> 后代的所有 <span> 元素 $(document).ready(function(){ $("div").find("span"); }); 返回 <div>>的所有后代: $(document).ready(function(){ $("div").find("*"); }); 同胞遍历: siblings() 返回被选元素的所有同胞元素 next() 返回被选元素的下一个同胞元素 只有一个 nextAll() 返回被选元素的所有跟随的同胞元素 nextUntil() 回介于两个给定参数之间的所有跟随的同胞元素 prev() prevAll() prevUntil() prev(), prevAll() & prevUntil() 跟前面的一样 不过是向前而已 siblings() 返回被选元素的所有同胞元素 也可以使用可选参数来过滤对同胞元素的搜索。 $("h2").siblings(); 所有同胞 $("h2").siblings("p"); 是p类型的同胞 nextUntil() 举例: 返回介于 <h2>与 <h6>元素之间的所有同胞元素 不包括h2和h6 $(document).ready(function(){ $("h2").nextUntil("h6"); }); 过滤 first() 第一个元素 last() 最后一个元素 eq() 根据指定索引找元素 filter() 匹配元素 not() 返回不匹配的元素 它们允许您基于其在一组元素中的位置来选择一个特定的元素 first() 返回被选元素的首个元素。 选取首个 <div>元素内部的第一个 <p>元素 $(document).ready(function(){ $("div p").first(); }); last() 相反: 选择最后一个 <div> 元素中的最后一个 <p> 元素 $(document).ready(function(){ $("div p").last(); }); eq() 返回被选元素中带有指定索引号的元素 从0开始 举例:选取第二个 <p> 元素 $(document).ready(function(){ $("p").eq(1); }); filter() 返回匹配的元素 举例: 返回带有类名 “intro” 的所有 <p>元素 $(document).ready(function(){ $("p").filter(".intro"); }); not() 回不匹配标准的所有元素 not() 方法与 filter() 相反。 返回不带有类名 “intro” 的所有<p>元素 $(document).ready(function(){ $("p").not(".intro"); });

优秀的个人博客,低调大师

Nginx PHP配置与优化(学习笔记二十二)

这篇是Nginx安装配置PHP(FastCGI)环境的教程。Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。 一、什么是 FastCGI FastCGI是一个可伸缩地、高速地在HTTP server和动态脚本语言间通信的接口。多数流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等,同时,FastCGI也被许多脚本语言所支持,其中就有PHP。 FastCGI是从CGI发展改进而来的。传统CGI接口方式的主要缺点是性能很差,因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析,然后结果被返回给HTTP服务器。这在处理高并发访问时,几乎是不可用的。另外传统的CGI接口方式安全性也很差,现在已经很少被使用了。 FastCGI接口方式采用C/S结构,可以将HTTP服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时,可以将其直接交付给FastCGI进程来执行,然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。 二、Nginx+FastCGI运行原理 Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket,(这个socket可以是文件socket,也可以是ip socket)。为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接纳到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端,这就是Nginx+FastCGI的整个运作过程。详细的过程,如图1所示。 图1 Nginx+FastCGI运行原理 三、spawn-fcgi与PHP-FPM 前面介绍过,FastCGI接口方式在脚本解析服务器上启动一个或者多个守护进程对动态脚本进行解析,这些进程就是FastCGI进程管理器,或者称之为FastCGI引擎, spawn-fcgi与PHP-FPM就是支持PHP的两个FastCGI进程管理器。下面简单介绍spawn-fcgi与PHP-FPM的异同。 spawn-fcgi是HTTP服务器lighttpd的一部分,目前已经独立成为一个项目,一般与lighttpd配合使用来支持PHP,但是ligttpd的spwan-fcgi在高并发访问的时候,会出现内存泄漏甚至自动重启FastCGI的问题。 Nginx是个轻量级的HTTP server,必须借助第三方的FastCGI处理器才可以对PHP进行解析,因此Nginx+spawn-fcgi的组合也可以实现对PHP的解析,这里不过多讲述。 PHP-FPM也是一个第三方的FastCGI进程管理器,它是作为PHP的一个补丁来开发的,在安装的时候也需要和PHP源码一起编译,也就是说PHP-FPM被编译到PHP内核中,因此在处理性能方面更加优秀;同时它在处理高并发方面也比spawn-fcgi引擎好很多,因此,推荐Nginx+PHP/PHP-FPM这个组合对PHP进行解析。 FastCGI 的主要优点是把动态语言和HTTP Server分离开来,所以Nginx与PHP/PHP-FPM经常被部署在不同的服务器上,以分担前端Nginx服务器的压力,使Nginx专一处理静态请求和转发动态请求,而PHP/PHP-FPM服务器专一解析PHP动态请求。 四、 PHP与PHP-FPM的安装及优化 1. 下载安装包 从php官方网站下载PHP源码包,这里下载的是稳定版php-5.2.13.tar.gz。从这里下载对应的PHP-FPM源码包,这里下载的是php-5.2.13-fpm-0.5.13.diff.gz。需要注意,在下载软件包版本时,尽量使PHP和PHP-FPM版本一致,如果版本之间相差太大,可以会出现兼容问题。 2. 配置安装环境 安装PHP需要下面软件包的支持,如果没有安装,请自行安装。 yum -y install gcc gcc-c++ libxml2 libxml2-devel autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel 由于各个Linux系统版本的不确定性,读者也可以在安装PHP过程中,根据错误提示信息,安装对应的软件库。 3. 开始编译安装PHP和PHP-FPM 编译安装PHP和PHP-FPM很简单,下面是安装过程: tar zxvf php-5.2.13.tar.gz gzip -cd php-5.2.13-fpm-0.5.13.diff.gz | patch -d php-5.2.13 -p1 cd php-5.2.13 ./configure --prefix=/usr/local/php --enable-fastcgi --enable-fpm make make install cp php.ini-dist /usr/local/php/lib/php.ini 其中,第二步将PHP-FPM作为补丁加入PHP源码中。 在“./configure”编译选项中,指定将PHP安装到/usr/local下,“--enable-fastcgi”是启用对PHP的FastCGI支持,“--enable-fpm”是激活对FastCGI模式的fpm支持。 在编译PHP时可以加入很多编译选项,但是这里为了介绍PHP的FastCGI功能没有加入更多的编译选项。 4. 配置与优化 PHP-FPM PHP的全局配置文件是php.ini,在上面的步骤中,已经将此文件复制到了/usr/local/php/lib/php.ini下。可以根据每个应用需求的不同,对php.ini进行相应的配置。 下面重点介绍PHP-FPM引擎的配置文件。根据上面指定的安装路径,PHP-FPM的默认配置文件为/usr/local/php/etc/php-fpm.conf。 php-fpm.conf是一个XML格式的纯文本文件,其内容很容易看明白。 这里重点介绍几个重要的配置标签: 标签listen_address是配置fastcgi进程监听的IP地址以及端口,默认是127.0.0.1:9000。 127.0.0.1:9000 标签display_errors用来设置是否显示PHP错误信息,默认是0,不显示错误信息,设置为1可以显示PHP错误信息。 0 标签user和group用于设置运行FastCGI进程的用户和用户组。需要注意的是,这里指定的用户和用户组要和Nginx配置文件中指定的用户和用户组一致。 nobody < value name="group">nobody 标签max_children用于设置FastCGI的进程数。根据官方建议,小于2GB内存的服务器,可以只开启64个进程,4GB以上内存的服务器可以开启200个进程。 5 标签request_terminate_timeout用于设置FastCGI执行脚本的时间。默认是0s,也就是无限执行下去,可以根据情况对其进行修改。 0s 标签rlimit_files用于设置PHP-FPM对打开文件描述符的限制,默认值为1024。这个标签的值必须和Linux内核打开文件数关联起来,例如要将此值设置为65535,就必须在Linux命令行执行'ulimit -HSn 65536'。 1024 标签max_requests指明了每个children最多处理多少个请求后便会被关闭,默认的设置是500。 500 标签allowed_clients用于设置允许访问FastCGI进程解析器的IP地址。如果不在这里指定IP地址,Nginx转发过来的PHP解析请求将无法被接受。 127.0.0.1 5. 管理FastCGI进程 在配置完php-fpm后,就可以启动FastCGI进程了。启动fastcgi进程有两种方式: /usr/local/php/bin/php-cgi --fpm 或者 /usr/local/php/sbin/php-fpm start 建议采用第二种方式启动FastCGI进程。/usr/local/php/sbin/php-fpm还有其他参数,具体为start|stop|quit|restart|reload|logrotate。 每个启动参数的含义如下: start,启动PHP的FastCGI进程 stop,强制终止PHP的FastCGI进程 quit,平滑终止PHP的FastCGI进程 restart, 重启PHP的FastCGI进程 reload, 重新加载PHP的php.ini logrotate, 重新启用log文件 reload是个很重要的参数,它可以在PHP的FastCGI进程不中断的情况下重新加载改动过的php.ini,因此通过php-fpm可以平滑变更FastCGI模式下的PHP设置。 在FastCGI进程启动后,其监听的IP地址和端口也随即启动,可以通过ps和netstat查看相关信息。 netstat -antl|grep 9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN ps -ef|grep php-cgi root 3567 1 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3568 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3569 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3570 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3571 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf nobody 3572 3567 0 17:06 ? 00:00:00 /usr/local/php/bin/php-cgi --fpm --fpm-config /usr/local/php/etc/php-fpm.conf root 3583 3524 0 17:09 pts/1 00:00:00 grep php-cgi 五、配置Nginx来支持PHP Nginx的安装特别简单,前面已经对此进行了详细介绍,这里不再进行讲述。下面重点介绍Nginx如何通过php-fpm的FastCGI进程对PHP进行解析处理。 由于Nginx本身不会对PHP进行解析,因此要实现Nginx对PHP的支持,其实是将对PHP页面的请求交给fastCGI进程监听的IP地址及端口。如果把php-fpm当做动态应用服务器,那么Nginx其实就是一个反向代理服务器。Nginx通过反向代理功能实现对PHP的解析,这就是Nginx实现PHP动态解析的原理。 这里假定Nginx的安装目录为/usr/local,则Nginx配置文件的路径为/usr/local/nginx/conf/nginx.conf。下面是在Nginx下支持PHP解析的一个虚拟主机配置实例。 server { include port.conf; server_name www.ixdba.net ixdba.net; location / { index index.html index.php; root /web/www/www.ixdba.net; } location ~ .php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME html$fastcgi_script_name; include fastcgi_params; } } 通过location指令,将所有以php为后缀的文件都交给127.0.0.1:9000来处理,而这里的IP地址和端口就是FastCGI进程监听的IP地址和端口。fastcgi_param指令指定放置PHP动态程序的主目录,也就是$fastcgi_script_name前面指定的路径,这里是/usr/local/nginx/html目录,建议将这个目录与Nginx虚拟主机指定的根目录保持一致,当然也可以不一致。fastcgi_params文件是FastCGI进程的一个参数配置文件,在安装Nginx后,会默认生成一个这样的文件,这里通过include指令将FastCGI参数配置文件包含了进来。 接下来,启动nginx服务。/usr/local/nginx/sbin/nginx到此为止,Nginx+PHP已经配置完成。 六、测试Nginx对PHP的解析功能 这里在/usr/local/nginx/html目录下创建一个phpinfo.php文件,内容如下: < ?php phpinfo(); ?> 然后通过浏览器访问,默认会在浏览器显示“Welcome to Nginx!”表示Nginx正常运行。 接着在浏览器中访问phpinfo.php,如果PHP能够正常解析,会出现PHP安装配置以及功能列表统计信息。 七、实例讲解Nginx中FastCGI参数的优化 在配置完成Nginx+FastCGI之后,为了保证Nginx下PHP环境的高速稳定运行,需要添加一些FastCGI优化指令。下面给出一个优化实例,将下面代码添加到Nginx主配置文件中的HTTP层级。 fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2 keys_zone=TEST:10m inactive=5m; fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; fastcgi_cache TEST; fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 1d; fastcgi_cache_valid any 1m; 下面是对上述代码的含义进行介绍: 第一行代码是为FastCGI缓存指定一个文件路径、目录结构等级、关键字区域存储时间和非活动删除时间。 fastcgi_connect_timeout指定连接到后端FastCGI的超时时间。 fastcgi_send_timeout指定向FastCGI传送请求的超时时间,这个值是已经完成两次握手后向FastCGI传送请求的超时时间。 fastcgi_read_timeout指定接收FastCGI应答的超时时间,这个值是已经完成两次握手后接收FastCGI应答的超时时间。 fastcgi_buffer_size用于指定读取FastCGI应答第一部分需要用多大的缓冲区,这个值表示将使用1个64KB的缓冲区读取应答的第一部分(应答头),可以设置为fastcgi_buffers选项指定的缓冲区大小。 fastcgi_buffers指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求。如果一个PHP脚本所产生的页面大小为256KB,那么会为其分配4个64KB的缓冲区来缓存;如果页面大小大于256KB,那么大于256KB的部分会缓存到fastcgi_temp指定的路径中,但是这并不是好方法,因为内存中的数据处理速度要快于硬盘。一般这个值应该为站点中PHP脚本所产生的页面大小的中间值,如果站点大部分脚本所产生的页面大小为256KB,那么可以把这个值设置为“16 16k”、“4 64k”等。 fastcgi_busy_buffers_size的默认值是fastcgi_buffers的两倍。 fastcgi_temp_file_write_size表示在写入缓存文件时使用多大的数据块,默认值是fastcgi_buffers的两倍。 fastcgi_cache表示开启FastCGI缓存并为其指定一个名称。开启缓存非常有用,可以有效降低CPU的负载,并且防止502错误的发生,但是开启缓存也会引起很多问题,要视具体情况而定。 fastcgi_cache_valid、fastcgi用来指定应答代码的缓存时间,实例中的值表示将200和302应答缓存一个小时,将301应答缓存1天,其他应答均缓存1分钟。

优秀的个人博客,低调大师

Jenkins +Cobertura代码覆盖率(学习笔记三十七)

https://www.cnblogs.com/testway/p/6380656.html 1、新建一个maven工程,在src/main/java 下建一个CoverageTest.java 类 package test_junit;publicclass CoverageTest { public CoverageTest() { // TODO Auto-generated constructor stub } publicstaticvoid main(String[] args) { // TODO Auto-generated method stub } publicstaticinttestadd(intx,int y){ intc = 0; if(x == 10){ c = x + y; }else{ c = (x + y)*2; } return c; } } 2、在src/main/java 新建一个测试类JunitTest.java package junit;import org.junit.Assert;import org.junit.Test;import test_junit.CoverageTest;/** * Created by 000284 on 2017/2/6. */publicclass JunitTest { @Test publicvoid testadd(){ intb = CoverageTest.testadd(5, 20); Assert.assertEquals(b,50); } } 3、pom.xml 文件 4.0.0testunittest_junit1.0-SNAPSHOTjenkinsenv.BUILD_NUMBERorg.codehaus.mojocobertura-maven-plugin2.7xmlpackagecoberturajunitjunit4.12 3、jenkins 安装插件cobertura 4、新建jenkins job build >Goals and options 设置:clean cobertura:cobertura Cobertura xml report pattern 设置:**/target/site/cobertura/coverage.xml post setps 设置:Enable the "Publish Cobertura Coverage Report" publisher 5、构建job 查看Coverage Report就会显示覆盖率报表

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册