精华内容
下载资源
问答
  • 代理人与相对人的关系
    千次阅读
    2016-05-19 11:11:34

    机票代理人Shoppping指令区别AV,AV指令只能查询4折以上的机票,而Shoppping可以查询所有折扣机票,所以现在把c#编写的Shoppping共享!


    以post请求参数

    String org;//出发地

    String dst;目的地

    String orgdate;出发日期

    Strin DirectFlightOnly;//是否直达,传true时只能查直达的航班,传false时查询中转航班

    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Com.Travelsky.Ibe.Client;
    using Com.Travelsky.Util;
    using Com.Travelsky.Ibe.Exceptions;
    using System.Web.Script.Serialization;
    using System.Diagnostics;
    using Com.Travelsky.Ibe.Client.Pnr;
    using Com.Travelsky.Ebuild.Clientapi.FlightShoppping;
    using System.Collections;
    using System.Text;
    using System.Globalization;
    using Newtonsoft.Json;
    
    public partial class AV1 : System.Web.UI.Page
    {
    
        public string FFDprice = "";//所有定义价格返回字符串
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                    FlightShoppping fltshopping = new FlightShoppping();
    
                    FareInterface service = new FareInterface();
                    Input input = new Input();
                    input.SetHeaderInType(getHeaderInType());
    
    
                    Request request = new Request();
                    FlightShopRequestType flightShopRequestType = new FlightShopRequestType();
                    //设置OD
    
                    ArrayList originDestinationInfo = new ArrayList();
                    originDestinationInfo.Add(getOriginDestinationInfoType());
                    flightShopRequestType.SetOriginDestinationInfo(originDestinationInfo);
                    //设置AVJourney
                    //ArrayList AVJ = new ArrayList();
                    //AVJ.Add(getAvJourneys(input));
                    //flightShopRequestType.SetAvJourneys(AVJ);
                    //设置TravelPreferences
                    flightShopRequestType.SetTravelPreferencesType(getTravelPreferencesType());
                    //设置Option
                    flightShopRequestType.SetOption(getOption());
                    /*//设置AdditionalShopRQData
                    flightShopRequestType.setAdditionalShopRQData(getAdditionalShopRQData());*/
    
    
                    request.SetFlightShopRequestType(flightShopRequestType);
                    input.SetRequest(request);
                    service.SetInput(input);
    
                    //long begin = System.currentTimeMillis();
                    //Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
                    //stopwatch.Start(); //  开始监视代码
    
                    Output outT = new Output();
                    outT = fltshopping.DoFlightShopping(service);//查询国内Shopping
                    //System.out.println(out);
                    FFDprice = StringBuildera(outT);//给所有航空公司返回价格附值
                    //CwJgInfo(FFDprice);
                    //Response.Write(FFDprice);
                    PrintResult(outT);
    
                    //Response.Write(StringBuildera(outT));
    
    
                    //stopwatch.Stop(); //  停止监视
                    //long Milliseconds = stopwatch.ElapsedMilliseconds; //  获取总时间
                    //Response.Write(Milliseconds.ToString());
            }
            catch (IBEException ex)
            {
                Response.Write("callbackfun({ result:\"" + ex.Message.ToString() + "\"})");
            }
        }
        public static HeaderInType getHeaderInType()
        {
            HeaderInType hi = new HeaderInType();
            hi.SetSysCode("CRS");//ICS或者CRS
            //hi.SetSysType("IBE");//接入系统类型。如BLUESKY/IBE/TRAVELWEB。
            hi.SetChannelID("1E");//CAET或者1E
            //hi.SetChannelType("B2C");//B2B或者B2C,渠道设置为 1E 下不能设置,非 1E 时根据具体情况设置
            Agency agency = new Agency();
            agency.SetOfficeId("<span style="font-family: Arial, Helvetica, sans-serif;">BJS999</span><span style="font-family: Arial, Helvetica, sans-serif;">");//如:代理人office号,BJS999 BJS472</span>
            agency.SetPid("11066");//如:20200
            agency.SetCity("PEK");//代理人所在地区
            //agency.setIataNum("");
            //agency.setCountry("");
            hi.SetAgency(agency);
            hi.SetLanguage("CN");//EN或者CN
            hi.SetCommandType("FS");//
            return hi;
        }
        public static OriginDestinationInfoType getOriginDestinationInfoType()//去程类
        {
            string ori = HttpContext.Current.Request["org"];//起始地
            string des = HttpContext.Current.Request["dst"];//目的地
            string SetDepartureDate = HttpContext.Current.Request["orgdate"];//去程日期
            DateBinding db = new DateBinding();
            OriginDestinationInfoType od = new OriginDestinationInfoType();
            od.SetOri(ori.Trim());//起始地
            od.SetDes(des.Trim());//目的地
            od.SetDepartureDate(SetDepartureDate.Trim());//起始出发日期,格式为DDMMMYY
            return od;
        }
        public static Option getOption()
        {
            Option op = new Option();
            //op.SetFcFeature("0");//组合限制取值为0/1,默认值为0
            op.SetIsAvNeeded("Y");//结果中是否需要AV信息。Y/N,缺省为Y
            op.SetIsPSnNeeded("Y");//结果中是否需要PS信息。Y/N,缺省为Y
            //op.SetIsPsAvBindsNeeded("Y");//结果中是否需要PsAvBinding信息。Y/N,缺省为Y
            //op.SetIsFaresNeeded("Y");//结果中是否需要fare信息。Y/N,缺省为Y
            //op.SetIsRefundReissueRuleNeeded("Y");
            //op.SetIsRefundReissueTextRuleNeeded("Y");//需要文本退改签信息
            op.SetFormat("NOR");//SIM:简化格式;NOR:正常格式,缺省为NOR
            //op.SetIsCompressedResultNeeded("Y");//需要压缩结果;N 不需要不压缩
            string DirectFlightOnly = HttpContext.Current.Request["DirectFlightOnly"];//是否直达
            if (DirectFlightOnly.Trim() == "true")
            {
                op.SetLowestOrAll("A");//L:每个航班返回最低价; A:返回所有可用舱位价格。缺省为L
            }
            else
            {
                op.SetLowestOrAll("L");//L:每个航班返回最低价; A:返回所有可用舱位价格。缺省为L
            }
            //op.SetLowestOrAll("A");//L:每个航班返回最低价; A:返回所有可用舱位价格。缺省为L
            //op.SetRuleTypeNeeded("ALL");//ALL:需要所有文本规则;NON:不需要文本规则;SIM:只需要文本规则前两项缺省为ALL
            op.SetFareSource("ALL");//PUB-查公布价, YPUB-只查Y舱公布价, ALL-包括公布价和净价。缺省为ALL
            //op.SetIsSpecificClassAllPriceZvalueNeeded("Y");//setIsSpecificClassAllPriceZvalueNeeded("Y");
            //op.SetIsPsDateBindsNeeded("Y");
            op.SetIsCabinFareNeeded("Y");
            op.SetIsZKeyNeeded("Y");
    
            return op;
    
        }
        public static TravelPreferencesType getTravelPreferencesType()
        {
            TravelPreferencesType tp = new TravelPreferencesType();
            //tp.setCabinClass("Y");//服务等级 F/C/Y
            tp.SetDisplayCurrCode("CNY");//显示用货币类型
            tp.SetCurrCode("CNY");//运价发布所有货币类型
            string DirectFlightOnly = HttpContext.Current.Request["DirectFlightOnly"];//是否直达
            if (DirectFlightOnly.Trim() == "true")
            {
                tp.SetIsDirectFlightOnly(true);//true - 只要直达航班;false - 包括非直达航班
    
            }
            else
            {
                tp.SetIsDirectFlightOnly(false);//true - 只要直达航班;false - 包括非直达航班
            }
            tp.SetJourneyType("OW");//OW - one way; RT - round trip; TS - two segments; MS - multi segment
            //tp.SetIsDealModel(true);//是否走产品管理(EPM)
            //tp.setIsGroup(false);//是否为团队 true/false
            ArrayList passenger = new ArrayList();
            PassengerType pa = new PassengerType();
            pa.SetNumber(1);//人数
            pa.SetType("AD");//成人
            passenger.Add(pa);
            tp.SetPassenger(passenger);
            return tp;
    
        }
        /*====================查询指定航空公司舱位价格=====================
         --例:1180.00/HU/7081/05NOV15/F/O/50.0/0.0/1350.00/CNY/0.0300,CA/C/2930.00/130.0/50.0/50.0*/
        public string StringBuildera(Output output)
        {
            string str = "";
            if (output.GetResult().GetFlightShopResult().GetPSn().GetPS() != null)
            {
                for (int j = 0; j < output.GetResult().GetFlightShopResult().GetPSn().GetPS().Count; j++)
                {
                    PricingSolutionType fs_ps = (PricingSolutionType)output.GetResult().GetFlightShopResult().GetPSn().GetPS()[j];
    
                    CabinFare CF = (CabinFare)fs_ps.Getcabinfares().GetyCabinFare()[0];
                    string cabin = CF.Getcabin();//服务等级
                    string amount = CF.Getamount();//服务等级价格
    
                    for (int j2 = 0; j2 < fs_ps.GetRouts().Count; j2++)
                    {
    
                        Routs routs = (Routs)fs_ps.GetRouts()[j2];
                        for (int j21 = 0; j21 < routs.GetRout().Count; j21++)
                        {
                            if (cabin.Trim() != "")
                            {
                                str = str + amount + "/";
                            }
                            else
                            {
                                str = str + "0" + "/";
                            }
    
                            RoutType rout = (RoutType)routs.GetRout()[j21];
                            //rout.GetBkClass();
                            string carr = rout.GetCarr();//航空公司两字码
                            str = str + carr + "/";
                            string fltNo = rout.GetFltNo();//航班号
                            str = str + fltNo + "/";
                            string departureDate = rout.GetDepartureDate();//起飞日期
                            DateTime st = DateTime.Parse(departureDate);
                            string strDate = st.ToString("ddMMMyy", DateTimeFormatInfo.InvariantInfo);
                            str = str + strDate + "/";
                            string bkClass = rout.GetBkClass();//舱位
                            str = str + bkClass + "/";
                            string oI = rout.GetOI();//去程回程标志,O 代表去程,I 代表回程
                            str = str + oI + "/";
                            TaxType tax = (TaxType)fs_ps.GetTaxes().GetTax()[0];
                            string amt = tax.GetAmt();//机场建建设费
                            str = str + amt + "/";
                            TaxType tax_a = (TaxType)fs_ps.GetTaxes().GetTax()[1];
                            string amt_A = tax_a.GetAmt();//燃油费
                            str = str + amt_A + "/";
                            string disAmt = fs_ps.GetDisAmt();//机票价格
                            str = str + disAmt + "/";
                            string disCurrCode = fs_ps.GetDisCurrCode();//显示用货币类型
                            str = str + disCurrCode + "/";
                            string zValue = fs_ps.GetZValue();//退票费折扣
                            str = str + zValue + "/";
                            str = str + ",";
                        }
                    }
                }
            }
            return str;
        }
    
        //3个参数:所有航空公司舱位价格,所要查询的航空公司,要查询的舱位
        public string CwJgInfo(string CabinPrice, string airline, string fltNo, string Scw)//
        {
            string amt = "0";//机场建建设费
            string amt_A = "0";//燃油费
            string disAmt = "0";//机票价格
            string disCurrCode = "CNY";//显示用货币类型
            string zValue = "0";//退票费折扣
            string DisCount = "0";//折扣
            string OI = "O";//去回程标识
            string[] arrayabc = CabinPrice.Split(',');//分割
            //sb.Append("价格数据量:" + arrayabc.Length);
            for (int jgabc = 0; jgabc < arrayabc.Length - 1; jgabc++)
            {
                string[] CwJgOne = arrayabc[jgabc].Split('/');//分割
                if (airline.Trim() == CwJgOne[1].Trim() && fltNo.Trim() == CwJgOne[2].Trim() && Scw.Trim() == CwJgOne[4].Trim())// && dt == CwJgOne[2].Trim().ToUpper() 
                {
                    amt = CwJgOne[6].ToString();//机场建建设费
                    //sb.Append("机场建建设费:" + amt);
    
                    amt_A = CwJgOne[7].ToString();//燃油费
                    //sb.Append("燃油费:" + amt_A);
    
                    disAmt = CwJgOne[8].ToString();//机票价格
                    //sb.Append("机票价格:" + disAmt);
    
                    disCurrCode = CwJgOne[9].ToString();//显示用货币类型
                    //sb.Append("显示用货币类型:" + disCurrCode);
    
                    zValue = CwJgOne[10].ToString();//代理费折扣
                    //sb.Append("代理费折扣:" + zValue);
                    if (CwJgOne[0].ToString().Trim() == "0")
                    {
                        DisCount = "特价";//折扣
                        //amount = CwJgOne[0].ToString();//Y舱位价格
                    }
                    else
                    {
                        if (CwJgOne[0].ToString().Trim() == CwJgOne[8].ToString().Trim())
                        {
                            DisCount = "全价";//折扣
                            //amount = CwJgOne[0].ToString();//Y舱位价格
                        }
                        else
                        {
                            double xzjg = Convert.ToDouble(CwJgOne[8].ToString().Trim());//现有价格
                            double yljg = Convert.ToDouble(CwJgOne[0].ToString().Trim());//原来价格
    
                            double zk = Math.Round((xzjg / yljg) * 10, 1);
                            if (zk > 10 || zk < 0)
                            {
                                DisCount = "特殊折扣";
                            }
                            else
                            {
                                DisCount = zk.ToString();//默认为保留两位
                            }
                        }
                    }
                    OI = CwJgOne[5].ToString();//去回程标识
    
                }
            }
            return amt + "/" + amt_A + "/" + disAmt + "/" + disCurrCode + "/" + zValue + "/" + DisCount + "/" + OI;
        }
        public void PrintResult(Output output)
        {
            //StringBuilder sb = new StringBuilder();
            List<myAvItem> list = new List<myAvItem>();
            if (output.GetResult().GetFlightShopResult().GetAvJourneys() != null)
            {
                for (int i = 0; i < output.GetResult().GetFlightShopResult().GetAvJourneys().Count; i++)
                {
                    AvJourneys fs_aj = (AvJourneys)output.GetResult().GetFlightShopResult().GetAvJourneys()[i];
                    for (int h1 = 0; h1 < fs_aj.GetAvJourney().Count; h1++)
                    {
                        AvailableJourneyType ajt = (AvailableJourneyType)fs_aj.GetAvJourney()[h1];
                        for (int h2 = 0; h2 < ajt.GetAvOpt().Count; h2++)
                        {
                            AvOpt avopt = (AvOpt)ajt.GetAvOpt()[h2];
                            for (int h3 = 0; h3 < avopt.GetFlt().Count; h3++)
                            {
                                FsFlightType flt = (FsFlightType)avopt.GetFlt()[h3];
    
                                Codeshare cdsh = flt.GetCodeshare();
                                string airlinegx = cdsh.GetAirline();
                                //string fltnogx = cdsh.GetFltno();
                                //string airline = flt.GetAirline();//航空公司
                                //string fltNo = flt.GetFltNo();//航班号
                                //Response.Write("开始--原航班号:" + airline + fltNo + ",共享航班号:" + airlinegx + fltnogx + "/----");
    
    
    
                                if (airlinegx == null || airlinegx == "")
                                {
                                    myAvItem model = new myAvItem();
                                    string rPH = flt.GetRPH().Substring(0, 6);//编号
                                    string airline = flt.GetAirline();//航空公司
                                    string fltNo = flt.GetFltNo();//航班号
                                    Term term = new Term();//航站楼信息类
                                    term = flt.GetTerm();
                                    string dep = flt.GetDep();//出发地
                                    string dep_term = term.GetDep();//出发航站楼
                                    string arr = flt.GetArr();//目的地
                                    string arr_term = term.GetArr();//到达航站楼
                                    int tpm = flt.GetTpm();//里程
                                    string dt = flt.GetDt();//出发日期
                                    string week = flt.GetWeek();//星期
                                    string deptm = flt.GetDeptm();//出发时间
                                    string arrtm = flt.GetArrtm();//到达时间
                                    int stop = flt.GetStop();//经停
                                    string dev = flt.GetDev();//机型
                                    string meal = flt.GetMeal();//餐食标识  
                                    /*B 早餐 C 免费酒精饮料 D 正餐 F 供采购的食物 G 供采购的食物和饮料 H 热的膳食 K 轻快早餐 L 午餐 M 膳食 N 没有饭食供应 O 冷的膳食 P 供采购的酒精饮料 R 茶点 S 快餐 V 供采购的茶点 */
    
                                    model.rPH = rPH;//编号
                                    model.dt = dt;//出发日期
                                    model.Carrier = airline;//航空公司两字码
                                    model.Airline = fltNo;  //航班号  
                                    model.Orgcity = dep;//起飞城市
                                    model.Deptime = deptm;//起飞时刻
                                    model.Dstcity = arr;//到达城市
                                    model.Arritime = arrtm;//到达时刻
                                    model.Planestyle = dev;//机型
                                    model.Stopnumber = stop;//经停次数
                                    model.DepTermAndArriTerm = dep_term;//出发航站楼
                                    model.arrTermAndArriTerm = arr_term;//到达航站楼
                                    model.Meal = meal;//餐食
                                    model.tpm = tpm; 里程
    
                                    for (int h4 = 0; h4 < flt.Get_Class().Count; h4++)
                                    {
                                        ClassType ct = (ClassType)flt.Get_Class()[h4];
                                        string cwname = ct.GetName();//可用舱位名
                                        //sb.Append("舱位名=" + cwname + ",");
                                        string av = ct.GetAv();//可用舱位数量
                                        //sb.Append("可用舱位数量=" + av + ",");
                                        ArrayList subclass_al = new ArrayList();
                                        subclass_al = ct.GetSubClass();
                                        if (subclass_al.Count > 0)
                                        {
                                            for (int h5 = 0; h5 < subclass_al.Count; h5++)
                                            {
                                                string subcwname = subclass_al[h5].ToString();//子舱位名
                                                //sb.Append("子舱位名=" + cwname + ",");
                                                if (subcwname.Trim() != cwname.Trim())
                                                {
                                                    string ThisCabinInformation = CwJgInfo(FFDprice, airline.Trim(), fltNo.Trim(), subcwname.Trim());
                                                    string[] CwJgOne = ThisCabinInformation.Split('/');//分割
                                                    myCabinPriceInfo CabinPriceInfo = new myCabinPriceInfo();
                                                    if (CwJgOne[2].ToString().Trim() != "0")
                                                    {
                                                        string amt = "0";//机场建建设费
                                                        string amt_A = "0";//燃油费
                                                        string disAmt = "0";//机票价格
                                                        string disCurrCode = "CNY";//显示用货币类型
                                                        string zValue = "0";//代理人Z值
                                                        string DisCount = "0";// 折扣
                                                        string OI = "O";// 去回程标识
                                                        amt = CwJgOne[0].ToString();
                                                        amt_A = CwJgOne[1].ToString();
                                                        disAmt = CwJgOne[2].ToString();
                                                        disCurrCode = CwJgOne[3].ToString();
                                                        zValue = CwJgOne[4].ToString();
                                                        DisCount = CwJgOne[5].ToString();
                                                        OI = CwJgOne[6].ToString();
                                                        CabinPriceInfo.CabinNo = subcwname.Trim();//可用舱位名
                                                        CabinPriceInfo.CabinInfo = av.Trim();//数量
                                                        CabinPriceInfo.Price = disAmt;//机票价格
                                                        CabinPriceInfo.disCurrCode = disCurrCode;//显示用货币类型
                                                        CabinPriceInfo.AirportTax = amt;//机场建建设费
                                                        CabinPriceInfo.FuelTax = amt_A;//燃油费
                                                        CabinPriceInfo.zValue = zValue;//代理人Z值
                                                        CabinPriceInfo.DisCount = DisCount;//  折扣
                                                        CabinPriceInfo.OI = OI;// 去回程标识
                                                        model.listCabinPriceInfo.Add(CabinPriceInfo);
                                                    }
                                                }
                                                else
                                                {
                                                    string ThisCabinInformation = CwJgInfo(FFDprice, airline.Trim(), fltNo.Trim(), cwname.Trim());
                                                    string[] CwJgOne = ThisCabinInformation.Split('/');//分割
                                                    myCabinPriceInfo CabinPriceInfo = new myCabinPriceInfo();
                                                    if (CwJgOne[2].ToString().Trim() != "0")
                                                    {
                                                        string amt = "0";//机场建建设费
                                                        string amt_A = "0";//燃油费
                                                        string disAmt = "0";//机票价格
                                                        string disCurrCode = "CNY";//显示用货币类型
                                                        string zValue = "0";//代理人Z值
                                                        string DisCount = "0";// 折扣
                                                        string OI = "O";// 去回程标识
                                                        amt = CwJgOne[0].ToString();
                                                        amt_A = CwJgOne[1].ToString();
                                                        disAmt = CwJgOne[2].ToString();
                                                        disCurrCode = CwJgOne[3].ToString();
                                                        zValue = CwJgOne[4].ToString();
                                                        DisCount = CwJgOne[5].ToString();
                                                        OI = CwJgOne[6].ToString();
                                                        CabinPriceInfo.CabinNo = cwname.Trim();//可用舱位名
                                                        CabinPriceInfo.CabinInfo = av.Trim();//数量
                                                        CabinPriceInfo.Price = disAmt;//机票价格
                                                        CabinPriceInfo.disCurrCode = disCurrCode;//显示用货币类型
                                                        CabinPriceInfo.AirportTax = amt;//机场建建设费
                                                        CabinPriceInfo.FuelTax = amt_A;//燃油费
                                                        CabinPriceInfo.zValue = zValue;//代理人Z值
                                                        CabinPriceInfo.DisCount = DisCount;// 折扣
                                                        CabinPriceInfo.OI = OI;// 去回程标识
                                                        model.listCabinPriceInfo.Add(CabinPriceInfo);
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            string ThisCabinInformation = CwJgInfo(FFDprice, airline.Trim(), fltNo.Trim(), cwname.Trim());
                                            string[] CwJgOne = ThisCabinInformation.Split('/');//分割
                                            myCabinPriceInfo CabinPriceInfo = new myCabinPriceInfo();
                                            if (CwJgOne[2].ToString().Trim() != "0")
                                            {
                                                string amt = "0";//机场建建设费
                                                string amt_A = "0";//燃油费
                                                string disAmt = "0";//机票价格
                                                string disCurrCode = "CNY";//显示用货币类型
                                                string zValue = "0";//代理人Z值
                                                string DisCount = "0";// 折扣
                                                string OI = "O";// 去回程标识
                                                amt = CwJgOne[0].ToString();
                                                amt_A = CwJgOne[1].ToString();
                                                disAmt = CwJgOne[2].ToString();
                                                disCurrCode = CwJgOne[3].ToString();
                                                zValue = CwJgOne[4].ToString();
                                                DisCount = CwJgOne[5].ToString();
                                                OI = CwJgOne[6].ToString();
                                                CabinPriceInfo.CabinNo = cwname.Trim();//可用舱位名
                                                CabinPriceInfo.CabinInfo = av.Trim();//数量
                                                CabinPriceInfo.Price = disAmt;//机票价格
                                                CabinPriceInfo.disCurrCode = disCurrCode;//显示用货币类型
                                                CabinPriceInfo.AirportTax = amt;//机场建建设费
                                                CabinPriceInfo.FuelTax = amt_A;//燃油费
                                                CabinPriceInfo.zValue = zValue;//代理人Z值
                                                CabinPriceInfo.DisCount = DisCount;// 折扣
                                                CabinPriceInfo.OI = OI;// 去回程标识
                                                model.listCabinPriceInfo.Add(CabinPriceInfo);
                                            }
                                        }
                                    }
    
                                    //ArrayList arrl_class = new ArrayList(); //可用舱位信息
                                    //arrl_class = flt.Get_Class(); ;
                                    //ClassType classtype = new ClassType();
                                    //for (int cwinfo = 0; cwinfo < arrl_class.Count; cwinfo++)
                                    //{
                                    //    string[] array = arrl_class[cwinfo].ToString().Split(',');//分割
                                    //    string[] arraya = array[0].Split('=');
                                    //    string[] arrayb = array[2].Split('=');
                                    //    string ThisCabinInformation = CwJgInfo(FFDprice, airline.Trim(), fltNo.Trim(), arraya[1].Trim());
                                    //    string[] CwJgOne = ThisCabinInformation.Split('/');//分割
                                    //    myCabinPriceInfo CabinPriceInfo = new myCabinPriceInfo();
                                    //    if (CwJgOne[2].ToString().Trim() != "0")
                                    //    {
                                    //        string amt = "0";//机场建建设费
                                    //        string amt_A = "0";//燃油费
                                    //        string disAmt = "0";//机票价格
                                    //        string disCurrCode = "CNY";//显示用货币类型
                                    //        string zValue = "0";//代理人Z值
                                    //        amt = CwJgOne[0].ToString();
                                    //        amt_A = CwJgOne[1].ToString();
                                    //        disAmt = CwJgOne[2].ToString();
                                    //        disCurrCode = CwJgOne[3].ToString();
                                    //        zValue = CwJgOne[4].ToString();
                                    //        CabinPriceInfo.CabinNo = arraya[1].Trim();//可用舱位名
                                    //        CabinPriceInfo.CabinInfo = arrayb[1].Trim();//数量
                                    //        CabinPriceInfo.Price = disAmt;//机票价格
                                    //        CabinPriceInfo.disCurrCode = disCurrCode;//显示用货币类型
                                    //        CabinPriceInfo.AirportTax = amt;//机场建建设费
                                    //        CabinPriceInfo.FuelTax = amt_A;//燃油费
                                    //        CabinPriceInfo.zValue = zValue;//代理人Z值
                                    //        model.listCabinPriceInfo.Add(CabinPriceInfo);
                                    //    }
                                    //}
                                    list.Add(model);
                                }
                            }
                        }
                    }
                }
                string strJson = JsonConvert.SerializeObject(list);
                //string strZip = ZipHelper.GZipCompressString(strJson);
                Response.Write(strJson);
            }
    
    
        }
    }

    返回结果是json数据返回,json相对应该的类如下

     //序号
        public string rPH { get; set; }
        //出发日期
        public string dt { get; set; }
        //航公司两字码
        public string Carrier { get; set; }
        //航班号
        public string Airline { get; set; }
        //起飞城市
        public string Orgcity { get; set; }
        //起飞时刻
        public string Deptime { get; set; }
        //到达城市
        public string Dstcity { get; set; }
        //到达时刻
        public string Arritime { get; set; }
        //机型
        public string Planestyle { get; set; }
        //经停次数
        public int Stopnumber { get; set; }
        //起飞航站楼
        public string DepTermAndArriTerm { get; set; }
        //达到航站楼
        public string arrTermAndArriTerm { get; set; }
        //餐食
        public string Meal { get; set; }
        //代码共享
    public int tpm { get; set; }
    
        //舱位信息与价格信息
        public List<myCabinPriceInfo> listCabinPriceInfo { get; set; }

    //舱位信息与价格信息 listCabinpriceInfo类字段
    /// <summary>
        /// 舱位编号
        /// </summary>
        public string CabinNo { get; set; }
        /// <summary>
        /// 舱位可用数量
        /// </summary>
        public string CabinInfo { get; set; }
        /// <summary>
        /// 价格
        /// </summary>
        public string Price { get; set; }
        /// <summary>
        /// 货币类型
        /// </summary>
        public string disCurrCode { get; set; }
        /// <summary>
        ///  机建
        /// </summary>
        public string AirportTax { get; set; }
        /// <summary>
        /// 燃油
        /// </summary>
        public string FuelTax { get; set; }
        /// <summary>
        ///  代理人费率
        /// </summary>
        public string zValue { get; set; }
        /// <summary>
        ///  折扣率
        /// </summary>
        public string DisCount { get; set; }
        /// <summary>
        ///  去程回程标志,O 代表去程,I 代表回程
        /// </summary>
    public string OI { get; set; }


    更多相关内容
  • 代理模式AOP

    千次阅读 2018-08-20 00:19:05
    代理模式简介 代理模式的优点 动态代理 JDK动态代理是如何实现的 问题1:为什么JDK动态代理只能代理实现了接口的类? 问题2:为什么JDK动态代理生成的代理类要去继承Proxy类? 问题3:为什么我们去调用代理类...

    Table of Contents

    代理模式简介

    代理模式的优点

    动态代理

    JDK动态代理是如何实现的

    问题1:为什么JDK动态代理只能代理实现了接口的类?

    问题2:为什么JDK动态代理生成的代理类要去继承Proxy类?

    问题3:为什么我们去调用代理类的目标方法,它会去调用invoke方法?

    问题4:JDK动态代理在哪些地方用到了反射?

    CGLib动态代理是如何实现的

    FastClass实现机制简介


    代理模式简介

    设计模式之禅在讲解代理模式时用了一个游戏代练的比喻。这个比喻非常的有代表性,对于理解代理模式很有帮助。它大致的思想是:大家都有过玩游戏的经历,也知道游戏代练。那么事实上游戏的代练在帮我的游戏账号打怪升级的时候,和代理模式里面的代理类做的事情不正是一样的事情吗?

    代理模式的定义如下:Provide a surrogate or placeholder for another object to control acess to it.(为其他对象提供一种代理以控制对这个对象的访问)。其通用类图如下:

    • Subject是一个抽象类也可以是一个接口,是一个最普通的业务类型定义无特殊要求
    • RealSubject是Subject的子类或实现类,它才是被代理角色。是业务逻辑的具体执行者。
    • Proxy叫做委托类,代理类。它负责对真实对象的应用。它在真实对象处理完毕前后做预处理和善后处理工作

    上面是一个静态代理的场景。代理一般实现的模式为JDK静态代理:创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时使其也实现这个接口。在代理类中持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法。

    代理模式的优点

    • 职责清晰

          真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。

    • 高扩展性

          具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱如来佛的手掌(接口),那我们的代理类完全就可以在不做任何修改的情况下使用。

    • 智能化

          这在我们以上讲解中还没有体现出来,不过在我们以下的动态代理章节中你就会看到代理的智能化,读者有兴趣也可以看看Struts是如何把表单元素映射到对象上的。

    动态代理

    动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理那一个对象,相对的来说,自己写代理类的方式就是静态代理。

    现在有一个非常流行的名称叫做:面向横切面编程,也就是AOP(Aspect Oriented Programming),其核心就是采用了动态代理机制。

    Spring AOP实现动态代理采用了两种方式,即JDK动态代理和CGLIB动态代理。

    JDK动态代理是如何实现的

    核心:代理模式加反射继承proxy实现被代理类接口
    JDK动态代理与静态代理有相同之处,都要创建代理类,代理类都要实现接口。但是不同之处在于:

    JDK静态代理是通过直接编码创建的,而JDK动态代理是利用反射机制在运行时根据指定参数创建代理类的。即JDK动态代理是更加通用的的一种方式,因为我们需要被代理的类往往是不止一个的。

    若我们要自己实现一个JDK代理的话,则可以按如下核心代码实现:

    public class JDKProxy implements InvocationHandler {
    
        //产生代理对象,被代理的对象必须实现一个接口
        public Object newProxy(Object targetObject) {//将目标对象传入进行代理
            Object object = Proxy.newProxyInstance(
                    targetObject.getClass().getClassLoader(),
                    targetObject.getClass().getInterfaces(), 
                    this);//返回代理对象
            return object;
        }
    
        //实现InvocationHandler的 invoke方法
        public Object invoke(Object proxy, Method method, Object[] args)//invoke方法
                throws Throwable {
            System.out.println("before");    //一般我们进行逻辑处理的函数比如这个地方是模拟检查权限
            
            Object  ret  = method.invoke(proxy, args);       //调用invoke方法,ret存储该方法的返回值,通过反射获取代理方法然后进行调用,而在cglib中则是直接调用的,因为继承的缘故
    
            System.out.println("after"); //后置增强
            
            return ret;
        }
    }
    

    第一个方法根据被代理类生成代理类,第二个方法实现增强逻辑,第二个方法调用被代理方法是通过反射(method.invoke)实现的。

    先来看第一个方法newProxy

    这个方法的目标是根据被代理对象去创建一个代理类。关键方法为

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

    此方法一共三个参数:

    1. ClassLoader 对象
    2. 一组interface接口
    3. 一个InvocationHandler对象

    该方法关键实现如下:

     @CallerSensitive
        public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
            throws IllegalArgumentException
        {
            Objects.requireNonNull(h);
    
            final Class<?>[] intfs = interfaces.clone();
            
            ...
    
            /*
             * Look up or generate the designated proxy class.
             */
            Class<?> cl = getProxyClass0(loader, intfs);
    
            /*
             * Invoke its constructor with the designated invocation handler.
             */
            try {
                if (sm != null) {
                    checkNewProxyPermission(Reflection.getCallerClass(), cl);
                }
    
                final Constructor<?> cons = cl.getConstructor(constructorParams);
                final InvocationHandler ih = h;
                if (!Modifier.isPublic(cl.getModifiers())) {
                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
                        public Void run() {
                            cons.setAccessible(true);
                            return null;
                        }
                    });
                }
                return cons.newInstance(new Object[]{h});
            } catch (IllegalAccessException|InstantiationException e) {
                 ...
            }
        }
    1. getProxyClass0方法的两个参数分别是classloader以及被代理类的接口,这个方法会生成一个Class对象出来。即代理类。
    2. 然后使用反射获得构造器: final Constructor<?> cons = cl.getConstructor(constructorParams);
    3. 返回实例:return cons.newInstance(new Object[]{h});

    生成的代理类:

    1. 会去继承proxy类,同时会去实现代理的接口,由于java不能多继承,这里已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理这里是实现的核心,aop既要执行原本方法又要执行增强方法,因此就通过生产proxy类,去继承jdkproxy获取增强,实现接口获取原本方法,再利用多态就实现了aop
    2. 提供了一个使用InvocationHandler作为参数的构造方法
    3. 生成静态代码块来初始化接口中方法的Method对象,以及Object类的equals、hashCode、toString方法。
    4. 重写了Object类的equals、hashCode、toString,它们都只是简单的调用了InvocationHandler的invoke方法,即可以对其进行特殊的操作,也就是说JDK的动态代理还可以代理上述三个方法。
    5. 代理类实现代理接口的目标方法中,只是简单的调用了InvocationHandler的invoke方法,我们可以在invoke方法中进行一些特殊操作,甚至不调用实现的方法,直接返回。

    经过我们的反编译,该类大致如下:

    import com.dr.designPattern.proxy.dynamicProxy.UserManager;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    
    public final class $Proxy extends Proxy implements UserManager {
    
       private static Method m1;
       private static Method m3;
       private static Method m2;
       private static Method m4;
       private static Method m0;
    
    
       public $Proxy(InvocationHandler var1) throws  {
          super(var1);
       }
    
       public final boolean equals(Object var1) throws  {
          try {
             return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
          } catch (RuntimeException | Error var3) {
             throw var3;
          } catch (Throwable var4) {
             throw new UndeclaredThrowableException(var4);
          }
       }
    
       public final void addUser(String var1, String var2) throws  {
          try {
             super.h.invoke(this, m3, new Object[]{var1, var2});
          } catch (RuntimeException | Error var4) {
             throw var4;
          } catch (Throwable var5) {
             throw new UndeclaredThrowableException(var5);
          }
       }
    
       public final String toString() throws  {
          try {
             return (String)super.h.invoke(this, m2, (Object[])null);
          } catch (RuntimeException | Error var2) {
             throw var2;
          } catch (Throwable var3) {
             throw new UndeclaredThrowableException(var3);
          }
       }
    
       public final void delUser(String var1) throws  {
          try {
             super.h.invoke(this, m4, new Object[]{var1});
          } catch (RuntimeException | Error var3) {
             throw var3;
          } catch (Throwable var4) {
             throw new UndeclaredThrowableException(var4);
          }
       }
    
       public final int hashCode() throws  {
          try {
             return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
          } catch (RuntimeException | Error var2) {
             throw var2;
          } catch (Throwable var3) {
             throw new UndeclaredThrowableException(var3);
          }
       }
    
       static {
          try {
             m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
             m3 = Class.forName("com.dr.designPattern.proxy.dynamicProxy.UserManager").getMethod("addUser", new Class[]{Class.forName("java.lang.String"), Class.forName("java.lang.String")});
             m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
             m4 = Class.forName("com.dr.designPattern.proxy.dynamicProxy.UserManager").getMethod("delUser", new Class[]{Class.forName("java.lang.String")});
             m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
          } catch (NoSuchMethodException var2) {
             throw new NoSuchMethodError(var2.getMessage());
          } catch (ClassNotFoundException var3) {
             throw new NoClassDefFoundError(var3.getMessage());
          }
       }
    }

     

    第二个方法是我们自己定义的JDKProxy类实现的InvocationHandler接口的invoke方法。可以看到上面生成的代理类就是通过调用invoke这个方法来进行目标方法的调用。

    在动态代理中InvocationHandler是核心,每个代理实例都具有一个关联的调用处理程序(InvocationHandler)。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序(InvocationHandler)的 invoke 方法。所以对代理方法的调用都是通InvocationHadler的invoke来实现中,而invoke方法根据传入的代理对象,方法和参数来决定调用代理的哪个方法。invoke方法定义如下:

     public Object invoke(Object proxy, Method method, Object[] args)

    这个时候我们再回头看生成的代理类$Proxy,并以其中实现的方法addUser方法为例来梳理一遍调用流程:

    首先代理类$Proxy继承了Proxy类并实现了被代理类UserManager

    ->$Proxy类实现了被代理类中的addUser和delUser方法。

    ->addUser方法的实现为:调用父类Proxy类的Invoke方法->因此,调用addUser方法就变成了调用被代理类的addUser方法->进而变成了调用Proxy类的invoke方法-> 而invoke方法是我们自己实现的->进而变成了调用有我们自己实现的逻辑(增强)的invoke方法

    ->invoke方法不仅要实现增强,还需调用被代理方法,因此这里传入了一个方法叫m3

    ->m3定义即为被代理方法addUser

    ->因此,在最终的invoke方法里面既能实现增强,又能调用被代理方法,并且,由于被代理方法是通过反射加载调用的,因此它可以是在运行时确定的,即动态的。

    通过反编译出来的代理类,我们甚至可以直接new一个它的实例出来调用它的方法,如下:

    $Proxy p = new $Proxy();
    p.addUser("ray","test");

    事实上这并没有什么神奇的地方,代理类和我们自己定义的普通的类并没有任何本质上的区别。

    方法调用的逻辑图如下:

     

    一些问题

    问题1:为什么JDK动态代理只能代理实现了接口的类?

    因为JDK动态代理生成的代理类需要去继承Proxy类,而java是单继承的,因此它只能去实现被代理类的接口(实现的接口)

    问题2:为什么JDK动态代理生成的代理类要去继承Proxy类?

    不仔细看的话,生成的代理类会给人一种继承Proxy类没有用的感觉,因为生成的代理类并没有用什么Proxy类的东西,很有迷惑性,我也是将生成的代理类代码亲自拿来试了一下才发现它的用处。

    事实上,在代理类$Proxy中有许多处方法的调用,都是通过使用super关键字去拿父类也就是proxy类中定义的InvocationHandler实例然后完成调用的。Super关键字正是在调用父类Prioxy类的方法。这就是用到proxy类的地方。

    在代理类$Proxy中调用父类的方法都是使用了InvocationHandler类的实例,在代理类$Proxy中通过构造方法传入进来,而我们应该还记得,在Proxy的newProxyInstance方法中的第三个参数,正是InvocationHandler的一个实例。

    因此这里调用方法时,自然就是使用这个实例去调用invoke方法,同时传入对应的方法参数。这下,所有的东西都串联起来了,问题三的答案事实上也已经有了。

    这里同时把oracle介绍代理的官方文档地址放在这里,作为参考。

    问题3:为什么我们去调用代理类的目标方法,它会去调用invoke方法?

    因为JDK生成真正的代理类中,是继承了Proxy类并实现了我们定义的被代理接口,而这个代理类在实现我们定义的接口方法时,是通过反射调用了InvocationHandlerImpl的invoke方法,然后在这个invoke方法当中,我们实现了增强的逻辑以及对被代理方法的真正调用。

    问题4:JDK动态代理在哪些地方用到了反射?

    经过上面的分析,至少有以下地方用到了反射:

    1. 在调用Proxy.newInstance方法时用反射获取接口传入方法

    2.在生成代理类$Proxy时,通过反射获取构造方法生成代理类

    3.在invoke方法当中调用被代理方法时,通过反射进行调用

    因此,反射对于jdk动态代理的实现至关重要,而代理更多的是起到一个设计思想,代码架构上的作用。

    CGLib动态代理是如何实现的

    核心:代理模式加继承

    具体说被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。

    方法的调用并不是通过反射来完成的,而是直接对方法进行调用,因为是继承,这一点与jdk动态代理是不一样的

    另外JDK代理只能对接口进行代理,Cglib则是对实现类进行代理。重点代码如下:

    public class CGLibProxy implements MethodInterceptor {
    
        //根据目标对象生成一个子类作为他的代理类
        public Object createProxyObject(Object obj) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(obj.getClass());//设置父类为被代理类
            enhancer.setCallback(this);
            Object proxyObj = enhancer.create();
            return proxyObj;// 返回代理对象
        }
    
        public Object intercept(Object proxy, Method method, Object[] args,
                MethodProxy methodProxy) throws Throwable {
            
            System.out.println("before");
          
            Object obj = methodProxy.invoke(proxy, args);
            
            System.out.println("after");
            return obj;
        }
    
        
    }

    总的来说思想和JDK动态代理差别不大,都是根据被代理类生成一个代理类,MethodInterceptor类的角色和JDK动态代理中的InvocationHandler是一样的。但是Cglib的实现逻辑更为复杂。

    但是在CGLib代理类中,因为是继承的缘故,因此会重写被代理类的方法,重写的逻辑就是调用我们这里实现的intercept方法,同时传入对应的参数。

    第一个方法createProxyObject

    这个方法会生成一个代理类,这个代理类当中重写了被代理类中的目标方法,同时,也提供了方法直接去调用被代理类的方法。

    第二个方法intercept方法

    在我们实现的intercept方法当中,当然也可以使用反射直接调用method方法,但是这里采取的实现是调用了MethodProxy类的方法去调用,这个方法没有用到反射机制。它的实现如下:

    public Object invoke(Object obj, Object[] args) throws Throwable {
            try {
                this.init();
                MethodProxy.FastClassInfo fci = this.fastClassInfo;
                return fci.f1.invoke(fci.i1, obj, args);
            } catch (InvocationTargetException var4) {
                throw var4.getTargetException();
            } catch (IllegalArgumentException var5) {
                if (this.fastClassInfo.i1 < 0) {
                    throw new IllegalArgumentException("Protected method: " + this.sig1);
                } else {
                    throw var5;
                }
            }
        }

    可以看到,是用了一个叫做FastClass的类来实现的。

    FastClass实现机制简介

    FastClass其实就是对Class对象进行特殊处理,提出下标概念index,通过索引保存方法的引用信息,将原先的反射调用,转化为方法的直接调用,从而体现所谓的fast,下面通过一个例子了解一下FastClass的实现机制。
    1、定义原类

    class Test {
        public void f(){
            System.out.println("f method");
        }
    
        public void g(){
            System.out.println("g method");
        }
    }

    2、定义Fast类

    class FastTest {
        public int getIndex(String signature){
            switch(signature.hashCode()){
            case 3078479:
                return 1;
            case 3108270:
                return 2;
            }
            return -1;
        }
    
        public Object invoke(int index, Object o, Object[] ol){
            Test t = (Test) o;
            switch(index){
            case 1:
                t.f();
                return null;
            case 2:
                t.g();
                return null;
            }
            return null;
        }
    }

    在FastTest中有两个方法,getIndex中对Test类的每个方法根据hash建立索引,invoke根据指定的索引,直接调用目标方法,避免了反射调用。所以当调用methodProxy.invoke方法时,实际上是调用代理类的方法,代理类则是直接调用了被代理类的原方法(因为是继承的缘故,可以直接调用)。

    在CGLibProxy类中重写的在intercept方法当中就可以进行逻辑增强,事实上,从技术上讲这里也可以通过反射调用被代理的原方法。

     

    展开全文
  • jdk动态代理使用详解

    万次阅读 多人点赞 2022-06-18 20:07:13
    jdk动态代理和cglib静态代理使用详解

    前言

    代理模式不管是JDK,spring框架,还是日常的开发中几乎可以说无处不在,下面一张简图描述了代理这个模式的业务场景,有过一些开发经验的同学对这张图应该不难理解;

    在这里插入图片描述

    为什么需要代理

    1、原有功能增强

    举例来说,当现有的类的代码只能满足一些基本的功能,而这些功能满足不了新需求,但又不能改动以前的代码,这时候就可以考虑使用代理,通过代理类,扩展原有类的功能,客户端访问的入口只是聪目标对象切换到代理对象而已;

    2、降低耦合

    在程序设计时,需要遵循一个叫做“单一职责”的原则,该原则要求每个类功能尽可能单一,为什么要单一,因为只有功能单一这个类被改动的可能性才会最小。

    现在突然接到需求,需要对现有类的增删改这样的事务性操作增加审计日志,很多人第一想到的是给每个增删改的地方增加日志,如果这样的类特别多,这就很折腾了,比较好的办法就是,使用代理类,在不对原来类修改的基础上,进行日志功能的扩展即可(spring aop功能即是如此);

    java中常用的代理模式

    总结下来,java中常用的代理实现主要包括:

    • jdk动态代理;
    • cglib静态代理

    一、JDK 动态代理

    JDK 动态代理是基于拦截器和反射实现的,不需要第三方库支持,只需要 JDK 环境即可

    • 必须实现 InvocationHandler 接口;
    • 使用 Proxy.newProxyInstance 产生代理对象;
    • 被代理的对象必须要实现接口;
    • 内部采用asm技术动态生成字节码;

    下面来看一个jdk动态代理的简单案例,深入理解下其用法

    public class JdkProxyDemo {
    
        interface Foo{
            void foo();
        }
    
        static class Target implements Foo{
            @Override
            public void foo() {
                System.out.println(" target foo");
            }
        }
    
        /**
         * jdk代理只能针对接口进行代理
         * 内部采用asm技术动态生成字节码()
         * @param args
         */
        public static void main(String[] args) {
    
            Target target = new Target();
    
            ClassLoader classLoader = JdkProxyDemo.class.getClassLoader();
            Foo proxy = (Foo)Proxy.newProxyInstance(classLoader, new Class[]{Foo.class}, new InvocationHandler() {
                //proxy 代理对象自身
                //method 正在执行的方法
                //方法参数
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("before");
                    Object result = method.invoke(target, args);
                    //代理类返回的是目标方法执行的结果
                    System.out.println("after");
                    return result;
                }
            });
            proxy.foo();
        }
    }
    

    运行这段代码,观察下效果

    在这里插入图片描述

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

    代码本身很简单,最重要的就是Proxy.newProxyInstance 这个方法,理解这里面的几个参数至关重要,分别说明下几个参数的含义:

    • classLoader,类加载器;
    • interfaces,目标对象接口;
    • InvocationHandler,真正完成相关方法反射代理的处理器;

    JDK动态代理,其关键的步骤就是在InvocationHandler 中执行目标实现类的方法反射调用

    由于JDK动态代理,底层是采用了asm字节码技术动态生成,我们无法通过debug源码的方式去学习,为了深入了解其原理,不妨模拟下其实现的过程吧;

    要模拟这个过程,大概需要下面的这些准备:

    • 接口和接口实现类;
    • 自定义的invocationHandler;
    • 自定义的Proxy对象(实现与目标类相同的接口);

    1、自定义接口和实现

    	interface Foo{
            void foo();
        }
    
        static class Target implements Foo{
            @Override
            public void foo() {
                System.out.println(" target foo");
            }
        }
    

    2、自定义的invocationHandler;

    通过上面的demo也可以看到,invocationHandler其实就是一个接口,真正执行时,需要传入到Proxy对象中,通过接口回调的方式实现,这里只需要参照JDK中的invocationHandler,定义好方法参数即可;

    	public interface MyInvocationHandler {
            Object invoke(Object proxy, Method method, Object[] params);
        }
    

    3、自定义的Proxy对象

    这段代码的逻辑大致如下:

    • 以构造的方式将自定义invocationHandler传入;
    • 通过反射拿到目标接口的方法;
    • 通过自定义invocationHandler的接口回调,通过反射完成代理逻辑实现;
    import java.lang.reflect.Method;
    
    public class MyProxy implements SelfJdkProxy.Foo {
    
        private SelfJdkProxy.MyInvocationHandler invocationHandler;
    
        public MyProxy(SelfJdkProxy.MyInvocationHandler invocationHandler) {
            this.invocationHandler = invocationHandler;
        }
    
        @Override
        public void foo() {
            try {
                Method foo = SelfJdkProxy.Foo.class.getMethod("foo");
                invocationHandler.invoke(this, foo, new Object[0]);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
    
    
        }
    
        @Override
        public int bar() {
            Method bar = null;
            Object result = null;
            try {
                bar = SelfJdkProxy.Foo.class.getMethod("bar");
                result = invocationHandler.invoke(this, bar, new Object[0]);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            return (int) result;
        }
    }
    
    

    运行上面的代码,观察效果,可以看到,输出效果是一样的,通过这个实现,我们简单模拟了JDK动态代理内部的简单实现;
    在这里插入图片描述

    二、cglib静态代理

    JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要cglib了;

    cglib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

    下面先看一个简单的cglib使用案例

    1、原始目标方法

    /**
     * 原始目标方法
     */
    public class CglibTarget {
    
        public void save() {
            System.out.println("save()");
        }
    
        public void save(int i) {
            System.out.println("save(int)");
        }
    
        public void save(long i) {
            System.out.println("save(long)");
        }
    
    }
    

    2、代理实现核心逻辑

    /**
     * cglib代理是通过父子继承关系创建代理
     * 代理对象自身是作为一个子类型的存在
     */
    public class CglibProxyDemo {
    
        static class Target {
            public void foo() {
                System.out.println(" target foo");
            }
        }
    
        public static void main(String[] args) {
            Target target = new Target();
            Target proxy = (Target)Enhancer.create(Target.class, new MethodInterceptor() {
                // o : 代理类对象自身
                //method : 代理类执行的方法
                //args : 方法执行参数
                //methodProxy :  方法代理【采用这个参数,可以避免使用方法反射进行调用,但是内部未使用反射】
                @Override
                public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    
                   /* System.out.println("before");
                    Object result = method.invoke(target, args);
                    System.out.println("after");
                    return result;*/
    
                   //methodProxy 使用 ,使用目标进行代理
                    /*System.out.println("before");
                    Object result = methodProxy.invoke(target,args);
                    System.out.println("after");
                    return result;*/
    
                    //methodProxy 使用 ,使用自身进行代理
                    System.out.println("before");
                    Object result = methodProxy.invokeSuper(o,args);
                    System.out.println("after");
                    return result;
    
                }
            });
            proxy.foo();
        }
    
    }
    

    cglib的使用相对JDK代理来说,显得更灵活,用起来也很方便,比较核心的地方在于通过调用CglibProxy这个方法的setMethodInterceptor,在回调接口中完成代理逻辑的实现;

    这里需要说明的是, 在MethodInterceptor 接口回调方法中,提供了两种完成代理逻辑实现的方式,

    • method.invoke(target,args); 基于反射实现;
    • methodProxy.invoke(target,args); 直接调用目标类的方法;
    • methodProxy.invokeSuper(o,args);直接调用目标类的方法;

    需要特别注意的是,CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例对象,因无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。

    同样来说,cglib底层的字节码技术的实现导致我们很难通过debug的方式去调试源码,下面来通过代码模拟上面的实现过程;

    自定义一个类,模拟Enhancer 实现

    整段代码逻辑做如下说明

    • 注入MethodInterceptor ,模拟cglib的create方法中的Enhancer;
    • 继承CglibTarget,即cglib采用的是继承目标类的方式完成代理;
    • 将代理类中的方法重写,并通过methodInterceptor.intercept 完成接口回调;
    • 将目标类中的方法,以静态代码块方式注入,避免每次调用重新实例化;
    • 自定义saveSuper方法,模拟MethodProxy 的实现过程;
    /**
     * cglib的代理是基于继承,并重写父类方法进行增强
     */
    public class CglibProxy extends CglibTarget {
    
        private MethodInterceptor methodInterceptor;
    
        public void setMethodInterceptor(MethodInterceptor methodInterceptor) {
            this.methodInterceptor = methodInterceptor;
        }
    
        static Method save0;
        static Method save1;
        static Method save2;
    
        static MethodProxy save0Proxy;
        static MethodProxy save1Proxy;
        static MethodProxy save2Proxy;
    
        static {
            try {
    
                save0 = CglibTarget.class.getMethod("save");
                save1 = CglibTarget.class.getMethod("save", int.class);
                save2 = CglibTarget.class.getMethod("save", long.class);
    
                save0Proxy = MethodProxy.create(CglibTarget.class, CglibProxy.class, "()V", "save", "saveSuper");
                save1Proxy = MethodProxy.create(CglibTarget.class, CglibProxy.class, "(I)V", "save1", "saveSuper");
                save2Proxy = MethodProxy.create(CglibTarget.class, CglibProxy.class, "(J)V", "save2", "saveSuper");
    
            } catch (NoSuchMethodException e) {
                throw new NoSuchMethodError(e.getMessage());
            }
        }
    
        public void saveSuper() {
            super.save();
        }
    
        public void saveSuper(int i) {
            super.save(i);
        }
    
        public void saveSuper(long i) {
            super.save(i);
        }
    
        @Override
        public void save() {
            try {
                methodInterceptor.intercept(this, save0, new Object[0], save0Proxy);
            } catch (Throwable throwable) {
                //throwable.printStackTrace();
                throw new UndeclaredThrowableException(throwable);
            }
        }
    
        @Override
        public void save(int i) {
            try {
                methodInterceptor.intercept(this, save1, new Object[]{i}, save1Proxy);
            } catch (Throwable throwable) {
                //throwable.printStackTrace();
                throw new UndeclaredThrowableException(throwable);
            }
        }
    
        @Override
        public void save(long i) {
            try {
                methodInterceptor.intercept(this, save2, new Object[]{i}, save2Proxy);
            } catch (Throwable throwable) {
                //throwable.printStackTrace();
                throw new UndeclaredThrowableException(throwable);
            }
        }
    }
    

    编写测试类

    public class CglibTest {
    
        public static void main(String[] args) {
            CglibProxy proxy = new CglibProxy();
            CglibTarget target = new CglibTarget();
    
            proxy.setMethodInterceptor(new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    System.out.println("before...");
                    //return method.invoke(target,args);
                    //return methodProxy.invoke(target,args);
                    return methodProxy.invokeSuper(o,args);
                }
            });
            proxy.save();
        }
    }
    

    运行上面的代码,通过控制台输出结果,可以看到和上面的效果一致;

    在这里插入图片描述

    这里需要对这个MethodProxy稍作说明,通过上面的案例可以看到,cglib的回调逻辑中,不仅可以通过类似JDK的反射实现代理,还可以通过MethodProxy提供的invoke()或者invokeSuper()方式实现,之所以说,cglib在某些情况下比JDK代理高效,就在于通过MethodProxy的两个方法,将不走反射,而是直接调用目标类的方法;

    三、spring中代理的使用

    在spring框架中,使用代理模式比较典型的场景就是AOP的实现了,代理逻辑核心要点如下:

    • 默认使用 JDK 动态代理,这样可以代理所有的接口类型;
    • 如果目标对象没有实现任何接口,则默认采用CGLIB代理;
    • 可强制使用CGLIB,指定proxy-target-class = “true” 或者 基于注解@EnableAspectJAutoProxy(proxyTargetClass = true)

    下面以AOP的功能使用为入口,来感受下以上三点在AOP的代理中的实现,

    来看下面这段以spring底层模拟实现的方式的AOP功能代码

    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.aop.aspectj.AspectJExpressionPointcut;
    import org.springframework.aop.framework.ProxyFactory;
    import org.springframework.aop.support.DefaultPointcutAdvisor;
    
    public class SpringAopTest {
    
        public static void main(String[] args) {
            //1、定义切点
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution(* foo())");
    
            //2、定义通知
            MethodInterceptor advice = new MethodInterceptor() {
                @Override
                public Object invoke(MethodInvocation methodInvocation) throws Throwable {
                    return methodInvocation.proceed();
                }
            };
    
            //3、定义切面
            DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
    
            //4、创建代理
            Target1 target1 = new Target1();
            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setTarget(target1);
            proxyFactory.addAdvisor(advisor);
    
            F1 proxy = (F1)proxyFactory.getProxy();
            //查看代理类的类型
            System.out.println(proxy.getClass());
            proxy.foo();
            proxy.bar();
    
        }
    
        interface F1 {
            void foo();
            void bar();
        }
    
        static class Target1 implements F1 {
            @Override
            public void foo() {
                System.out.println("Target1 foo() ...");
            }
    
            @Override
            public void bar() {
                System.out.println("Target1 bar() ...");
            }
        }
    
        static class Target2 implements F1 {
            @Override
            public void foo() {
                System.out.println("Target2 foo() ...");
            }
    
            @Override
            public void bar() {
                System.out.println("Target2 bar() ...");
            }
        }
    }
    
    

    主要逻辑思路可以参考注释,然后运行这段代码,观察控制台效果
    在这里插入图片描述

    通过控制台输出结果,可以大致得出下面几点结论,

    • AOP技术底层采用了代理实现;
    • 如果目标类实现了接口,spring默认情况下使用的是JDK代理;
    • 可以通过修改ProxyConfig中的属性proxyTargetClass 值来改变代理方式;

    在这里插入图片描述

    根据这个属性的不同,将会产生下面几种代理方式

    • proxyTargetClass = false; 目标实现了接口,采用JDK代理实现;
    • proxyTargetClass = false; 目标没有实现接口,采用cglib实现;
    • proxyTargetClass = true; 总是使用cglib实现;

    关于上面这几点,我们来通过上面代码的微调来观察效果,上面为什么会输出的是cglib的代理呢?因为在程序中并没有设置这个属性,因此被判断为并未实现接口,所以走的是cglib代理,

    调整1:设置代理类的接口

    在这里插入图片描述

    再次运行上面的代码,这次走的就是JDK动态代理
    在这里插入图片描述

    调整2:设置proxyTargetClass 属性为true

    在这里插入图片描述

    再次运行上面的代码,这次走的就是cglib代理
    在这里插入图片描述

    展开全文
  • NAT技术与代理服务器的区别

    千次阅读 2018-06-20 21:16:19
    ISA Server 最吸引的地方在于它和 Active Directory 的集成,这使得我们可以使用管理其它网络和用户相同的方法来管理用户访问、 Internet 以及安全策略。 ISA Server 使用 Microsoft 管理控制台(MMC), MMC ...

    NAT技术

    是当前解决IP地址不够用的主要手段, 是路由器的一个重要功能

    NAT技术能够在私有IP对外通信时, 将其转为全局IP

    也就是一种将私有IP和全局IP相互转化的技术方法

    很多学校, 家庭, 公司内部在每个终端设置私有IP, 而在路由器或必要的服务器上设置全局IP

    全局IP要求唯一, 但是私有IP不需要

    在不同的局域网中出现相同的私有IP是完全不影响的

    NAT 的 IP 转换过程

    这里写图片描述

    NAT 路由器将源地址从10.0.0.10替换成全局的IP 202.244.174.37

    NAT 路由器收到外部的数据时, 又会把目标IP从 202.244.174.37 替换回 10.0.0.10

    在NAT 路由器内部, 有一张自动生成的, 用于地址转换的表

    10.0.0.10 第一次向 163.221.120.9 发送数据时就会生成表中的映射关系

    如果局域网内, 有多个主机都访问同一个外网服务器, 那么对于服务器返回的数据中,

    目的IP都是相同的. 那么NAT路由器如何判定将这个数据包转发给哪个局域网的主机呢?

    这时候NAPT就来解决这个问题了. 它使用ip + port来建立这个关联关系

    这里写图片描述

    这种关联关系也是由NAT 路由器自动维护的

    例如: 在TCP建立连接时, 就会生成这个表项, 在断开连接后, 就会删除这个表项

    NAT 技术的缺陷

    由于NAT 依赖这个转换表, 所以有诸多限制

    无法从NAT 外部向内部服务器建立连接

    转换表的生成和销毁都需要额外开销

    通信过程中一旦NAT 设备异常, 即使存在热备, 所有的TCP连接也都会断开

    代理服务器(Proxy Server)

    是一种重要的服务器安全功能,它的工作主要在 OSI 模型的会话层,从而起到防火墙的作用

    代理服务器大多被用来连接 INTERNET(国际互联网) 和 Local Area Network(局域网)

    其功能就是代理网络用户去取得网络信息。

    形象的说:它是网络信息的中转站。代理服务器就好象一个大的Cache(高速缓存),这样就能显著提高浏览速度和效率。

    更重要的是:Proxy Server(代理服务器)是Internet链路级网关所提供的一种重要的安全功能,主要的功能有:

    • 突破自身IP访问限制,访问国外站点。教育网、过去的169网等
    • 网络用户可以通过代理访问国外网站
    • 访问一些单位或团体内部资源,如某大学FTP(前提是该代理地址在该资源 的允许访问范围之内),使用教育网内地址段免费代理服务器,就可以用于对教育网开放的各类FTP下载上传,以及各类资料查询共享等服务。
    • 突破中国电信的IP封锁:中国电信用户有很多网站是被限制访问的,这种限制是人为的,不同Serve对地址的封锁是不同的。所以不能访问时可以换一个国外的代理服务器试试。
    • 提高访问速度:通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。
    • 隐藏真实IP:上网者也可以通过这种方法隐藏自己的IP,免受攻击

    在国内,所谓中国多媒体公众信息网和教育网都是独立的大型国家级局域网,是与国际互联网隔绝的。出于各种需要,某些集团或个人在两网之间开设了代理服务器,如果我们知道这些代理服务器的地址,就可以利用它到达国外网站

    NAT 和 代理服务器的区别

    路由器往往都具备NAT 设备的功能, 通过NAT 设备进行中转, 完成子网设备和其他子网设备的通信过程

    代理服务器看起来和NAT 设备有一点相似

    客户端向代理服务器发送请求, 代理服务器将请求转发给真正要请求的服务器

    服务器返回结果后, 代理服务器又把结果回传给客户端

    两者的区别是:

    • 从应用上讲, NAT 设备是网络基础设备之一, 解决的是IP不足的问题

      代理服务器则是更贴近具体应用

      比如: 通过代理服务器进行”翻墙”, 另外像迅游这样的加速器, 也是使用代理服务器实现的

    • 从底层实现上讲, NAT 是工作在网络层的, 直接对IP地址进行替换

      代理服务器往往工作在应用层

    • 从使用范围上讲, NAT 一般在局域网的出口部署

      代理服务器可以在局域网做, 也可以在广域网做, 也可以跨网

    • 从部署位置上看, NAT 一般集成在防火墙, 路由器等硬件设备上

      代理服务器则是一个软件程序, 需要部署在服务器上

    常见的代理服务器

    1、Microsoft Proxy 代理服务器

    Microsoft Proxy Server 是微软提供的一种代理服务器解决方案,大型的局域网可以用它作为局域网的代理服务器软件。

    Microsoft Proxy 除了提供传统的代理功能外,还对当前Internet一些最新的应用提供了代理服务

    如IP电话(Internet Phone)、网络寻呼机(ICQ)等。

    Microsoft Proxy 包括了Web Proxy、Socks Proxy、Winsock Proxy。

    其中Web Proxy支持HTTP、FTP等服务,WinSock Proxy支持Telnet、电子邮件、RealAudio、IRC、ICQ等服务,Socks Proxy负责中转使用Socks代理服务的程序与外界服务器间的信息交换。

    Microsoft Proxy 在运行Windows NT/2000的服务器上安装后,各工作站就可以使用Web Proxy提供的服务,上网浏览、使用FTP等。

    如果要使用winSock Proxy和Socks Proxy提供的服务,必须要在客户端安装配置程序,并且还要在服务器端进行设置。

    相对于SyGate、WinGate等简易的代理服务器软件,Microsoft Proxy Server功能更强大,适用于企业级或大型网吧的局域网,但由于它一定要运行在WinNT/2000上,且配置比较复杂,小型局域网使用较少。

    2、Microsoft ISA 代理服务器

    Microsoft Internet Security and Acceleration Server (简称Microsoft ISA或ISA Server)

    是Microsoft Proxy Server的升级换代产品

    ISA Server是一个可扩展的企业防火墙和Neb缓存服务器,可与Windows 2000/2003集成,以便为连网用户实现基于策略的安全的实现、数据访问的加速。

    ISA Server 最吸引人的地方在于它和 Active Directory 的集成,这使得我们可以使用与管理其它网络和用户相同的方法来管理用户访问、 Internet 以及安全策略。

    ISA Server 使用 Microsoft 管理控制台(MMC), MMC 是一个界面,用来管理 Windows 2000/2003 Server 中的许多功能,而且文档十分完善。

    ISA Server构建在Windows 2000/2003安全、目录、虚拟专用网络(VPN)和带宽控制基础之上。不论是作为一组单独的防火墙还是缓存服务器来部署,还是以集成的模式来部署, ISA Server均可增强网络的安全性,实施一致的Internet使用策略,加速Internet访问,并最大限度地提高各种规模公司员工的办公效率。

    3、WinProxy 代理服务器

    Winproxy 是一种常用的代理服务器软件,只要安装在局域网的服务器上就可以了,它可以让局域网的多台客户机通过服务器上网。

    它支持SOCKs 4 & 5,利用Winproxy的SOCKs协议可以让客户机连通QQ。

    Winproxy是一款集NAT、代理和防火墙三者为一体的代理软件,它能够支持我们提到过的多种代理方式,同样也能够支持常见的协议。

    从功能上看,WinProxy与WinGate十分相似,但不如WinGate强大,其性能介于WinGate和CCProxy之间,对于那些不希望使用 WinGate这么复杂软件,但还需要使用NAT共享方式的用户来说,这是一个相当不错的选择。

    4 、WinGate 代理服务器

    WinGate可以作为一个坚固的防火墙,能控制企业内部网络的入出访问。

    相对同类软件,WinGate有很多优点,如可以限制用户对 Internet访问的能力,通过GateKeeper提供的强劲的远程控制和用户认证能力(Pro版),记录和审计能力, 一个SOCKS5服务器, HTTP缓存(节省带宽和加速访问),连接映射,可作为服务运行等等。

    如果使用的是一个十多台计算机的局域网环境,以Wingate为代理服务器通过一个Modem上网,应该说速度还是可以接受的。

    不过,问题就是我们刚才也提到的,在操控方面,WinGate对用户的要求似乎更高些。

    作为一款经典的代理服务软件,WinGate能够提供多种网络代理服务。

    其最新版除了提供常用的HTTP、Socks代理服务以外,还支持 DHCP、DNS服务。

    同时,它还提供了完整的POP3和SMTP服务,用户可以借此构建一个邮件服务器。

    WinGate还特别提供了按需拨号功能。

    更方便的是,WinGate还能够与Windows用户进行集成,Windows NT/2000系统用户可以直接使用已创建好的用户信息。

    5、winRoute 代理服务器

    WinRoute除了具有代理服务器的功能外,还具有NAT(Network Address Translation,网络地址转换)、防火墙、邮件服务器、DHCP服务器、DNS服务器等功能,能为用户提供一个功能强大的软网关。

    WinRoute有很多选项设置,涉及到网络配置的方方面面,但是它的帮助系统却不是很完善,由于WinRoute具有DHCP服务器的功能,局域网内部的机器还可配置成由WinRoute动态分配IP地址。

    WinRoute的Commands选单比较简单,可以进行拨号、断线、收发电子邮件。

    总体来说,WinRoute的网络功能相当全面,是一个优秀的软网关, 美中不足的就是它的用户界面显得有些简单,帮助系统不完善,从而增加了配置工作的难度。

    6、SyGate 代理服务器

    SyGate 是一种支持多用户访问因特网的软件,并且是只通过一台计算机,共享因特网帐号,达到上网的目的。

    使用SyGate 若干个用户能同时通过一个小型网络,迅速、快捷、经济地访问因特网。

    易于安装 SyGate在数分钟之内便可以安装完成,并且通常不需要其他外加的设置。

    和其他代理服务器软件不同的是,SyGate仅安装Server便可以了。

    SyGate拥有直观的图形化界面,懂得操作Windows的人员均会操作。

    SyGate启动后便在后台运行,不需要人工的干预。

    易于管理在TCP/IP网络上,SyGate Client能让用户从任何一台计算机上远程监察和管理SyGate Server。

    SyGate诊断程序在任何时候都能帮助你确定你的系统设置以及解决网络连接的问题。

    SyGate设有使用日志文件以及系统设置文件,在需要的时候可轻易地查寻与检测。

    尽管这些功能并非是必须的,SyGate还是能以其高度的可配适性,满足任何小型网络中的多种需要。

    7、CCProxy 代理服务器

    CCProxy是一款国产的代理服务器软件,能满足小型网络用户所有的代理需求。

    它支持HTTP、FTP、Socks4、Socks5等多种代理协议,虽然不具备与Windows用户的集成能力,但CCProxy可以自行创建用户,并允许网管员根据需要为不同用户分配不同的权限。

    而通过相关规则的设定,CCProxy还能对单个用户连接数、访问网址等加以限制。

    CCProxy代理服务器于2000年6月问世,是国内最流行的下载量最大的的国产代理服务器软件。

    主要用于局域网内共享Modem猫代理上网,ADSL代理共享、宽带代理共享、专线代理共享、ISDN代理共享、卫星代理共享、蓝牙代理共享和二级代理等共享代理上网。

    总体来说,CCProxy可以完成两项大的功能:代理共享上网和客户端代理权限管理。

    CCProxy非常适合中国用户使用,无论是政府机关部门,大中小公司,学校,或是网吧,CCProxy都是实现共享上网的首选代理服务器软件。

    8、squid 代理服务器

    在Unix/linux下使用的比较优秀的代理服务器软件Squid

    之所以说它比较优秀,是因为它可以在代理服务器上做一个很大的缓存,可以把好多常去的网站内容存储到缓存中,这样,内部网的机器再访问那些网站,就可以从缓存里调用了。

    这样一方面可以加快内部网浏览因特网的速度,这就是所谓的提高客户机的访问命中率

    另一方面,Squid不仅仅支持HTTP协议,而且还支持 FTP, GOPHER,SSL和WAIS等协议

    考虑到简捷实用的原则,squid作为代理服务器不仅性能优异,而且还详细的纪录了各个客户端的访问纪录。

    Squid是一个缓存internet数据的一个软件,它接收用户的下载申请,并自动处理所下载的数据。

    Squid可以工作在很多的操作系统中,如 AIX, Digital Unix, FreeBSD, HP-UX, Irix, Linux, NetBSD, Nextstep, SCO, Solaris,OS/2等,也有不少人在其他操作系统中重新编译过Squid

    由于它安装简单,使用方便,所以已经被广泛使用。

    展开全文
  • [4]还用CNN编码人与物体之间的相对空间关系。我们的工作建立在HOI检测的这些最新进展的基础上,但具有关键的区别。现有工作基于个体线索( 人类外观,物体外观或 - 物体对之间的空间关系 )识别交互。我们的主要...
  • 5分钟搞懂Java静态代理与动态代理

    千次阅读 多人点赞 2020-08-01 10:07:38
    Java代理模式 一、代理的概念 ​ 代理(Proxy):即...使用静态代理的时候,代理对象目标对象要实现相同的接口,以此来保证两者具有相同的方法。代理对象持有目标对象的句柄。 代码示例: 接口: public interface S
  • NAT技术与代理服务器详解

    千次阅读 2017-06-24 19:44:24
    NAT技术原理应用1 概述1.1 简介1.1.1 名词解释公有IP地址:也叫全局地址,是指合法的IP地址,它是由NIC(网络信息中心)或者ISP(网络服务提供商)分配的地址,对外代表一个或多个内部局部地址,是全球统一的可寻 址...
  • [微信公众号 乐生活爱]公众号曾转载过蔡恒进教授的奇文|意识如何演化?机器何时有自我意识?《附着隧通-心智的工作模式》,值得反复也读。我上周听了由北京大学博古睿研究中心、...我们该如何面临将要到来的...
  • 厉害了!打工用Python分析西安市职位信息

    千次阅读 热门讨论 2020-12-05 21:54:24
    如果有一天“996”被合法化并成为一种常态,那么,我们又该如何去面对“会一天天衰老,总有一天肝不动”的客观规律呢?我注意到Boss直聘移动端会展示某个公司的作息时间,所以,我有了抓取西安市职位和公司信息并...
  • 我们知道TCP是端到端协议,其对中间链路是无感知的,拥塞控制机制中的cwnd如何能相对精确预知,一直是一个世界级难题。可以肯定的是,TCP两端相距越远,RTT越大,链路状况越是难以获取,误判越是会增多,而误判的...
  • 获取模块相对比较简单,主要功能就是从各个免费代理网站上将我们所需要的代理信息抓取下来。示例如下: import requests from pyquery import PyQuery from MysqlClient import MysqlClient from ...
  • 谈谈 Java 反射机制,动态代理是基于什么原理?典型回答反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect,官方用语)的能力。通过反射我们可以直接操作类或者对象,比如获取某个对象的类...
  • jvm的新生代、老年代、永久代关系

    万次阅读 多人点赞 2018-07-08 13:43:44
    很多认为方法区(或者HotSpot虚拟机中的永久代)是没有垃圾收集的,Java虚拟机规范中确实说过可以不要求虚拟机在方法区实现垃圾收集,而且在方法区进行垃圾收集的“性价比”一般比较低:在堆中,尤其是在新生代中...
  • 原文:http://www.cnblogs.com/vipyoumay/p/7455431.html我们知道,不同肤色的外貌差别很大,而双胞胎的辨识很难。有意思的是We...
  • 一,题记所有的业务系统,都有生成ID的需求,如订单id,商品id,文章ID等。这个ID会是数据库中的唯一...著名的例子就是身份证号码,身份证号码确实是对唯一的,然而一个是可以办理多个身份证的,例如你身份证...
  • 牛逼!Java 从入门到精通,超全汇总版

    万次阅读 多人点赞 2021-05-06 19:40:33
    设计目标 从 Paxos 到 Zookeeper ZooKeeper : 分布式过程协同技术详解 Nginx Nginx 基础知识 Nginx 正向代理与反向代理 Nginx 基本配置 Nginx 负载均衡 Nginx常用命令 深入理解 Nginx Netty Netty 实战 ES Elastic...
  • 关系抽取的论文收集

    千次阅读 多人点赞 2019-03-01 16:00:18
    找了ACL NACL EMNLP这两年的一些关系抽取的论文 Neural Relation Extraction with Selective Attention over Instances(16年,典型模型) 代码:(https://github.com/thunlp/NRE.) 运用attention机制来尽量减轻...
  • NLP之机对话系统

    千次阅读 2018-10-11 22:15:32
    机对话系统 机对话系统又称口语对话系统(spoken dialogue system)。一个典型的机对话系统主要包括如下6个技术模块:①语音识别器(speech recognizer);②语言解析器(language parser);③问题求解...
  • wget--Windows10下的安装使用

    千次阅读 2019-01-30 09:54:46
    文章目录一、下载安装二、使用方法wget -P 目录 网址三、详情参数 一、下载安装 GNU Wget是一个在网络上进行下载的简单而强大的自由软件,其本身也是GNU计划的一部分。它的名字是“World Wide Web”和“Get”的...
  • 大学四年零基础自学Java的路线

    万次阅读 多人点赞 2020-09-02 12:14:16
    国内人口基数这么大,那相对来说垃圾内容应该更多才对,但是大家几乎可以一直浏览到绿色健康的网络环境,这得益于风控,算法同学也会用风控去对涉黄,涉政等内容做一个甄别。 你要知道你的每一个行为在进入app开始...
  • 企业为获得利益回报而为顾客创造价值并之建立关系的过程。 2、营销组合 4P 4C Product 产品 设计出满足消费者需求的产品 Consumer‘s Needs 客户需求 设计一款樱花奶茶 Price 价格 为产品设定合理的...
  • SNMP介绍,OID及MIB库 理解与关系

    千次阅读 2019-03-21 21:27:41
    因此,在这里真正需要注意的是,MIB其实只是提供给我们一张我们想从某个SNMP代理中获得的可用OID的各种值的地图。一个MIB描述了在哪里找某个值、以及返回结果是什么。我们可以不用MIB设备进行交互,只不过在理获得...
  • 让我来试图再分析下更深层次的原因:因为用户不把手机当作很认真的专业游戏设备,所以对手游产品的忠诚度相对偏低,用户选择游戏的随意性偏高,对产品质量的敏感度也偏低,游戏的生命周期就更短。进一步往下推演,就...
  • Nginx笔记——代理服务配置

    千次阅读 2022-03-30 09:55:36
    Nginx的代理配置,正向代理、反向代理、负载均衡
  • 2018年1月iOS招心得(附面试题)- 答案整理 基础不牢,地动山摇. 面试问的大多都是开发所必备的基础知识,通过面试题整理自己的技术栈是一个非常不错的途径. 这套面试题可作为开发同仁的一份复习提纲, 整理过程中...
  • 机交互中6种任务模型对比

    千次阅读 2015-08-27 21:29:16
    是通过选择规则来表示的,只能表示相对较简单的时序关系,包括顺序、选择、并行和循环关系。 GOMS 模型是一种用户的认知模型,主要用来描述任务在实践过程中是如何执行的。它的基本思想是,首先确定目标,将目标...
  • Java常见设计模式总结

    万次阅读 多人点赞 2021-09-18 17:18:54
    设计模式于己于于系统都是多赢的,它使得代码编写真正工程化,它是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现实中都有相应的原理来之对应,每种...
  • 很多时候程序默认是以jmeter的bin目录为根路径的,如果参数文件或是java文件的相对路径不是以bin为开始目录,很可能在分布式测试时,就出现远程代理机所调用的文件路径本地脚本不一致。  所以最好的方式是,将...
  • 浅谈Android中的MVP动态代理的结合

    千次阅读 热门讨论 2017-09-24 00:31:56
    浅谈Android中的MVP动态代理的结合 本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在Android开发平台上接触MVP足足算起来大概已经有一个年头左右。从最开始到现在经历的几个项目中我都采用了MVP架构...
  • 机交互基础教程

    千次阅读 多人点赞 2020-09-15 20:12:44
    狭义:研究人与计算机之间的信息交换: 到计算机:借助键盘、鼠标、操纵杆、数据服装、眼动跟踪器、位置跟踪器、数据手套、压力笔等设备,用手、脚、声音、姿势或身体的动作、眼镜甚至脑电波等向计算机传递信息 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 71,934
精华内容 28,773
关键字:

代理人与相对人的关系