具体方法与代码示例详解-pb如何获取服务器时间

教程大全 2026-03-08 02:09:19 浏览

在Web开发中,获取服务器时间是一个常见的需求,尤其是在需要确保时间准确性、处理时区问题或记录日志等场景,由于浏览器的安全限制,前端JavaScript代码无法直接读取服务器的时间,开发者需要借助一些技术手段来实现这一目标,本文将详细介绍几种在PB(powerBuilder)中获取服务器时间的方法,包括通过Web服务、AJAX请求、直接数据库查询以及利用服务器端脚本等技术,并分析各自的优缺点和适用场景。

通过Web服务获取服务器时间

Web服务是一种跨平台的通信方式,允许不同应用程序之间交换数据,在PB中,可以通过调用服务器端提供的Web服务来获取服务器时间,这种方法的优势在于它解耦了前端和后端的依赖,使得时间获取逻辑可以独立于前端应用进行维护,实现步骤通常包括:首先在服务器端创建一个简单的Web服务,该服务提供一个返回当前时间的方法;然后在PB中使用Web服务代理或HTTP请求调用该服务,并解析返回的时间数据,这种方法适用于分布式系统或需要跨服务器获取时间的场景,但需要额外的Web服务基础设施支持。

使用AJAX请求获取服务器时间

AJAX(Asynchronous JavaScript and XML)技术允许在不重新加载整个页面的情况下与服务器交换数据,在PB中,如果应用是基于Web的,可以通过嵌入JavaScript代码发起AJAX请求到服务器的一个专门接口,该接口返回服务器的时间,服务器端可以使用任何后端技术(如PHP、Java、ASP.NET等)生成当前时间并返回给前端,PB的Web窗口或DataWindow可以捕获这个响应并将其转换为PB可用的格式,这种方法轻量且易于实现,特别适合PB Web应用,但需要注意跨域问题和异步请求的处理逻辑。

直接查询数据库获取服务器时间

如果PB应用与数据库服务器在同一台机器或可以访问数据库,最直接的方法是通过SQL查询获取数据库服务器的时间,大多数数据库系统(如Oracle、SQL Server、MySQL等)都提供了内置函数来获取当前时间,例如Oracle的、SQL Server的或MySQL的,在PB中,可以使用数据窗口或嵌入式SQL执行这些查询,并将结果存储到PB变量中,这种方法简单高效,不需要额外的中间层,但前提是数据库时间与服务器时间一致,且应用有权限访问数据库。

利用服务器端脚本生成时间戳

对于PB Web应用,另一种常见的方法是在服务器端脚本(如ASP、jsp或PHP)中生成时间戳,并将其传递给前端,可以在PB的Web窗口中嵌入一个服务器端脚本块,该脚本使用服务器端函数获取时间并输出到JavaScript变量中,前端JavaScript可以直接读取这个变量,从而获得服务器时间,这种方法利用了服务器端脚本的执行环境,确保了时间的准确性,但需要PB应用支持服务器端脚本集成,且可能增加开发复杂度。

处理时区和格式转换

无论采用哪种方法获取服务器时间,都可能需要处理时区和格式转换的问题,服务器返回的时间可能是UTC时间或特定时区的时间,而PB应用可能需要将其转换为本地时区或特定格式,PB提供了丰富的日期时间函数,如 RelativeDate 、等,可以方便地进行时区调整和格式化,还需要考虑夏令时等特殊情况,确保时间转换的准确性。

pb获取服务器时间方法

性能和安全性考虑

在选择获取服务器时间的方法时,性能和安全性是两个重要因素,频繁的请求可能会增加服务器负载,因此应尽量减少时间获取的频率,例如将时间缓存并在一定时间内复用,确保时间接口的安全性,避免未授权访问或数据篡改,对于敏感应用,可以考虑使用HTTPS加密通信,或添加身份验证机制。

相关问答FAQs

