代理(Proxy)

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

一、代理的概念

  動態代理技術是整個java技術中最重要的一個技術,它是學習java框架的基礎,不會動態代理技術,那么在學習Spring這些框架時是學不明白的。

  動態代理技術就是用來產生一個對象的代理對象的。在開發中為什么需要為一個對象產生代理對象呢?
  舉一個現實生活中的例子:歌星或者明星都有一個自己的經紀人,這個經紀人就是他們的代理人,當我們需要找明星表演時,不能直接找到該明星,只能是找明星的代理人。比如劉德華在現實生活中非常有名,會唱歌,會跳舞,會拍戲,劉德華在沒有出名之前,我們可以直接找他唱歌,跳舞,拍戲,劉德華出名之后,他干的第一件事就是找一個經紀人,這個經紀人就是劉德華的代理人(代理),當我們需要找劉德華表演時,不能直接找到劉德華了(劉德華說,你找我代理人商談具體事宜吧!),只能是找劉德華的代理人,因此劉德華這個代理人存在的價值就是攔截我們對劉德華的直接訪問!
  這個現實中的例子和我們在開發中是一樣的,我們在開發中之所以要產生一個對象的代理對象,主要用于攔截對真實業務對象的訪問。那么代理對象應該具有什么方法呢?代理對象應該具有和目標對象相同的方法

  所以在這里明確代理對象的兩個概念:
    1、代理對象存在的價值主要用于攔截對真實業務對象的訪問
    2、代理對象應該具有和目標對象(真實業務對象)相同的方法。劉德華(真實業務對象)會唱歌,會跳舞,會拍戲,我們現在不能直接找他唱歌,跳舞,拍戲了,只能找他的代理人(代理對象)唱歌,跳舞,拍戲,一個人要想成為劉德華的代理人,那么他必須具有和劉德華一樣的行為(會唱歌,會跳舞,會拍戲),劉德華有什么方法,他(代理人)就要有什么方法,我們找劉德華的代理人唱歌,跳舞,拍戲,但是代理人不是真的懂得唱歌,跳舞,拍戲的,真正懂得唱歌,跳舞,拍戲的是劉德華,在現實中的例子就是我們要找劉德華唱歌,跳舞,拍戲,那么只能先找他的經紀人,交錢給他的經紀人,然后經紀人再讓劉德華去唱歌,跳舞,拍戲。

二、java中的代理

2.1、"java.lang.reflect.Proxy"類介紹

  現在要生成某一個對象的代理對象,這個代理對象通常也要編寫一個類來生成,所以首先要編寫用于生成代理對象的類。在java中如何用程序去生成一個對象的代理對象呢,java在JDK1.5之后提供了一個"java.lang.reflect.Proxy"類,通過"Proxy"類提供的一個newProxyInstance方法用來創建一個對象的代理對象,如下所示:

1?static?Object?newProxyInstance(ClassLoader?loader,?Class<?>[]?interfaces,?InvocationHandler?h)

  newProxyInstance方法用來返回一個代理對象,這個方法總共有3個參數,ClassLoader loader用來指明生成代理對象使用哪個類裝載器,Class<?>[] interfaces用來指明生成哪個對象的代理對象,通過接口指定,InvocationHandler h用來指明產生的這個代理對象要做什么事情。所以我們只需要調用newProxyInstance方法就可以得到某一個對象的代理對象了。

2.2、編寫生成代理對象的類

  在java中規定,要想產生一個對象的代理對象,那么這個對象必須要有一個接口,所以我們第一步就是設計這個對象的接口,在接口中定義這個對象所具有的行為(方法)

  1、定義對象的行為接口

package?cn.gacl.proxy;/**
*?@ClassName:?Person
*?@Description:?定義對象的行為
*?@author:?孤傲蒼狼
*?@date:?2014-9-14?下午9:44:22
*
*/?
public?interface?Person?{/***?@Method:?sing*?@Description:?唱歌*?@Anthor:孤傲蒼狼**?@param?name*?@return*/?String?sing(String?name);/***?@Method:?sing*?@Description:?跳舞*?@Anthor:孤傲蒼狼**?@param?name*?@return*/?String?dance(String?name);
}

  2、定義目標業務對象類

