整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          sendmsg系統調用

          sendmsg系統調用

          endmsg系統調用,主要工作是將用戶空間的消息頭復制到內核空間中,對消息頭進行檢查。最后逐級調用發包接口發送數據。

          https://www.cnblogs.com/wanpengcoder/p/11749313.html

          send、sendto、sendmsg區別:

          https://www.cnblogs.com/hnrainll/archive/2011/08/16/2141483.html

          send只可用于基于連接的套接字,send 和 write唯一的不同點是標志的存在,當標志為0時,send等同于write。sendto 和 sendmsg既可用于無連接的套接字,也可用于基于連接的套接字。

          SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)

          E:\linux-4.1.45\linux-4.1.45\net\socket.c
          SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
          {
          	if (flags & MSG_CMSG_COMPAT)
          		return -EINVAL;
          	return __sys_sendmsg(fd, msg, flags);
          }
          

          __sys_sendmsg()

          
          /*
           *	BSD sendmsg interface
           */
          
          long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
          {
          	int fput_needed, err;
          	struct msghdr msg_sys;
          	struct socket *sock;
          
          	sock=sockfd_lookup_light(fd, &err, &fput_needed);//根據fd找到對應socket
          	if (!sock)
          		goto out;
          
                  //發送數據
          	err=___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
          
          	fput_light(sock->file, fput_needed);
          out:
          	return err;
          }
          

          ___sys_sendmsg()

          
          static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
          			 struct msghdr *msg_sys, unsigned int flags,
          			 struct used_address *used_address)
          {
          	struct compat_msghdr __user *msg_compat=(struct compat_msghdr __user *)msg;
          	struct sockaddr_storage address;
          	struct iovec iovstack[UIO_FASTIOV], *iov=iovstack;
          	unsigned char ctl[sizeof(struct cmsghdr) + 20]
          	    __attribute__ ((aligned(sizeof(__kernel_size_t))));
          	/* 20 is size of ipv6_pktinfo */
          	unsigned char *ctl_buf=ctl;
          	int ctl_len;
          	ssize_t err;
          
          	msg_sys->msg_name=&address;
          
          	if (MSG_CMSG_COMPAT & flags)
                           /* 從64位消息頭拷貝數據到32位消息頭 */
          		err=get_compat_msghdr(msg_sys, msg_compat, NULL, &iov);
          	else
          		err=copy_msghdr_from_user(msg_sys, msg, NULL, &iov);
          	if (err < 0)
          		return err;
          
          	err=-ENOBUFS;
          
                  /* 控制信息長度錯誤 */
          	if (msg_sys->msg_controllen > INT_MAX)
          		goto out_freeiov;
          
                  /* 拷貝控制信息 */
          	ctl_len=msg_sys->msg_controllen;
          	if ((MSG_CMSG_COMPAT & flags) && ctl_len) {
          		err=cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl,
          						     sizeof(ctl));
          		if (err)
          			goto out_freeiov;
          		ctl_buf=msg_sys->msg_control;
          		ctl_len=msg_sys->msg_controllen;
          	} else if (ctl_len) {
          		if (ctl_len > sizeof(ctl)) {
          			ctl_buf=sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
          			if (ctl_buf==NULL)
          				goto out_freeiov;
          		}
          		err=-EFAULT;
          		/*
          		 * Careful! Before this, msg_sys->msg_control contains a user pointer.
          		 * Afterwards, it will be a kernel pointer. Thus the compiler-assisted
          		 * checking falls down on this.
          		 */
          		if (copy_from_user(ctl_buf,
          				   (void __user __force *)msg_sys->msg_control,
          				   ctl_len))
          			goto out_freectl;
          		msg_sys->msg_control=ctl_buf;
          	}
          
                   /* 設置發送標記 */
          	msg_sys->msg_flags=flags;
          
                  /* 設置非阻塞標記 */
          	if (sock->file->f_flags & O_NONBLOCK)
          		msg_sys->msg_flags |=MSG_DONTWAIT;
          	
                  /* 如果這次發送的地址跟上次成功發送的一致 */
                  /*
          	 * If this is sendmmsg() and current destination address is same as
          	 * previously succeeded address, omit asking LSM's decision.
          	 * used_address->name_len is initialized to UINT_MAX so that the first
          	 * destination address never matches.
          	 */
          	if (used_address && msg_sys->msg_name &&
          	    used_address->name_len==msg_sys->msg_namelen &&
          	    !memcmp(&used_address->name, msg_sys->msg_name,
          		    used_address->name_len)) {
                          /* 無需進行檢查,直接發送 */
          		err=sock_sendmsg_nosec(sock, msg_sys);
          		goto out_freectl;
          	}
                  /* 進行安全模塊檢查后發送 */
          	err=sock_sendmsg(sock, msg_sys);
          
                  /* 發送成功需要更新成功地址記錄 */
          	/*
          	 * If this is sendmmsg() and sending to current destination address was
          	 * successful, remember it.
          	 */
          	if (used_address && err >=0) {
          		used_address->name_len=msg_sys->msg_namelen;
          		if (msg_sys->msg_name)
          			memcpy(&used_address->name, msg_sys->msg_name,
          			       used_address->name_len);
          	}
          
          out_freectl:
          	if (ctl_buf !=ctl)
          		sock_kfree_s(sock->sk, ctl_buf, ctl_len);
          out_freeiov:
          	kfree(iov);
          	return err;
          }
          

          在項目中測試發現,沒有定義CONFIG_COMPAT宏, 用的是#define compat_msghdr msghdr

          E:\linux-4.1.45\linux-4.1.45\include\net\compat.h
          #if defined(CONFIG_COMPAT)
          
          #include <linux/compat.h>
          
          struct compat_msghdr {
          	compat_uptr_t	msg_name;	/* void * */
          	compat_int_t	msg_namelen;
          	compat_uptr_t	msg_iov;	/* struct compat_iovec * */
          	compat_size_t	msg_iovlen;
          	compat_uptr_t	msg_control;	/* void * */
          	compat_size_t	msg_controllen;
          	compat_uint_t	msg_flags;
          };
          
          ...
          
          #else /* defined(CONFIG_COMPAT) */
          /*
           * To avoid compiler warnings:
           */
          #define compat_msghdr	msghdr
          #define compat_mmsghdr	mmsghdr
          #endif /* defined(CONFIG_COMPAT) */

          sock_sendmsg()

          int sock_sendmsg(struct socket *sock, struct msghdr *msg)
          {
          	int err=security_socket_sendmsg(sock, msg,
          					  msg_data_left(msg));
          
          	return err ?: sock_sendmsg_nosec(sock, msg);
          }
          

          sock_sendmsg_nosec()

          static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
          {
          	int ret=sock->ops->sendmsg(sock, msg, msg_data_left(msg));
          	BUG_ON(ret==-EIOCBQUEUED);
          	return ret;
          }
          

          inet_sendmsg()

          對表單的驗證,自己寫大量的js畢竟不是一個明智的做法。不僅僅是代碼很長而且不便于梳理。Validform就是一款開源的第三方驗證js的控件,通過添加相應的js以及css能夠有效的驗證表單,維護起來也很方便。

          1、js和css的引用:

          這里引用官網下載中的一下css:

          (文件里這個注釋 "/*==========以下部分是Validform必須的===========*/" 之后的部分是必須的)

          畢竟validform是基于jquery編寫的,所以這個地方也需要引用Jquery腳本;

          <script type="text/javascript" src="http://validform.rjboy.cn/wp-content/themes/validform/js/jquery-1.6.2.min.js"></script>
          <script type="text/javascript" src="http://validform.rjboy.cn/Validform/v5.1/Validform_v5.1_min.js"></script>
          

          2、表單元素的屬性綁定:

          表單元素的屬性主要有:datatype、nullmsg、sucmsg、errormsg、ignore、recheck、tip、altercss、ajaxurl 和 plugin;

          2.1:datatype:

          內置基本的datatype類型有: * | *6-16 | n | n6-16 | s | s6-18 | p | m | e | url

          *:檢測是否有輸入,可以輸入任何字符,不留空即可通過驗證;

          *6-16:檢測是否為6到16位任意字符;

          n:數字類型;

          n6-16:6到16位數字;

          s:字符串類型;

          s6-18:6到18位字符串;

          p:驗證是否為郵政編碼;

          m:手機號碼格式;

          e:email格式;

          url:驗證字符串是否為網址。

          自定義datatype的名稱,可以由字母、數字、下劃線、中劃線和*號組成。

          形如"*6-16"的datatype,Validform會自動擴展,可以指定任意的數值范圍。如內置基本類型有"*6-16",那么你綁定datatype="*4-12"就表示4到12位任意字符。如果你自定義了一個datatype="zh2-4",表示2到4位中文字符,那么datatype="zh2-6"就表示2到6位中文字符。

          5.2版本之后,datatype支持規則累加或單選。用","分隔表示規則累加;用"|"分隔表示規則多選一,即只要符合其中一個規則就可以通過驗證,綁定的規則會依次驗證,只要驗證通過,后面的規則就會忽略不再比較。如綁定datatype="m|e",表示既可以填寫手機號碼,也能填寫郵箱地址,如果知道填入的是手機號碼,那么就不會再檢測他是不是郵箱地址;datatype="zh,s2-4",表示要符合自定義類型"zh",也要符合規則"s2-4"。

          注:

          5.2.1版本之后,datatype支持:

          直接綁定正則:如可用這樣寫datatype="/\w{3,6}/i",要求是3到6位的字母,不區分大小寫;

          支持簡單的邏輯運算:如datatype="m | e, *4-18 | /\w{3,6}/i | /^validform\.rjboy\.cn$/",

          這個表達式的意思是:可以是手機號碼;或者是郵箱地址,但字符長度必須在4到18位;或者是3到6位的字母,不區分大小寫;或者輸入validform.rjboy.cn,區分大小寫。這里","分隔相當于邏輯運算里的"&&"; "|"分隔相當于邏輯運算里的"||";不支持括號運算。

          2.2、nullmsg:

          當表單元素值為空時的提示信息,不綁定,默認提示"請填入信息!"。如:nullmsg="請填寫用戶名!"

          2.3、sucmsg :

          當表單元素通過驗證時的提示信息,不綁定,默認提示"通過信息驗證!"。如:sucmsg="用戶名還未被使用,可以注冊!"

          2.4、errormsg:

          輸入內容不能通過驗證時的提示信息,默認提示"請輸入正確信息!"。如:errormsg="用戶名必須是2到4位中文字符!"

          2.5、ignore:

          綁定了ignore="ignore"的表單元素,在有輸入時,會驗證所填數據是否符合datatype所指定數據類型,沒有填寫內容時則會忽略對它的驗證;

          2.6、rechec:

          表單里面經常需要檢查兩次密碼輸入是否一致,recheck就是用來指定需要比較的另外一個表單元素。如:recheck="password1",那么它就會拿當前元素的值跟該表單下,name為"password1"的元素比較。

          2.7、tip:

          表單里經常有些文本框需要默認就顯示一個灰色的提示文字,當獲得焦點時提示文字消失,失去焦點時提示文字顯示。tip屬性就是用來實現這個效果。它通常和altercss搭配使用。如<input type="text" value="默認提示文字" class="gray intxt" tip="默認提示文字" altercss="gray" />

          2.8、altercss:

          它需要和tip屬性配合使用,altercss指定的樣式名,會在文本框獲得焦點時被刪除,沒有輸入內容而失去焦點時重新加上。

          2.9、ajaxurl:

          指定ajax實時驗證的后臺文件的地址。后臺頁面如valid.php文件中可以用 $_POST["param"] 接收到值,Ajax中會POST過來變量param和name。param是文本框的值,name是文本框的name屬性。

          2.10、plugin:

          指定需要使用的插件。5.3版開始,對于日期、swfupload和密碼強度檢測這三個插件,綁定了plugin屬性即可以初始化對應的插件,可以不用在validform初始化時傳入空的usePlugi了。

          舉例如下:

          <!--ajax實時驗證用戶名-->
          <input type="text" value="" name="name" datatype="e" ajaxurl="valid.php?myparam1=value1&myparam2=value2" sucmsg="用戶名驗證通過!" nullmsg="請輸入用戶名!" errormsg="請用郵箱或手機號碼注冊!" />
           
          <!--密碼-->
          <input type="password" value="" name="userpassword" datatype="*6-15" errormsg="密碼范圍在6~15位之間!" />
          <!--確認密碼-->
          <input type="password" value="" name="userpassword2" datatype="*" recheck="userpassword" errormsg="您兩次輸入的賬號密碼不一致!" />
           
          <!--默認提示文字-->
          <textarea tip="請在這里輸入您的意見。" errormsg="很感謝您花費寶貴時間給我們提供反饋,請填寫有效內容!" datatype="s" altercss="gray" class="gray" name="msg" value="">請在這里輸入您的意見。</textarea>
           
          <!--使用swfupload插件-->
          <input type="text" plugin="swfupload" class="inputxt" disabled="disabled" value="">
          <input type="hidden" value="" pluginhidden="swfupload">
           
          <!--使用passwordStrength插件-->
          <input type="password" errormsg="密碼至少6個字符,最多18個字符!" datatype="*6-18" plugin="passwordStrength" class="inputxt" name="password" value="">
          <div class="passwordStrength" style="display:none;"><b>密碼強度:</b> <span>弱</span><span>中</span><span class="last">強</span></div>
           
          <!--使用DatePicker插件-->
          <input type="text" plugin="datepicker" class="inputxt" name="birthday" value="">
          

          初始化參數說明:

          參數說明:【所有參數均為可選項】

          • 必須是表單對象執行Validform方法,示例中".demoform"就是綁定在form元素上的class名稱;
          • btnSubmit
          • 指定當前表單下的哪一個按鈕觸發表單提交事件,如果表單下有submit按鈕時可以省略該參數。示例中".btn_sub"是該表單下要綁定點擊提交表單事件的按鈕;
          • btnReset
          • ".btn_reset"是該表單下要綁定點擊重置表單事件的按鈕;
          • tiptype
          • 可用的值有:1、2、3、4和function函數,默認tiptype為1。 3、4是5.2.1版本新增
          • 1=> 自定義彈出框提示;
          • 2=> 側邊提示(會在當前元素的父級的next對象的子級查找顯示提示信息的對象,表單以ajax提交時會彈出自定義提示框顯示表單提交狀態);
          • 3=> 側邊提示(會在當前元素的siblings對象中查找顯示提示信息的對象,表單以ajax提交時會彈出自定義提示框顯示表單提交狀態);
          • 4=> 側邊提示(會在當前元素的父級的next對象下查找顯示提示信息的對象,表單以ajax提交時不顯示表單的提交狀態);
          • 如果上面的4種提示方式不是你需要的,你可以給tiptype傳入自定義函數。通過自定義函數,可以實現你想要的任何提示效果:
          tiptype:function(msg,o,cssctl){
           //msg:提示信息;
           //o:{obj:*,type:*,curform:*},
           //obj指向的是當前驗證的表單元素(或表單對象,驗證全部驗證通過,提交表單時o.obj為該表單對象),
           //type指示提示的狀態,值為1、2、3、4, 1:正在檢測/提交數據,2:通過驗證,3:驗證失敗,4:提示ignore狀態, 
           //curform為當前form對象;
           //cssctl:內置的提示信息樣式控制函數,該函數需傳入兩個參數:顯示提示信息的對象 和 當前提示的狀態(既形參o中的type);
          }
          具體參見demo頁。
          
          • tiptype不為1時,Validform會查找class為"Validform_checktip"的標簽顯示提示信息。tiptype=1時,會自動創建彈出框顯示提示信息。
          • Validform_checktip和表單元素之間的位置關系,會根據tiptype的值有對應的結構,上面已經做了說明。
          • 5.3版本開始,如果頁面里沒有顯示出錯信息的標簽,會根據tiptype值自動創建Validform_checktip對象。
          • ignoreHidden
          • 可用值: true | false。
          • 默認為false,當為true時對:hidden的表單元素將不做驗證;
          • dragonfly
          • 可用值: true | false。
          • 默認false,當為true時,值為空時不做驗證;
          • tipSweep
          • 可用值: true | false。
          • 默認為false, 5.3版中做了修正,在各種tiptype下, 為true時提示信息將只會在表單提交時觸發顯示,各表單元素blur時不會觸發信息提示;
          • label 5.3.1+
          • 選擇符
          • 在沒有綁定nullmsg時查找要顯示的提示文字,默認查找".Validform_label"下的文字;
          • showAllError
          • 可用值: true | false。
          • 默認為false,true:提交表單時所有錯誤提示信息都會顯示;false:一碰到驗證不通過的對象就會停止檢測后面的元素,只顯示該元素的錯誤信息;
          • postonce
          • 可用值: true | false。
          • 默認為false,指定是否開啟二次提交防御,true開啟,不指定則默認關閉;
          • 為true時,在數據成功提交后,表單將不能再繼續提交。
          • ajaxPost
          • 可用值: true | false。
          • 默認為false,使用ajax方式提交表單數據,將會把數據POST到config方法或表單action屬性里設定的地址;
          • datatype
          • 傳入自定義datatype類型,可以是正則,也可以是函數。
          datatyp:{
           "zh2-4":/^[\u4E00-\u9FA5\uf900-\ufa2d]{2,4}$/,
           "phone":function(gets,obj,curform,regxp){
           //參數gets是獲取到的表單元素值,
           //obj為當前表單元素,
           //curform為當前驗證的表單,
           //regxp為內置的一些正則表達式的引用。
           
           //return false表示驗證出錯,沒有return或者return true表示驗證通過。
           }
          }
          
          • 具體示例請參考demo頁;
          • usePlugin
          • 目前已整合swfupload、datepicker、passwordstrength和jqtransform四個插件,在這里傳入這些插件使用時需要傳入的參數。datepicker在Validform內調用時另外擴展了幾個比較實用的參數,具體請參考demo頁;
          • beforeCheck(curform)
          • 在表單提交執行驗證之前執行的函數,curform參數獲取到的是當前表單對象。
          • 函數return false的話將不會繼續執行驗證操作;
          • beforeSubmit(curform)
          • 在表單驗證通過,提交表單數據之前執行的函數,data參數是當前表單對象。
          • 函數return false的話表單將不會提交;
          • callback
          • 在使用ajax提交表單數據時,數據提交后的回調函數。返回數據data是Json對象:
          • {"info":"demo info","status":"y"}
          • info: 輸出提示信息,
          • status: 返回提交數據的狀態,是否提交成功,"y"表示提交成功,"n"表示提交失敗,在ajax_post.php文件返回數據里自定字符,主要用在callback函數里根據該值執行相應的回調操作。你也可以在ajax_post.php文件返回更多信息在這里獲取,進行相應操作;
          • 如果不是ajax方式提交表單,傳入callback,這時data參數是當前表單對象,回調函數會在表單驗證全部通過后執行,然后判斷是否提交表單,如果callback里return false,則表單不會提交,如果return true或沒有return,則會提交表單。
          • 5.3版開始,ajax遇到服務端錯誤時也會執行回調,這時的data是{ status:**, statusText:**, readyState:**, responseText:** }

          初始化舉例代碼如下:

          $(".demoform").Validform({
           btnSubmit:"#btn_sub", 
           btnReset:".btn_reset",
           tiptype:1, 
           ignoreHidden:false,
           dragonfly:false,
           tipSweep:true,
           label:".label",
           showAllError:false,
           postonce:true,
           ajaxPost:true,
           datatype:{
           "*6-20": /^[^\s]{6,20}$/,
           "z2-4" : /^[\u4E00-\u9FA5\uf900-\ufa2d]{2,4}$/,
           "username":function(gets,obj,curform,regxp){
           //參數gets是獲取到的表單元素值,obj為當前表單元素,curform為當前驗證的表單,regxp為內置的一些正則表達式的引用;
           var reg1=/^[\w\.]{4,16}$/,
           reg2=/^[\u4E00-\u9FA5\uf900-\ufa2d]{2,8}$/;
           
           if(reg1.test(gets)){return true;}
           if(reg2.test(gets)){return true;}
           return false;
           
           //注意return可以返回true 或 false 或 字符串文字,true表示驗證通過,返回字符串表示驗證失敗,字符串作為錯誤提示顯示,返回false則用errmsg或默認的錯誤提示;
           },
           "phone":function(){
           // 5.0 版本之后,要實現二選一的驗證效果,datatype 的名稱 不 需要以 "option_" 開頭; 
           }
           },
           usePlugin:{
           swfupload:{},
           datepicker:{},
           passwordstrength:{},
           jqtransform:{
           selector:"select,input"
           }
           },
           beforeCheck:function(curform){
           //在表單提交執行驗證之前執行的函數,curform參數是當前表單對象。
           //這里明確return false的話將不會繼續執行驗證操作; 
           },
           beforeSubmit:function(curform){
           //在驗證成功后,表單提交前執行的函數,curform參數是當前表單對象。
           //這里明確return false的話表單將不會提交; 
           },
           callback:function(data){
           //返回數據data是json對象,{"info":"demo info","status":"y"}
           //info: 輸出提示信息;
           //status: 返回提交數據的狀態,是否提交成功。如可以用"y"表示提交成功,"n"表示提交失敗,在ajax_post.php文件返回數據里自定字符,主要用在callback函數里根據該值執行相應的回調操作;
           //你也可以在ajax_post.php文件返回更多信息在這里獲取,進行相應操作;
           //ajax遇到服務端錯誤時也會執行回調,這時的data是{ status:**, statusText:**, readyState:**, responseText:** };
           
           //這里執行回調操作;
           //注意:如果不是ajax方式提交表單,傳入callback,這時data參數是當前表單對象,回調函數會在表單驗證全部通過后執行,然后判斷是否提交表單,如果callback里明確return false,則表單不會提交,如果return true或沒有return,則會提交表單。
           }
          });
          

          Validform對象:

          如示例 var demo=$(".formsub").Validform(),那么demo對象會有以下屬性和方法可以調用:

          tipmsg【object】

          如:demo.tipmsg.s="error! no message inputed.";

          通過該對象可以修改除 tit 以外的其他提示文字,這樣可以實現同一個頁面的不同表單使用不同的提示文字。

          具體可修改的提示文字
          $.Tipmsg={//默認提示文字;
          tit:"提示信息",
          w:{
           "*":"不能為空!",
           "*6-16":"請填寫6到16位任意字符!",
           "n":"請填寫數字!",
           "n6-16":"請填寫6到16位數字!",
           "s":"不能輸入特殊字符!",
           "s6-18":"請填寫6到18位字符!",
           "p":"請填寫郵政編碼!",
           "m":"請填寫手機號碼!",
           "e":"郵箱地址格式不對!",
           "url":"請填寫網址!"
          },
          def:"請填寫正確信息!",
          undef:"datatype未定義!",
          reck:"兩次輸入的內容不一致!",
          r:"通過信息驗證!",
          c:"正在檢測信息…",
          s:"請{填寫|選擇}{0|信息}!",
          v:"所填信息沒有經過驗證,請稍后…",
          p:"正在提交數據…"
          };
          

          要修改tit(彈出框的標題文字)的話,可以這樣:$.Tipmsg.tit="Message Box",則彈出框的標題文字會換成"Message Box"

          注:5.3.2+

          $.Tipmsg.w里,形如"*6-16"的提示文字,里面的數字是會被替換的。如綁定datatype="*2-18",那它默認的出錯信息就會是"請填寫2到18位任意字符!",可以通過$.Tipmsg.w或Validform對象的tipmsg屬性修改和擴展默認錯誤信息,如果你已經設置了"zh2-4"的提示信息是"2-4位中文",那么"zh2-8"出錯的信息就自動會是:"2-8位中文"。對于自定義的datatype,在擴展默認信息時,注意錯誤信息的名字要跟datatype名字一樣,如上面示例是:$.Tipmsg.w["zh2-4"]="2-4位中文"。對于多頁面或一個頁面多表單有相同datatype來說,在$.Tipmsg.w或Validform對象的tipmsg屬性中擴展默認提示信息是個很好的選擇。

          5.3.1+

          $.Tipmsg.s是用來指定在沒有綁定nullmsg時的默認提示信息。"{0}"是會被找到的label參數指定的對象或Validform_label里的文字替換掉的,"{填寫|選擇}"里的文字在綁定了"recheck"屬性的表單元素上檢測時是會不顯示的,當前驗證對象是radio、checkbox或select時,會輸出"選擇",是其他類型的元素時會輸出"填寫"和后面的"信息"。

          具體示例請參見demo頁。

          dataType【object】

          獲取內置的一些正則:

          {
           "match":/^(.+?)(\d+)-(\d+)$/,
           "*":/[\w\W]+/,
           "*6-16":/^[\w\W]{6,16}$/,
           "n":/^\d+$/,
           "n6-16":/^\d{6,16}$/,
           "s":/^[\u4E00-\u9FA5\uf900-\ufa2d\w\.\s]+$/,
           "s6-18":/^[\u4E00-\u9FA5\uf900-\ufa2d\w\.\s]{6,18}$/,
           "p":/^[0-9]{6}$/,
           "m":/^13[0-9]{9}$|14[0-9]{9}|15[0-9]{9}$|18[0-9]{9}$/,
           "e":/^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
           "url":/^(\w+:\/\/)?\w+(\.\w+)+.*$/
          }
          

          addRule(rule)【返回值:Validform】

          可以通過Validform對象的這個方法來給表單元素綁定驗證規則,綁定驗證類型中列出的附加屬性都可以通過這個方法綁定。

          demo.addRule([
           {
           ele:"#name",
           datatype:"s6-18",
           ajaxurl:"valid.php",
           nullmsg:"請輸入昵稱!",
           errormsg:"昵稱至少6個字符,最多18個字符!"
           },
           {
           ele:"#userpassword",
           datatype:"*6-16",
           nullmsg:"請設置密碼!",
           errormsg:"密碼范圍在6~16位之間!"
           },
           {
           ele:"#userpassword2",
           datatype:"*",
           recheck:"userpassword",
           nullmsg:"請再輸入一次密碼!",
           errormsg:"您兩次輸入的賬號密碼不一致!"
           }
          ]);
          

          其中ele是指定要綁定規則的對象,會在Validform對象下查找這些對象。

          eq(n)【返回值:Validform】

          獲取Validform對象的第n個元素。

          如你頁面上有多個form的class都是formsub,執行上面的驗證綁定,得到的demo對象就可以操作所有這些表單,如果你要對其中某個表單執行某些操作,那么就可以使用這個方法。

          如demo.eq(0).resetForm(),重置第一個表單。

          ajaxPost(flag,sync,url)【返回值:Validform】

          以ajax方式提交表單。flag為true時,跳過驗證直接提交,sync為true時將以同步的方式進行ajax提交。

          參數url是5.3版新增,傳入了url地址時,表單會提交到這個地址

          如demo.ajaxPost(true),不做驗證直接ajax提交表單。

          abort()【返回值:Validform】

          終止ajax的提交。

          如執行上面的ajaxPost()之后,發現某些項填寫不對,想取消表單提交,那么就可以執行這個操作:demo.abort()

          submitForm(flag,url)【返回值:Validform】

          以初始化時傳入參數的設置方式提交表單,flag為true時,跳過驗證直接提交。

          參數url是5.3版新增,傳入了url地址時,表單會提交到這個地址

          如demo.submitForm(true),不做驗證直接提交表單。

          resetForm()【返回值:Validform】

          重置表單。

          如demo.resetForm(),重置表單到初始狀態。

          resetStatus()【返回值:Validform】

          重置表單的提交狀態。傳入了postonce參數的話,表單成功提交后狀態會設置為"posted",重置提交狀態可以讓表單繼續可以提交。

          如demo.resetStatus()

          getStatus()【返回值:String】

          獲取表單的提交狀態,normal:未提交,posting:正在提交,posted:已成功提交過。

          如demo.getStatus()

          setStatus(status)【返回值:Validform】

          設置表單的提交狀態,可以設置normal,posting,posted三種狀態,不傳參則設置狀態為posting,這個狀態表單可以驗證,但不能提交。

          如demo.setStatus("posted")

          ignore(selector)【返回值:Validform】

          忽略對所選擇對象的驗證,不傳入selector則忽略所有表單元素。

          如demo.ignore("select,textarea,#name"),忽略Validform對象下所有select,textarea及一個id為"name"元素的驗證。

          unignore(selector)【返回值:Validform】

          將ignore方法所忽略驗證的對象重新獲取驗證效果,不傳入selector則恢復驗證所有表單元素。

          如demo.unignore("select,textarea,#name"),恢復Validform對象下所有select,textarea及一個id為"name"元素的驗證。

          check(bool,selector)【返回值:Boolean】

          bool為true時則只驗證不顯示提示信息

          對指定對象進行驗證(默認驗證當前整個表單),通過返回true,否則返回false(綁定實時驗證的對象,格式符合要求時返回true,而不會等ajax的返回結果)

          如demo.check(),驗證當前整個表單,且只驗證但不顯示對錯信息。

          config(setup) 5.3+ 【返回值:Validform】

          setup參數是一個對象。

          JeeWeb是一款基于SpringBoot 2+Spring+Mybatis+Hibernate的敏捷開發系統;它是一款具有代碼生成功能的智能快速開發平臺;是以Spring Framework為核心容器,Spring MVC為模型視圖控制器,Hibernate為數據訪問層, Apache Shiro為權限授權層,Ehcahe對常用數據進行緩存,Disruptor作為并發框架,Bootstrap作為前端框架的優秀 開源 系統。

          JeeWeb是一款 全開源開發平臺 ,特別 代碼生成器模塊也采用開源模式 ,各位開發者可以根據自己的需要改造出更加適合自己的代碼生成器,不管是做項目、學習、接私活它都將是你的最佳拍檔;

          JeeWeb主要定位于企業快速開發平臺建設,已內置很多優秀的基礎功能和高效的 代碼生成 工具,包括:系統權限組件、數據權限組件、數據字典組件、核心工具組件、視圖操作組件、代碼生成、 UI模版標簽 庫等。前端界面風格采用了結構簡單、性能優良、頁面美觀大氣的Twitter Bootstrap頁面展示框架。采用分層設計、提交數據安全編碼、密碼加密、訪問驗證、數據權限驗證。使用Maven做項目管理,提高項目的易開發性、擴展性。

          目前功能模塊代碼生成器、權限框架、數據字典、數據緩存、并發框架、數據監控、計劃任務、多數據源管理、附件管理、類似mybatis動態SQL、UI模板標簽、短信發送、郵件發送、統計功能等功能。

          JeeWeb的開發方式采用( 代碼生成器快速設計生成代碼->手工完善邏輯->豐富模板標簽快速前端開發 ),可以快速協助java開發人員解決60%的重復工作,讓開發人員更多關注業務邏輯的實現,框架使用前端模板標簽,解放JAVA開發人員的開發壓力,提高開發效率,為企業節省項目研發成本,減少開發周期。

          后臺框架演示(支持兩種前端樣式自由切換)

          論壇演示

          前后端分離演示

          JeeWeb 技術特點

          JeeWeb使用目前流程的WEB開發架構技術,如 SpringBoot,Mybatis, Hibernate,Apache Shiro, Disruptor , ehcache, Jquery ,BootStrap等等,支持多種數據庫MySQL, Oracle, sqlserver等。 分層設計:使用分層設計,分為dao,service,Controller,view層,層次清楚,低耦合,高內聚。

          安全考慮:嚴格遵循了web安全的規范,前后臺雙重驗證,參數編碼傳輸,密碼md5加密存儲,shiro權限驗證,從根本上避免了SQL注入,XSS攻擊,CSRF攻擊等常見的web攻擊手段。

          JeeWeb 功能特點

          • SpringBoot+Spring+Mybatis+Hibernate+Shiro+ Ehcache+Disruptor+Jquery + Boostrap + Ztree等基礎前后端架構架構
          • 采用面向聲明的開發模式, 基于泛型編寫極少代碼即可實現復雜的數據展示、數據編輯、表單處理等功能,在不使用代碼生成器的情況下,也只需要很少的代碼就能實現基礎的CURD操作,再配合在線開發與代碼生成器的使用,更加加快了開發的進度,將J2EE的開發效率成本提高,可以將代碼減少60%以上。
          • 在線開發(通過在線配置實現一個表模型的增刪改查功能,無需一行代碼,支持用戶自定義表單布局)
          • 代碼生成器,支持多種數據模型,根據表生成對應的Entity,Service,Dao,Controller,JSP等,增刪改查功能生成直接使用
          • UI標簽開發庫,針對前端UI進行標準封裝表,頁面統一采用UI標簽實現功能:數據datagrid,treegrid,FileInput,Editor,GridSelect等,實現JSP頁面零JS,開發維護簡潔高效
          • 查詢過濾器:只需前端配置,后臺動態拼SQL追加查詢條件;支持多種匹配方式(全匹配/模糊查詢/包含查詢/不匹配查詢)
          • 移動平臺支持,對Bootstrap(兼容Html5)進行標準封裝
          • 靈活的權限控制,可控制到頁面或按鈕,滿足絕大部分的權限需求,優化權限注解方便權限配置
          • 完善的XSS防范及腳本過濾,徹底杜絕XSS攻擊
          • 支持分布式部署,session存儲在redis中
          • 友好的代碼結構及注釋,便于閱讀及二次開發
          • 引入quartz定時任務,可動態完成任務的添加、修改、刪除、暫停、恢復及日志查看等功能
          • 引入swagger文檔支持,方便編寫API接口文檔
          • 國際化(支持多語言,國際化的封裝為多語言做了便捷支持)
          • 多數據源(在線配置數據源,數據源工作類封裝)
          • 數據權限:整合Shiro權限
          • 計劃任務控制(在線配置計劃任務、方便計劃任務的時間調整規劃)
          • 郵件發送(配置郵件模版、郵件帳號的在線配置、郵件異步發送、郵件發送日志功能統計)
          • 短信發送(配置短信模版、短信帳號的在線配置、短信異步發送、短信發送日志功能統計、支持短信發送平臺動態切換)
          • 多種首頁風格切換,支持自定義首頁風格。(Inspinia風格|ACE風格)
          • 數據統計報表:豐富的報表統計功能
          • 支持多種瀏覽器: Google, 火狐, IE,360 等
          • 支持數據庫: Mysql,Oracle10g,SqlServer等
          • 基礎權限: 用戶,角色,菜單權限
          • Web容器測試通過的有Jetty和Tomcat,Weblogic
          • 要求JDK1.8+

          技術選型

          1、后端

          • 核心框架:Spring boot2.0、Spring Framework
          • 安全框架:Apache Shiro
          • 服務端驗證:Hibernate Validator
          • 模板標簽:Beetl
          • 任務調度:Quartz
          • 持久層框架:Hibernate
          • 數據庫連接池:Alibaba Druid
          • 緩存框架:Redis、Ehcache
          • 并發框架:Disruptor
          • 日志管理:SLF4J、Log4j
          • 工具類:Apache Commons、Jackson、Xstream、

          2、前端

          • JS框架:jQuery。
          • CSS框架:Twitter Bootstrap
          • 客戶端驗證:Validform。
          • 富文本在線編輯:markdown、simditor、Summernote、CodeMirror自由切換
          • 文件上傳工具:Bootstrap fileinput
          • 數據表格:jqGrid
          • 對話框:layer
          • 樹結構控件:jQuery zTree
          • 日期控件: datepicker
          • 代碼高亮: syntaxhighlighter

          簡單使用說明

          • 導入jeeweb目錄下的,具體模塊sql/mysql.sql文件到mysql數據庫
          • 導入項目到Idea,(項目目前使用分模塊開發,我們建議是用IDEA開發).
          • 修改數據庫配置文件application.yml中的賬號密碼.
          • 啟動項目,管理員賬號admin/密碼123456

          平臺目錄結構說明

          jeeweb
          ├─jeeweb-common 公共模塊
          │ ├─jeeweb-common-base 公用基礎模塊
          │ │ 
          │ ├─jeeweb-common-email 郵件基礎模塊
          │ │ 
          │ ├─jeeweb-common-hibernatemvc hibernate公用模塊
          │ │ 
          │ ├─jeeweb-common-mybatismvc mybatis公用模塊
          │ │ 
          │ ├─jeeweb-common-oss 數據存儲公用模塊
          │ │ 
          │ ├─jeeweb-common-quartz quartz公用模塊
          │ │ 
          │ ├─jeeweb-common-query 查詢封裝模塊
          │ │ 
          │ ├─jeeweb-common-security 安全公用模塊
          │ │ 
          │ ├─jeeweb-common-sms 短信公用模塊
          │ │ 
          │ └─jeeweb-common-utils 公用工具模塊
          │ 
          ├─jeeweb-ui UI模塊
          │ ├─jeeweb-beetl-tag 基于beetl的類似spring form的模板標簽
          │ │ 
          │ ├─jeeweb-ui-static 公用靜態資源模塊
          │ │ 
          │ └─jeeweb-ui-tag 基于靜態資源模塊的標簽
          │ 
          ├─jeeweb-web 業務模塊
          │ ├─jeeweb-admin 后臺案例模塊
          │ │ 
          │ ├─jeeweb-bbs Jeeweb官方論壇代碼模塊
          │ │ 
          │ ├─jeeweb-vue 前后端分離后端模塊
          │ │ 
          │ └─jeeweb-generator 代碼生成器模塊
          │
          

          代碼示例

          [1].GRID列表

          <#grid:grid id="onlineGrid" datatype="local" datas="${onlineSessionList}" sortname="startTimestamp" sortorder="desc">
           <#grid:column label="sys.common.key" hidden="true" name="id" width="100"/>
           <#grid:column label="用戶" name="username" />
           <#grid:column label="用戶主機IP" name="host" />
           <#grid:column label="系統主機IP" name="systemHost" />
           <#grid:column label="登錄時間" name="startTimestamp" width="140" queryMode="date" condition="between" />
           <#grid:column label="最后訪問時間" name="lastAccessTime" width="140"/>
           <#grid:column label="狀態" name="status" dict="onlinestatus" />
           <#grid:column label="User-Agent" name="userAgent" />
           <#grid:column label="用戶會話ID" name="id" />
           <#grid:toolbar title="強制退出" btnclass="btn-danger" icon="fa-trash-o" function="toolbarSelectConfirm" url="${adminPath}/sys/online/forceLogout" tipMsg="您確定要強制退出這些信息么,請謹慎操作!"/>
          </#grid:grid>
          

          [2].TREEGRID列表

          <#grid:grid id="organizationGrid" async="true" treeGrid="true" expandColumn="name" url="${adminPath}/sys/organization/ajaxTreeList">
          	<#grid:column label="sys.common.key" hidden="true" name="id" width="100"/>
          	<#grid:column label="sys.organization.name" name="name" query="true" condition="like" />
          	<#grid:column label="sys.organization.remarks" name="remarks" />
          	<#grid:column label="sys.common.opt" name="opt" formatter="button" width="100"/>
          	<#grid:button groupname="opt" function="delete" />
          	<#grid:toolbar function="add"/>
          	<#grid:toolbar function="update"/>
          	<#grid:toolbar function="delete"/>
          	<#grid:toolbar function="search"/>
          	<#grid:toolbar function="reset"/>
          </#grid:grid>
          

          [3].表單代碼

          <% layout('/layouts/form.html', {title: @MessageUtils.getMessage('sys.user.updateuser',''), formId: 'userForm', bodyClass: 'white-bg', libs: 'bootstrap-fileinput'}){ %>
          <#form:form id="userForm" modelAttribute="data" method="post" class="form-horizontal">
           <#form:hidden path="id" />
           <table class="table table-bordered table-condensed dataTables-example dataTable no-footer">
           <tbody>
           <tr>
           <td class="width-15 active text-right">
           <label>用戶名:</label></td>
           <td class="width-35">${data.username}</td>
           <td class="width-15 active text-right">
           <label>
           <font color="red">*</font>姓名:</label></td>
           <td class="width-35">
           <#form:input path="realname" class="form-control " datatype="*" nullmsg="請輸入姓名!" htmlEscape="false" />
           <label class="Validform_checktip"></label>
           </td>
           </tr>
           <tr>
           <td class="width-15 active text-right">
           <label>
           <font color="red">*</font>郵箱:</label></td>
           <td class="width-35">
           <#form:input path="email" class="form-control" datatype="e" nullmsg="請輸入姓名!" htmlEscape="false" />
           <label class="Validform_checktip"></label>
           </td>
           <td class="width-15 active text-right">
           <label>
           <font color="red">*</font>聯系電話:</label></td>
           <td class="width-35">
           <#form:input path="phone" class="form-control" htmlEscape="false" datatype="m" nullmsg="請輸入用戶名!" />
           <label class="Validform_checktip"></label>
           </td>
           </tr>
           <tr>
           <td class="active">
           <label class="pull-right">
           <font color="red">*</font>用戶角色:</label></td>
           <td colspan="3">
           <#form:checkboxes path="roleIdList" nested="false" items="${allRoles}" defaultValue="${roleIdList}" itemLabel="name" itemValue="id" htmlEscape="false" cssClass="i-checks required" /></td>
           </tr>
           <tr>
           <td class="width-15 active">
           <label class="pull-right">組織機構:</label></td>
           <td colspan="3">
           <#form:treeselect title="請選擇組織機構" path="organizationIds" nested="false" dataUrl="${adminPath}/sys/organization/treeData" chkboxType="" labelName="parentname" labelValue="${organizationNames}" multiselect="true" /></td>
           </tr>
           </tbody>
           </table>
          </#form:form>
          <% } %>
          

          git地址:https://gitee.com/dataact/jeeweb


          主站蜘蛛池模板: 精品国产一区二区三区久久影院 | A国产一区二区免费入口| 日本精品少妇一区二区三区| 在线不卡一区二区三区日韩| 久久精品国产第一区二区| 亚洲午夜福利AV一区二区无码| 国产午夜精品一区二区三区 | 无码喷水一区二区浪潮AV| 久久精品国产一区二区三区肥胖| 国产一区二区三区福利| 国产亚洲无线码一区二区| 国产丝袜无码一区二区视频| 91精品一区二区三区久久久久| 91久久精一区二区三区大全| 无码人妻精品一区二区蜜桃百度 | 久久亚洲中文字幕精品一区四 | 日本免费一区二区在线观看| 日韩一区在线视频| 毛片一区二区三区无码| 国产免费一区二区三区| 国产视频一区在线观看| 动漫精品专区一区二区三区不卡| 亚洲国产精品无码第一区二区三区| 一区二区免费视频| 亚洲一区二区三区四区视频| 亚洲va乱码一区二区三区| 久久久精品人妻一区亚美研究所| 久久精品一区二区| 日韩在线一区二区| 国产精品无码一区二区三区不卡| 精品福利一区二区三区免费视频 | 亚洲视频免费一区| 末成年女AV片一区二区| 激情无码亚洲一区二区三区| 国产精品亚洲一区二区无码| 无码人妻精品一区二区三区不卡| 成人久久精品一区二区三区| 一区二区三区视频观看| 国产精品日本一区二区在线播放| 麻豆AV无码精品一区二区| 国产婷婷一区二区三区|