Q1: 为什么PB不能直接获取服务器时间? A1: 由于浏览器的同源策略和安全限制,前端JavaScript无法直接访问服务器端的系统时间,PB作为前端开发工具,其运行环境在客户端,因此必须通过间接方式(如Web服务、AJAX请求等)从服务器获取时间数据。

Q2: 如何确保获取的服务器时间与本地时间同步? A2: 可以通过定期(如每分钟)从服务器获取时间并校准本地时钟,或使用Network Time Protocol(NTP)服务同步时间,在PB中记录服务器时间与本地时间的偏差,并在计算时进行补偿,以确保时间的一致性。


高分求做c语言作业,急急急

// : Defines the entry point for the console application.//#include stdafx.h// : Defines the entry point for the console application.//#include stdafx.h/**2012年4月10日21:17:33*功能:集合*说明:默认第一个节点[下标为0],作为垃圾回收头节点,所以任何指向第一个节点[下标为0],都认为指向结束*我就不认真写算法了,具体要改进的话,你在我的这个框架下很容易改的*/#define ARG_SetADT_SIZE 255 //函数声明//初始化boolSetNew(struct arg_SetADT*constpthis);//测试函数boolSetIN_SET(struct arg_SetADT*constpthis, int m_data);//输入并插入到单链表中的函数boolSetINSERT_SET(struct arg_SetADT*constpthis, int m_data);//集合元素输出函数voidSetPrint(struct arg_SetADT*constpthis);//获取第一个数据boolSetGetFirstData(struct arg_SetADT*constpthis, int *const pm_data);//获取下一个数据boolSetGetNextData(struct arg_SetADT*constpthis, int *const pm_data);//集合A、B的交C=A∩B的函数boolSetMixed(struct arg_SetADT*constpthis, struct arg_SetADT*constpA, struct arg_SetADT*constpB);//集合A、B的并D=A∪B的函数boolSetAnd(struct arg_SetADT*constpthis, struct arg_SetADT*constpA, struct arg_SetADT*constpB);//销毁voidSetDestroy(struct arg_SetADT*constpthis);//节点typedef struct arg_SetParADT {intm_index;//索引intm_data;//数据intm_point;//指针}arg_SetParCDT, *parg_SetParCDT;//集合对象typedef struct arg_SetADT {//数据//数据链arg_SetParCDTsz_List[ARG_SETADT_SIZE];//头节点索引intm_Index;//数据个数intm_Length;//处理函数//初始化bool(*New)(struct arg_SetADT*constpthis);//测试函数bool(*IN_SET)(struct arg_SetADT*constpthis, int m_data);//输入并插入到单链表中的函数bool(*INSERT_SET)(struct arg_SetADT*constpthis, int m_data);//集合元素输出函数void(*Print)(struct arg_SetADT*constpthis);//获取第一个数据bool(*GetFirstData)(struct arg_SetADT*constpthis, int *const pm_data);//获取下一个数据bool(*GetNextData)(struct arg_SetADT*constpthis, int *const pm_data);//集合A、B的交C=A∩B的函数bool(*Mixed)(struct arg_SetADT*constpthis, struct arg_SetADT*constpA, struct arg_SetADT*constpB);//集合A、B的并D=A∪B的函数bool(*And)(struct arg_SetADT*constpthis, struct arg_SetADT*constpA, struct arg_SetADT*constpB);//销毁void(*Destroy)(struct arg_SetADT*constpthis);}arg_SetCDT, *parg_SetCDT;//初始化boolSetNew(constparg_SetCDTpthis){//断言有初始化assert(NULL != pthis->New);int m_temp = 0;//数据初始化pthis->m_Length = 0;pthis->m_Index= 0;//pthis->sz_List[0].m_index = -1;//建立垃圾回收机制pthis->sz_List[0].m_point = 1;for (m_temp = 1; m_temp < ARG_SETADT_SIZE; m_temp++){//垃圾池中可用节点个数pthis->sz_List[0].m_data++;pthis->sz_List[m_temp].m_index = m_temp;//指针指向下一个节点pthis->sz_List[m_temp].m_point = m_temp + 1;}//没有节点指向pthis->sz_List[m_temp].m_point = 0;//函数绑定pthis->New= SetNew;pthis->IN_SET= SetIN_SET;pthis->INSERT_SET= SetINSERT_SET;pthis->Print= SetPrint;pthis->GetFirstData= SetGetFirstData;pthis->GetNextData= SetGetNextData;pthis->Mixed= SetMixed;pthis->And= SetAnd;pthis->Destroy= SetDestroy;return true;}//测试函数(我这里快点写,就简单处理了)boolSetIN_SET(struct arg_SetADT*constpthis, int m_data){int m_temp = 0;//没有数据if (pthis->m_Length == 0){return false;}for (m_temp = 1; m_temp < ARG_SETADT_SIZE; m_temp++){if (0 == pthis->sz_List[m_temp].m_point){continue;}//比对数据if (m_data == pthis->sz_List[m_temp].m_data){return true;}}return false;}//输入并插入到单链表中的函数boolSetINSERT_SET(constparg_SetCDTpthis, int m_data){intm_point = 0;//查看垃圾池中是否还有节点if (0 == pthis->sz_List[0].m_data){return false;}//从垃圾池中获取节点m_point = pthis->sz_List[0].m_point;pthis->sz_List[0].m_point = pthis->sz_List[m_point].m_point;pthis->sz_List[0].m_data--;//校验数据assert(m_point);//数据赋值 插入数据pthis->sz_List[m_point].m_data = m_data;pthis->sz_List[m_point].m_point = pthis->m_Index;pthis->m_Index = m_point;pthis->m_Length++;return true;}//集合元素输出函数voidSetPrint(constparg_SetCDTpthis){int m_temp = 0;int m_point = pthis->m_Index;for (m_temp = 0; m_temp < pthis->m_Length; m_temp++){printf(第%d个数据:%d\n,m_temp+1, pthis->sz_List[m_point].m_data);m_point = pthis->sz_List[m_point].m_point;//assert(m_point);}}//获取第一个数据boolSetGetFirstData(struct arg_SetADT*constpthis, int *const pm_data){if (0 == pthis->m_Length){return false;}*pm_data = pthis->sz_List[pthis->m_Index].m_data;//第一个[下标为0]的索引号作为数据移动的记录点pthis->sz_List[0].m_index = pthis->sz_List[pthis->m_Index].m_point;return true;}//获取下一个数据boolSetGetNextData(struct arg_SetADT*constpthis, int *const pm_data){//ole自治if (-1 == pthis->sz_List[0].m_index){return pthis->GetFirstData(pthis, pm_data);}if (0 == pthis->sz_List[0].m_index){return false;}*pm_data = pthis->sz_List[pthis->sz_List[0].m_index].m_data;//第一个[下标为0]的索引号作为数据移动的记录点pthis->sz_List[0].m_index = pthis->sz_List[pthis->sz_List[0].m_index].m_point;return true;}//集合A、B的交C=A∩B的函数boolSetMixed(struct arg_SetADT*constpthis, struct arg_SetADT*constpA, struct arg_SetADT*constpB){int m_data = 0;int m_temp = 0;//如果C中本身有数据if (0 != pthis->m_Length){return false;}//A B都有if( pA->GetFirstData(pA,&m_data) ){//检测数据是否在Bif (pB->IN_SET(pB, m_data)){pthis->INSERT_SET(pthis, m_data);}}else{return false;}for (m_temp = 1; m_temp < pA->m_Length; m_temp++){if( pA->GetNextData(pA,&m_data) ){//检测数据是否在Bif (pB->IN_SET(pB, m_data)){pthis->INSERT_SET(pthis, m_data);}}else{return true;}}return true;}//集合A、B的并D=A∪B的函数boolSetAnd(struct arg_SetADT*constpthis, struct arg_SetADT*constpA, struct arg_SetADT*constpB){int m_data = 0;int m_temp = 0;int m_temp1st = 0;int m_temp2st = 0;//查看A和B的交是否会超过缓冲(简单检测,不准确)if (pB->m_Length + pA->m_Length >= ARG_SETADT_SIZE){return false;}if( pA->GetFirstData(pA,&m_data) ){pthis->INSERT_SET(pthis, m_data);}else{//copy操作 直接copy pBif( pB->GetFirstData(pB,&m_data) ){pthis->INSERT_SET(pthis, m_data);}else{return true;}for (m_temp = 1; m_temp < pA->m_Length; m_temp++){if( pB->GetNextData(pB,&m_data) ){pthis->INSERT_SET(pthis, m_data);}else{return true;}}}for (m_temp1st = 1; m_temp1st < pA->m_Length; m_temp1st++){if( pA->GetNextData(pA,&m_data) ){pthis->INSERT_SET(pthis, m_data);}}//获取pBif( pB->GetFirstData(pB,&m_data) ){//检测数据是否在Aif (!pA->IN_SET(pA, m_data)){pthis->INSERT_SET(pthis, m_data);}}else{return true;}for (m_temp2st = 1; m_temp2st < pA->m_Length; m_temp2st++){if( pB->GetNextData(pB,&m_data) ){//检测数据是否在Bif (!pA->IN_SET(pA, m_data)){pthis->INSERT_SET(pthis, m_data);}}else{return true;}}return true;}//销毁voidSetDestroy(constparg_SetCDTpthis){//因为没有申请内存,所以直接清除数据即可pthis->m_Length = 0;memset(pthis->sz_List, 0, sizeof(arg_SetParCDT)*ARG_SETADT_SIZE);//解除函数绑定pthis->New= NULL;pthis->IN_SET= NULL;pthis->INSERT_SET= NULL;pthis->Print= NULL;pthis->GetFirstData= NULL;pthis->GetNextData= NULL;pthis->Mixed= NULL;pthis->And= NULL;pthis->Destroy= NULL;}int main(int argc, char* argv[]){arg_SetCDT A;arg_SetCDT B;arg_SetCDT C;arg_SetCDT D; = SetNew;(&A); = SetNew;(&B); = SetNew;(&C); = SetNew;(&D);_SET(&A, 40);_SET(&A, 10);_SET(&A, 55);_SET(&A, 45);_SET(&A, 52);_SET(&A, 51);_SET(&A, 35);printf(\nA\n);(&A);_SET(&B, 32);_SET(&B, 12);_SET(&B, 61);_SET(&B, 45);_SET(&B, 31);_SET(&B, 36);_SET(&B, 24);printf(\nB\n);(&B);printf(\n AND \n);(&C, &A, &B);(&C);printf(\n MIXED \n);(&D, &A, &B);(&D);(&A);(&B);(&C);(&D);return 0;}//楼主,我为了帮你做这个题,花了我差不多2个多小时的时间,你自己看着办吧//VC6.0 测试通过