package?cn.gacl.proxy;/**
*?@ClassName:?LiuDeHua
*?@Description:?劉德華實現Person接口,那么劉德華會唱歌和跳舞了
*?@author:?孤傲蒼狼
*?@date:?2014-9-14?下午9:22:24
*
*/?
public?class?LiuDeHua?implements?Person?{public?String?sing(String?name){System.out.println("劉德華唱"+name+"歌!!");return?"歌唱完了,謝謝大家!";}public?String?dance(String?name){System.out.println("劉德華跳"+name+"舞!!");return?"舞跳完了,多謝各位觀眾!";}
}

  3、創建生成代理對象的代理類

package?cn.gacl.proxy;import?java.lang.reflect.InvocationHandler;
import?java.lang.reflect.Method;
import?java.lang.reflect.Proxy;/**
*?@ClassName:?LiuDeHuaProxy
*?@Description:?這個代理類負責生成劉德華的代理人
*?@author:?孤傲蒼狼
*?@date:?2014-9-14?下午9:50:02
*
*/?
public?class?LiuDeHuaProxy?{//設計一個類變量記住代理類要代理的目標對象private?Person?ldh?=?new?LiuDeHua();/***?設計一個方法生成代理對象*?@Method:?getProxy*?@Description:?這個方法返回劉德華的代理對象:Person?person?=?LiuDeHuaProxy.getProxy();//得到一個代理對象*?@Anthor:孤傲蒼狼**?@return?某個對象的代理對象*/?public?Person?getProxy()?{//使用Proxy.newProxyInstance(ClassLoader?loader,?Class<?>[]?interfaces,?InvocationHandler?h)返回某個對象的代理對象return?(Person)?Proxy.newProxyInstance(LiuDeHuaProxy.class.getClassLoader(),?ldh.getClass().getInterfaces(),new?InvocationHandler()?{/***?InvocationHandler接口只定義了一個invoke方法,因此對于這樣的接口,我們不用單獨去定義一個類來實現該接口,*?而是直接使用一個匿名內部類來實現該接口,new?InvocationHandler()?{}就是針對InvocationHandler接口的匿名實現類*//***?在invoke方法編碼指定返回的代理對象干的工作*?proxy?:?把代理對象自己傳遞進來?*?method:把代理對象當前調用的方法傳遞進來?*?args:把方法參數傳遞進來*?*?當調用代理對象的person.sing("冰雨");或者?person.dance("江南style");方法時,*?實際上執行的都是invoke方法里面的代碼,*?因此我們可以在invoke方法中使用method.getName()就可以知道當前調用的是代理對象的哪個方法*/@Overridepublic?Object?invoke(Object?proxy,?Method?method,Object[]?args)?throws?Throwable?{//如果調用的是代理對象的sing方法if?(method.getName().equals("sing"))?{System.out.println("我是他的經紀人,要找他唱歌得先給十萬塊錢!!");//已經給錢了,經紀人自己不會唱歌,就只能找劉德華去唱歌!return?method.invoke(ldh,?args);?//代理對象調用真實目標對象的sing方法去處理用戶請求}//如果調用的是代理對象的dance方法if?(method.getName().equals("dance"))?{System.out.println("我是他的經紀人,要找他跳舞得先給二十萬塊錢!!");//已經給錢了,經紀人自己不會唱歌,就只能找劉德華去跳舞!return?method.invoke(ldh,?args);//代理對象調用真實目標對象的dance方法去處理用戶請求}return?null;}});}
}

  測試代碼:

package?cn.gacl.proxy;public?class?ProxyTest?{public?static?void?main(String[]?args)?{LiuDeHuaProxy?proxy?=?new?LiuDeHuaProxy();//獲得代理對象Person?p?=?proxy.getProxy();//調用代理對象的sing方法String?retValue?=?p.sing("冰雨");System.out.println(retValue);//調用代理對象的dance方法String?value?=?p.dance("江南style");System.out.println(value);}
}

  運行結果如下:

  105856_qNQj_1169289.png  

? ? ? Proxy類負責創建代理對象時,如果指定了handler(處理器),那么不管用戶調用代理對象的什么方法,該方法都是調用處理器的invoke方法。
  由于invoke方法被調用需要三個參數:代理對象、方法、方法的參數,因此不管代理對象哪個方法調用處理器的invoke方法,都必須把自己所在的對象、自己(調用invoke方法的方法)、方法的參數傳遞進來。

三、動態代理應用

  在動態代理技術里,由于不管用戶調用代理對象的什么方法,都是調用開發人員編寫的處理器的invoke方法(這相當于invoke方法攔截到了代理對象的方法調用)。并且,開發人員通過invoke方法的參數,還可以在攔截的同時,知道用戶調用的是什么方法,因此利用這兩個特性,就可以實現一些特殊需求,例如:攔截用戶的訪問請求,以檢查用戶是否有訪問權限、動態為某個對象添加額外的功能。

3.1、在字符過濾器中使用動態代理解決中文亂碼

  在平時的JavaWeb項目開發中,我們一般會寫一個CharacterEncodingFilter(字符過濾器)來解決整個JavaWeb應用的中文亂碼問題,如下所示:

package?me.gacl.web.filter;import?java.io.IOException;import?javax.servlet.Filter;
import?javax.servlet.FilterChain;
import?javax.servlet.FilterConfig;
import?javax.servlet.ServletException;
import?javax.servlet.ServletRequest;
import?javax.servlet.ServletResponse;/**
*?@ClassName:?CharacterEncodingFilter
*?@Description:?解決中文亂碼的字符過濾器
*?@author:?孤傲蒼狼
*?@date:?2014-9-14?下午10:38:12
*
*/?
public?class?CharacterEncodingFilter?implements?Filter?{@Overridepublic?void?init(FilterConfig?filterConfig)?throws?ServletException?{}@Overridepublic?void?doFilter(ServletRequest?request,?ServletResponse?response,FilterChain?chain)?throws?IOException,?ServletException?{//解決以Post方式提交的中文亂碼問題request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");chain.doFilter(request,?response);}@Overridepublic?void?destroy()?{}
}

  但是這種寫法是沒有辦法解決以get方式提交中文參數時的亂碼問題的,我們可以用如下的代碼來證明上述的解決中文亂碼過濾器只對以post方式提交中文參數時有效,而對于以get方式提交中文參數時無效

  jsp測試頁面如下:

<%@?page?language="java"?pageEncoding="UTF-8"%>
<%--引入jstl標簽庫?--%>
<%@taglib?uri="http://java.sun.com/jsp/jstl/core"?prefix="c"%>
<!DOCTYPE?HTML>
<html><head><title>使用字符過濾器解決解決get、post請求方式下的中文亂碼問題</title></head><body><%--使用c:url標簽構建url,構建好的url存儲在servletDemo1變量中--%><c:url?value="/servlet/ServletDemo1"?scope="page"?var="servletDemo1"><%--構建的url的附帶的中文參數?,參數名是:username,值是:孤傲蒼狼--%><c:param?name="username"?value="孤傲蒼狼"></c:param></c:url><%--使用get的方式訪問?--%><a?href="${servletDemo1}">超鏈接(get方式請求)</a><hr/><%--使用post方式提交表單?--%><form?action="${pageContext.request.contextPath}/servlet/ServletDemo1"?method="post">用戶名:<input?type="text"?name="username"?value="孤傲蒼狼"?/><input?type="submit"?value="post方式提交"></form></body>
</html>

  處理請求的ServletDemo1代碼如下:

package?me.gacl.web.controller;import?java.io.IOException;
import?java.io.PrintWriter;import?javax.servlet.ServletException;
import?javax.servlet.http.HttpServlet;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;public?class?ServletDemo1?extends?HttpServlet?{public?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)throws?ServletException,?IOException?{//?接收參數String?username?=?request.getParameter("username");//?獲取請求方式String?method?=?request.getMethod();//?獲取輸出流PrintWriter?out?=?response.getWriter();out.write("請求的方式:"?+?method);out.write("<br/>");out.write("接收到的參數:"?+?username);}public?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)throws?ServletException,?IOException?{doGet(request,?response);}
}

  在web.xml中注冊上述的CharacterEncodingFilter和ServletDemo1

<filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>me.gacl.web.filter.CharacterEncodingFilter</filter-class></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><servlet><servlet-name>ServletDemo1</servlet-name><servlet-class>me.gacl.web.controller.ServletDemo1</servlet-class></servlet><servlet-mapping><servlet-name>ServletDemo1</servlet-name><url-pattern>/servlet/ServletDemo1</url-pattern></servlet-mapping>

  測試結果如下所示:

  

  從運行結果可以看出,上述的過濾器的確是不能解決以get方式提交中文參數的亂碼問題,下面使用動態代理技術改造上述的過濾器,使之能夠解決以get方式提交中文參數的亂碼問題,改造后的過濾器代碼如下:

package?me.gacl.web.filter;import?java.io.IOException;
import?java.lang.reflect.InvocationHandler;
import?java.lang.reflect.Method;
import?java.lang.reflect.Proxy;import?javax.servlet.Filter;
import?javax.servlet.FilterChain;
import?javax.servlet.FilterConfig;
import?javax.servlet.ServletException;
import?javax.servlet.ServletRequest;
import?javax.servlet.ServletResponse;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;/**
*?@ClassName:?CharacterEncodingFilter
*?@Description:?解決中文亂碼的字符過濾器
*?@author:?孤傲蒼狼
*?@date:?2014-9-14?下午10:38:12
*
*/?
public?class?CharacterEncodingFilter?implements?Filter?{@Overridepublic?void?init(FilterConfig?filterConfig)?throws?ServletException?{}@Overridepublic?void?doFilter(ServletRequest?req,?ServletResponse?resp,FilterChain?chain)?throws?IOException,?ServletException?{final?HttpServletRequest?request?=?(HttpServletRequest)?req;HttpServletResponse?response?=?(HttpServletResponse)?resp;//解決以Post方式提交的中文亂碼問題request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");//獲取獲取HttpServletRequest對象的代理對象ServletRequest?requestProxy?=?getHttpServletRequestProxy(request);/***?傳入代理對象requestProxy給doFilter方法,*?這樣用戶在使用request對象時實際上使用的是HttpServletRequest對象的代理對象requestProxy*/chain.doFilter(requestProxy,?response);}/***?@Method:?getHttpServletRequestProxy*?@Description:?獲取HttpServletRequest對象的代理對象*?@Anthor:孤傲蒼狼**?@param?request*?@return?HttpServletRequest對象的代理對象*/?private?ServletRequest?getHttpServletRequestProxy(final?HttpServletRequest?request){ServletRequest?proxy??=?(ServletRequest)?Proxy.newProxyInstance(CharacterEncodingFilter.class.getClassLoader(),request.getClass().getInterfaces(),new?InvocationHandler(){@Overridepublic?Object?invoke(Object?proxy,?Method?method,?Object[]?args)throws?Throwable?{//如果請求方式是get并且調用的是getParameter方法if?(request.getMethod().equalsIgnoreCase("get")?&&?method.getName().equals("getParameter"))?{//調用getParameter方法獲取參數的值String?value?=?(String)?method.invoke(request,?args);if(value==null){return?null;}//解決以get方式提交的中文亂碼問題return?new?String(value.getBytes("iso8859-1"),"UTF-8");}else?{//直接調用相應的方法進行處理return?method.invoke(request,?args);}}});//返回HttpServletRequest對象的代理對象return?proxy;}@Overridepublic?void?destroy()?{}
}

  我們在過濾器中使用動態代理技術生成一個HttpServletRequest對象的代理對象requestProxy,然后把代理對象requestProxy進行chain.doFilter(requestProxy, response)傳遞給用戶使用,這樣用戶實際上使用的就是HttpServletRequest對象的代理對象requestProxy。然而這一過程對于用戶來說是透明的,用戶是不知道自己使用的HttpServletRequest對象是一個代理對象requestProxy,由于代理對象requestProxy和目標對象HttpServletRequest具有相同的方法,當用戶調用getParameter方法接收中文參數時,實際上調用的就是代理對象requestProxy的invoke方法,因此我們就可以在invoke方法中就判斷當前的請求方式以及用戶正在調用的方法,如果判斷當前的請求方式是get方式并且用戶正在調用的是getParameter方法,那么我們就可以手動處理get方式提交中文參數的中文亂碼問題了。

  測試結果如下所示:

  

?3.2、在字符過濾器中使用動態代理壓縮服務器響應的內容后再輸出到客戶端

  壓縮過濾器的代碼如下:

package?me.gacl.web.filter;import?java.io.ByteArrayOutputStream;
import?java.io.IOException;
import?java.io.OutputStreamWriter;
import?java.io.PrintWriter;
import?java.lang.reflect.InvocationHandler;
import?java.lang.reflect.Method;
import?java.lang.reflect.Proxy;
import?java.util.zip.GZIPOutputStream;import?javax.servlet.Filter;
import?javax.servlet.FilterChain;
import?javax.servlet.FilterConfig;
import?javax.servlet.ServletException;
import?javax.servlet.ServletOutputStream;
import?javax.servlet.ServletRequest;
import?javax.servlet.ServletResponse;
import?javax.servlet.http.HttpServletRequest;
import?javax.servlet.http.HttpServletResponse;/**
*?@ClassName:?GzipFilter
*?@Description:?壓縮過濾器,將web應用中的文本都經過壓縮后再輸出到瀏覽器
*?@author:?孤傲蒼狼
*?@date:?2014-9-15?下午9:35:36
*
*/?
public?class?GzipFilter?implements?Filter?{@Overridepublic?void?init(FilterConfig?filterConfig)?throws?ServletException?{}@Overridepublic?void?doFilter(ServletRequest?req,?ServletResponse?resp,FilterChain?chain)?throws?IOException,?ServletException?{final?HttpServletRequest?request?=?(HttpServletRequest)?req;final?HttpServletResponse?response?=?(HttpServletResponse)?resp;final?ByteArrayOutputStream?bout?=?new?ByteArrayOutputStream();final?PrintWriter?pw?=?new?PrintWriter(new?OutputStreamWriter(bout,"UTF-8"));chain.doFilter(request,?getHttpServletResponseProxy(response,?bout,?pw));pw.close();//拿到目標資源的輸出byte?result[]?=?bout.toByteArray();System.out.println("原始大小:"?+?result.length);ByteArrayOutputStream?bout2?=?new?ByteArrayOutputStream();GZIPOutputStream?gout?=?new?GZIPOutputStream(bout2);gout.write(result);gout.close();//拿到目標資源輸出的壓縮數據byte?gzip[]?=?bout2.toByteArray();System.out.println("壓縮大小:"?+?gzip.length);response.setHeader("content-encoding",?"gzip");response.setContentLength(gzip.length);response.getOutputStream().write(gzip);}/***?@Method:?getHttpServletResponseProxy*?@Description:?獲取HttpServletResponse對象的代理對象*?@Anthor:孤傲蒼狼**?@param?response*?@param?bout*?@param?pw*?@return?HttpServletResponse對象的代理對象*/?private?ServletResponse?getHttpServletResponseProxy(final?HttpServletResponse?response,final?ByteArrayOutputStream?bout,?final?PrintWriter?pw)?{return?(ServletResponse)?Proxy.newProxyInstance(GzipFilter.class.getClassLoader(),?response.getClass().getInterfaces(),?new?InvocationHandler(){@Overridepublic?Object?invoke(Object?proxy,?Method?method,?Object[]?args)throws?Throwable?{if(method.getName().equals("getWriter")){return?pw;?}else?if(method.getName().equals("getOutputStream")){return?new?MyServletOutputStream(bout);}else{return?method.invoke(response,?args);}}});}@Overridepublic?void?destroy()?{}class?MyServletOutputStream?extends?ServletOutputStream{private?ByteArrayOutputStream??bout?=?null;public?MyServletOutputStream(ByteArrayOutputStream??bout){this.bout?=?bout;}@Overridepublic?void?write(int?b)?throws?IOException?{bout.write(b);}}
}

  在web.xml中注冊上述的GzipFilter

<filter><description>配置壓縮過濾器</description><filter-name>GzipFilter</filter-name><filter-class>me.gacl.web.filter.GzipFilter</filter-class></filter><!--jsp文件的輸出的內容都經過壓縮過濾器壓縮后才輸出?--><filter-mapping><filter-name>GzipFilter</filter-name><url-pattern>*.jsp</url-pattern><!--?配置過濾器的攔截方式--><!--?對于在Servlet中通過request.getRequestDispatcher("jsp頁面路徑").forward(request,?response)?方式訪問的Jsp頁面的要進行攔截?--><dispatcher>FORWARD</dispatcher><!--對于直接以URL方式訪問的jsp頁面進行攔截,過濾器的攔截方式默認就是REQUEST--><dispatcher>REQUEST</dispatcher></filter-mapping><!--js文件的輸出的內容都經過壓縮過濾器壓縮后才輸出?--><filter-mapping><filter-name>GzipFilter</filter-name><url-pattern>*.js</url-pattern></filter-mapping><!--css文件的輸出的內容都經過壓縮過濾器壓縮后才輸出?--><filter-mapping><filter-name>GzipFilter</filter-name><url-pattern>*.css</url-pattern></filter-mapping><!--html文件的輸出的內容都經過壓縮過濾器壓縮后才輸出?--><filter-mapping><filter-name>GzipFilter</filter-name><url-pattern>*.html</url-pattern></filter-mapping>

  GzipFilter過濾器會將*.jsp,*.js,*.css,*.html這些文件里面的文本內容都經過壓縮后再輸出到客戶端顯示。

轉載于:https://my.oschina.net/HerrySun/blog/656559

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/285126.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285126.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285126.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【ArcGIS微課1000例】0006:創建隨機點(Create Random Points)

問題描述 在一個給定的范圍內,根據隨機位置,生成指定數量的隨機點。生成的隨機點通常用來提取每個點對應的NDVI,高程,氣溫等值。 ArcGIS創建隨機點 創建指定數量的隨機點要素。可以在范圍窗口中、面要素內、點要素上或線要素沿線生成隨機點。 工具介紹:

C語言試題163之計算某一天是對應年的第幾天,這一年一共多少天;計算兩個日期之間相隔的天數。兩個日期由鍵盤輸入。

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:計算某一…

[轉]《吐血整理》系列-頂級程序員工具集

你知道的越多&#xff0c;你不知道的越多 點贊再看&#xff0c;養成習慣 GitHub上已經開源 https://github.com/JavaFamily 有一線大廠面試點腦圖、個人聯系方式&#xff0c;歡迎Star和指教 前言 這期是被人才群交流里&#xff0c;還有很多之前網友評論強行頂出來的一期&#x…

跟我做?個高德地圖的 iOS / Android MAUI 控件(前言)

Microsoft Build 2022 ?會上正式發布了 .NET MAUI , 對于 .NET 開發者可以? C# 完成跨平臺的前端應?開發。對?起 MAUI 的前身 Xamarin , MAUI 除了可以?傳統的原?開發模式外&#xff0c;還?持了 Blazor 的混合式開發。這也讓更多?向的開發?員能進?到跨平臺的應?開發…

Valid Number

Valid Number 題解 題目描述 即判斷某個字符串是否合法的數字表達式。如&#xff1a; 2e10&#xff0c;合法。 75.0.&#xff0c;非法。 0e&#xff0c;非法。 0.1 &#xff0c;合法。題解 基于規則與狀態判斷。可利用二維數組模擬狀態轉移圖&#xff0c;又或是利用變量記錄狀…

java.util.ListIterator

列表迭代器并不持有當前元素的引用&#xff0c;其持有的游標是位于列表連個元素之間。可以通過調用next()或者previous()返回列表中的元素。一個擁有n個元素的列表擁有n1個游標位置&#xff0c;示意圖如下&#xff1a; 注意&#xff1a;remove和 set(Object)方法并不是以迭代器…

保姆級C語言版高斯坐標正算反算傾情奉獻!

文章目錄 正反算原理速遞C語言正反算實現坐標正算坐標反算擴展閱讀: 【小程序】坐標正算神器V1.0(附C/C#/VB源程序) 測量人看過來:多種語言編寫的測量坐標反算神器附源碼(C#/VB) 正反算原理速遞 已知邊長和方位角,由已知點計算待定點的坐標,稱為坐標正算。已知兩點坐標…

C語言試題164之求定積分

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:利用梯形…

我的jekyll配置和修改

主要記錄使用jekyll搭建博客時的一些配置和修改。 注意&#xff1a; >使用時請刪除{和%以及{和{之間的空格。 預覽文章 source ~/.bash_profile jekyll server添加about me 邊欄 參考the5fire的技術博客在index.html頁面加入如下代碼&#xff1a; <section> <h4>…

[轉]白話阿里巴巴Java開發手冊高級篇

不久前&#xff0c;阿里巴巴發布了《阿里巴巴Java開發手冊》&#xff0c;總結了阿里巴巴內部實際項目開發過程中開發人員應該遵守的研發流程規范&#xff0c;這些流程規范在一定程度上能夠保證最終的項目交付質量&#xff0c;通過在時間中總結模式&#xff0c;并推廣給廣大開發…

C語言試題165之求三色旗問題

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:有一根繩…

spring boot微服務通用部署啟動腳本

2019獨角獸企業重金招聘Python工程師標準>>> 通用springboot微服務啟動、停止腳本。 #!/bin/bash # # chkconfig: - 20 80 # description: Starts and stops the App. # author:vakingeENVdev RUNNING_USERvakinge ADATEdate %Y%m%d%H%M%S APP_NAMEpassport-serve…

day10 多媒體(文字 圖片 音頻 視頻)

1計算機表示圖形的幾種方式bmp:以高質量保存 用于計算機jpg:以良好的質量保存 用于計算機或者網絡png:以高質量保存圖片大小的計算公式&#xff1a;圖片的總像素*每個像素的大小 (多出的一點是圖片的信息)單色&#xff1a;每個像素最多可以表示2種顏色 要么是黑要么是…

VB實現6大排序算法---動態過程展示(建議收藏)

VB實現6大排序算法&#xff1a;插入排序、基數排序、快速排序、希爾排序、選擇排序、歸并排序。可以隨機生成指定個數的數據&#xff0c;顯示排序過程&#xff0c;給出排序結果&#xff0c;計算排序算法消耗的時間。 生成隨機數&#xff1a; 排序結果&#xff1a; 插入排序&…

C# 實現 Actor并發模型 (案例版)

啥是Actor模型Actor (英語翻譯 演員) 這個概念要回溯到面向對象程序設計的本身上來&#xff0c;更偏向于現實世界&#xff0c;現實世界就是由單個個體&#xff08;人&#xff09;與其他個體或(人&#xff09;通訊&#xff08;消息&#xff09;組成的現實世界&#xff0c;所以&a…

oracle--number

1. oracle的number類型是oracle的內置類型之一&#xff0c;是oracle的最基礎數值數據類型。在9iR2及其以前的版本中只支持一種適合存儲數值數據的固有數據類型&#xff0c;在10g以后&#xff0c;才出現了兩種新的數值類型&#xff0c;即推出本地浮點數據類型(Native Floating-P…

超詳細C語言版數據結構:圖的深度優先遍歷(推薦收藏)

文章目錄一、鄰接矩陣存儲圖的深度優先遍歷過程分析二、結果分析三、C語言編程實現圖的深度優先遍歷四、圖的遍歷及其應用一、鄰接矩陣存儲圖的深度優先遍歷過程分析 對圖1這樣的無向圖&#xff0c;要寫成鄰接矩陣&#xff0c;則就是下面的式子&#xff1a; 一般要計算這樣的問…

Navicat Premium 64 bit 12.1.25

Navicat Premium可讓你以單一程序同時連接到 MySQL、MariaDB、SQL Server、SQLite、Oracle 和 PostgreSQL 數據庫&#xff0c;是一個可多重連接的數據庫管理工具&#xff0c;它讓管理不同類型的數據庫更加方便。 官方下載地址&#xff1a;https://www.navicat.com.cn/download/…

C語言試題166之整數逆序輸出

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款刷算法、筆試、面經、拿大公司offer神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:將一個從…

[JMX一步步來] 7、用JDK5.0的JConsole來連接MBean

前面所有看效果都是通過Html網頁來看的。JDK5.0自帶了一個jmx客戶端&#xff0c;叫jconsole&#xff0c;位于c:\jdk\bin\jconsole.exe。我們來用用這個客戶端來連接Mbean Server。一、vm參數方式1、還是用第一篇的那個HelloAgent&#xff0c;修改HelloAgent&#xff0c;將第一句…