.net分层构架的设计文档

微软的pet shop 4.0 去csdn上下载 输入petshop 回车就有源码和文档 如果找不到 我发给你 ===================================== 再给你一篇文章看 本文不是从理论的角度来探讨三层架构,而是用一个示例来介绍如何建设一个三层架构的项目,并说明项目中各个文件所处的层次与作用。写本文的目的,不是为了说明自己的这个方法有多对,别人的肯定不对,而是希望给那些初学三层架构却不知从何入手的朋友提供一点帮助。因为网上的文章,大多是注重理论的介绍,而忽略了具体的实践应用,或者有示例但讲得不透彻。导致看了之后,理论上又学习了一遍,但还是不知道代码怎么写。所以想从这个方面入手写一下,让从来没做过三层架构的初学者也能照猫画虎,写出代码来。文章表述的是笔者个人对三层架构的认识,肯定有许多不足的地方,欢迎大家指正,小弟也会根据反馈来修改这篇文章。文中的代码是伪代码,仅用来阐明思路。正文:一提三层架构,大家都知道是表现层(UI),业务逻辑层(BLL)和数据访问层(DAL),而且每层如何细分也都有很多的方法。但具体代码怎么写,到底那些文件算在哪一层,却是模模糊糊的。下面用一个简单的例子来带领大家实战三层架构的项目,这个例子只有一个功能,就是用户的简单管理。首先建立一个空白解决方案,添加如下项目及文件1、添加 Web Application项目,命名为UI,新建Web Form类型文件(含)2、添加ClassLibrary项目,命名为BLL,新建Class类型文件3、添加ClassLibrary项目,命名为DAL,新建Class类型文件。添加SQLHelper引用。(这个是微软的数据访问类,也可以不用,直接编写所有的数据访问代码。我一般用自己写的数据访问类DataAccessHelper )。4、添加ClassLibrary项目,命名为Model,新建Class类型文件5、添加ClassLibrary项目,命名为IDAL,新建Interface类型文件6、添加ClassLibrary项目,命名为ClassFactory相信大家已经看出来了,这个和Petshop的示例没什么区别,而且更简单,因为在下也是通过Petshop学习三层架构的。但一些朋友对于这几个项目所处的层次,以及它们之间的关系,可能比较模糊,这里逐个说明一下:1、和 这两个文件(以及文件所属的项目,下面也是如此,不再重复强调了)都属于表现层部分。比较好理解,因为它就是显示页面了。有些人觉得不应该算,而是要划到业务逻辑层中去。如果不做分层的话,那么让来处理业务逻辑,甚至操作数据库都没什么问题,但是做分层的话,这样就不应该了。在分层结构中,仅应该处理与显示有关的内容,其它部分都不应该涉及。举例:我们实现用列表方式显示用户的功能,那么提取信息的工作是由BLL来做的,UI(本例中是)调用BLL得到UserInfo后,通过代码绑定到的数据控件上,就实现了列表的显示。在此过程中对UI没有起到什么作用,仅是用来传递数据,而且因为实际编码中大部分情况都是如此的实现,所以使有些人觉得不应该算UI,而应该并入BLL负责逻辑处理。继续往下看,这时提出了一个新需求,要求在每个用户的前面加一个图标,生动地表现出用户的性别,而且不满18岁的用儿童图标表示。这个需求的实现,就轮到来做了,这种情况下才算有了真正的用途。2、 添加如下方法:public IList GetUsers():返回所有的用户信息列表public UserInfo GetUser(int UserId):返回指定用户的详细信息public bool AddUser(UserInfo User):新增用户信息public bool ChangeUser(UserInfo User):更新用户信息public void RemoveUser(int UserId):移除用户信息此文件就属于业务逻辑层了,专门用来处理与业务逻辑有关的操作。可能有很多人觉得这一层唯一的用途,就是把表现层传过来的数据转发给数据层。这种情况确实很多,但这只能说明项目比较简单,或者项目本身与业务的关系结合的不紧密(比如当前比较流行的MIS),所以造成业务层无事可做,只起到了一个转发的作用。但这不代表业务层可有可无,随着项目的增大,或者业务关系比较多,业务层就会体现出它的作用来了。此处最可能造成错误的,就是把数据操作代码划在了业务逻辑层,而把数据库作为了数据访问层。举例:有些朋友感觉BLL层意义不大,只是将DAL的数据提上来就转发给了UI,而未作任何处理。看一下这个例子BLL层SelectUser(UserInfo userInfo)根据传入的username或email得到用户详细信息。IsExist(UserInfo userInfo)判断指定的username或email是否存在。然后DAL也相应提供方法共BLL调用SelectUser(UserInfo userInfo)IsExist(UserInfo userInfo)这样BLL确实只起到了一个传递的作用。但如果这样做(Userinfo userinfo){UerInfo user = (User);return ( != null);}那么DAL就无需实现IsExist()方法了,BLL中也就有了逻辑处理的代码。3、 实体类,这个东西,大家可能觉得不好分层。包括我以前在内,是这样理解的:UIßàModelßàBLLßàModelßàDAL,如此则认为Model在各层之间起到了一个数据传输的桥梁作用。不过在这里,我们不是把事情想简单,而是想复杂了。Model是什么?它什么也不是!它在三层架构中是可有可无的。它其实就是面向对象编程中最基本的东西:类。一个桌子是一个类,一条新闻也是一个类,int、string、doublie等也是类,它仅仅是一个类而已。这样,Model在三层架构中的位置,和int,string等变量的地位就一样了,没有其它的目的,仅用于数据的存储而已,只不过它存储的是复杂的数据。所以如果你的项目中对象都非常简单,那么不用Model而直接传递多个参数也能做成三层架构。那为什么还要有Model呢,它的好处是什么呢。下面是思考一个问题时想到的,插在这里:Model在各层参数传递时到底能起到做大的作用?在各层间传递参数时,可以这样:AddUser(userId,userName,userPassword,…,)也可以这样:AddUser(userInfo)这两种方法那个好呢。一目了然,肯定是第二种要好很多。什么时候用普通变量类型(int,string,guid,double)在各层之间传递参数,什么使用Model传递?下面几个方法:SelectUser(int UserId)SelectUserByName(string username)SelectUserByName(string username,string password)SelectUserByEmail(string email)SelectUserByEmail(string email,string password)可以概括为:SelectUser(userId)SelectUser(user)这里用user这个Model对象囊括了username,password,email这三个参数的四种组合模式。UserId其实也可以合并到user中,但项目中其它BLL都实现了带有id参数的接口,所以这里也保留这一项。传入了userInfo,那如何处理呢,这个就需要按照先后的顺序了,有具体代码决定。这里按这个顺序处理首先看是否同时具有username和password,然后看是否同时具有email和password,然后看是否有username,然后看是否有email。依次处理。这样,如果以后增加一个新内容,会员卡(number),则无需更改接口,只要在DAL的代码中增加对number的支持就行,然后前台增加会员卡一项内容的表现与处理即可。4、 public IList SelectUsers():返回所有的用户信息列表public UserInfo SelectUser(int UserId):返回指定用户的相信信息public bool InsertUser(UserInfo User):新增用户信息public bool UpdateUser(UserInfo User):更新用户信息public void DeleteUser(int UserId):移除用户信息很多人最闹不清的就是数据访问层,到底那部分才算数据访问层呢?有些认为数据库就是数据访问层,这是对定义没有搞清楚,DAL是数据访问层而不是数据存储层,因此数据库不可能是这一层的。 也有的把SQLHelper(或其同类作用的组件)作为数据访问层,它又是一个可有可无的东西,SQLHelper的作用是减少重复性编码,提高编码效率,因此如果我习惯在乎效率或使用一个非数据库的数据源时,可以丢弃SQLHelper,一个可以随意弃置的部分,又怎么能成为三层架构中的一层呢。 可以这样定义:与数据源操作有关的代码,就应该放在数据访问层中,属于数据访问层5、IUserDAL 数据访问层接口,这又是一个可有可无的东西,因为Petshop中带了它和ClassFactory类工厂,所以有些项目不论需不需要支持多数据源,都把这两个东西做了进来,有的甚至不建ClassFactory而只建了IDAL,然后“IUserDAL iUserDal = new UserDAL();”,不知意义何在。 这就完全是画虎不成反类犬了。 许多人在这里有一个误解,那就是以为存在这样的关系:BLLßàIDALßàDAL,认为IDAL起到了BLL和DAL之间的桥梁作用,BLL是通过IDAL来调用DAL的。 但实际是即使你如此编码:“IUserDAL iUserDal = ();”,那么在执行“()”时,其实还是执行的UserDAL实例,而不是IUserDAL实例,所以IDAL在三层中的位置是与DAL平级的关系。 通过上面的介绍,基本上将三层架构的层次结构说明了。 其实,本人有一个判断三层架构是否标准的方法,那就是将三层中的任意一层完全替换,都不会对其它两层造成影响,这样的构造基本就符合三层标准了(虽然实现起来比较难^_^)。 例如如果将项目从B/S改为C/S(或相反),那么除了UI以外,BLL与DAL都不用改动;或者将SQLServer改为Oracle,只需替换SQLServerDAL到OracleDAL,无需其它操作等等。 本来想在文中加入一些具体的代码的,但感觉不是很必要,如果大家觉得需要的话,我再补充吧。 总结:不要因为某个层对你来说没用,或者实现起来特别简单,就认为它没有必要,或者摒弃它,或者挪作它用。 只要进行了分层,不管是几层,每一层都要有明确的目的和功能实现,而不要被实际过程所左右,造成同一类文件位于不同层的情况发生。 也不要出现同一层实现了不同的功能的情况发生。

@PathVariable和@RequestParam的区别

1、 @PathVariable 当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上。 示例代码:@Controller@RequestMapping(/owners/{ownerId})public class RelativePathUriTemplateController {@RequestMapping(/pets/{petId})public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {// implementation omitted }}上面代码把URI template 中变量 ownerId的值和petId的值,绑定到方法的参数上。 若方法参数名称和需要绑定的uri template中变量名称不一致,需要在@PathVariable(name)指定uri template中的名称。 2、 @RequestHeader、@CookieValue@RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上。 示例代码:这是一个Request 的header部分:Hostlocalhost:8080Accepttext/html,application/xhtml+xml,application/xml;q=0.9Accept-Language fr,en-gb;q=0.7,en;q=0.3Accept-Encoding gzip,deflateAccept-CharsetISO-8859-1,utf-8;q=0.7,*;q=0.7Keep-Alive300@RequestMapping(/)public void displayHeaderInfo(@RequestHeader(Accept-Encoding) String encoding,@RequestHeader(Keep-Alive) long keepAlive){}上面的代码,把request header部分的 Accept-Encoding的值,绑定到参数encoding上了, Keep-Alive header的值绑定到参数keepAlive上。 @CookieValue 可以把Request header中关于cookie的值绑定到方法的参数上。 例如有如下Cookie值:JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84 参数绑定的代码:@RequestMapping(/)public void displayHeaderInfo(@CookieValue(JSESSIONID) String cookie){}即把JSESSIONID的值绑定到参数cookie上。 3、@RequestParam, @Requestbody@RequestParam A) 常用来处理简单类型的绑定,通过() 获取的String可直接转换为简单类型的情况( String--> 简单类型的转换操作由ConversionService配置的转换器来完成);因为使用()方式获取参数,所以可以处理get 方式中queryString的值,也可以处理post方式中 body data的值;B)用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容,提交方式GET、POST;C) 该注解有两个属性: value、required; value用来指定要传入值的id名称,required用来指示参数是否必须绑定;示例代码:@Controller@RequestMapping(/pets)@SessionAttributes(pet)public class EditPetForm {@RequestMapping(method = ) public String setupForm(@RequestParam(petId) int petId, ModelMap model) { Pet pet = (petId); (pet, pet); return petForm; }@RequestBody该注解常用来处理Content-Type: 不是application/x-www-form-urlencoded编码的内容,例如application/json, application/xml等;它是通过使用HandlerAdapter 配置的HttpMessageConverters来解析post data body,然后绑定到相应的bean上的。 因为配置有FormHttpMessageConverter,所以也可以用来处理 application/x-www-form-urlencoded的内容,处理完的结果放在一个MultiValueMap里,这种情况在某些特殊需求下使用,详情查看FormHttpMessageConverter api;

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