首页 文章 精选 留言 我的

精选列表

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

java面试-Java并发编程(二)——重排序

当我们写一个单线程程序时,总以为计算机会一行行地运行代码,然而事实并非如此。 什么是重排序? 重排序指的是编译器、处理器在不改变程序执行结果的前提下,重新排列指令的执行顺序,以达到最佳的运行效率。 重排序分类 重排序分为:编译器重排序 和 处理器重排序。 数据依赖 编译器和处理器并不会随意的改变指令的执行顺序,因为有些指令之间是有依赖关系的,若改变了他们的执行顺序,就会出现错误的结果。因此,编译器和处理器只会对没有依赖关系的指令进行重排序。 数据依赖:若相邻的两条指令访问同一个变量,并且其中有一条指令执行写操作,那么这样的两条指令之间存在数据依赖。对于有数据依赖关系的指令,不会发生重排序。 数据依赖关系总结一下为以下三种情况: 指令 示例 读后写 a=b;b=1; 写后写 a=1;a=2; 写后读 a=1;b=a; as-if-serial 在单线程开发中,程序员不需要知道指令是如何重排序的,只要简单地认为指令是按照顺序依次执行的即可。这就是as-if-serial的语义,即:貌似是串行的。

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

C++标准编程:虚函数与内联

我们曾经在讨论C++的时候,经常会问到:“虚函数能被声明为内联吗?”现在,我们几乎听不到这个问题了。现在听到的是:“你不应该使print成为内联的。声明一个虚函数为内联是错误的!” 这种说法的两个主要的原因是(1)虚函数是在运行期决议而内联是一个编译期动作,所以,我们将虚函数声明为内联并得不到什么效果;(2)声明一个虚函数为内联导致了函数的多分拷贝,而且我们为一个不应该在任何时候内联的函数白白花费了存储空间。这样做很没脑子。 不过,事实并不是这样。我们先来看看第一个:许多情况下,虚拟函数都被静态地决议了——比如在派生类虚拟函数中调用基类的虚拟函数的时候。为什么这样做呢?封装。一个比较明显的例子就是派生类析构函数调用链。所有的虚析构函数,除了最初触发这个析构链的虚析构函数,都被静态的决议了。如果不将基类的虚析构函数内联,我们无法从中获利[a]。这和不内联一个虚拟析构函数有什么不同吗?如果继承体系层次比较深并且有许多这样的类的实例要被销毁的话,答案是肯定的。 再来看另外一个不用析构函数的例子,想象一下设计一个图书馆类。我们将MaterialLocation作为抽象类LibraryMaterial的一个成员。将它的print成员函数声明为一个纯虚函数,并且提供函数定义:它输出MaterialLocation。 class LibraryMaterial { private: MaterialLocation _loc;// shared data // … public: // declares pure virtual function inline virtual void print(ostream& = cout) = 0; }; // we actually want to encapsulate the handling of the // location of the material within a base class // LibraryMaterial print() method - we just don’t want it // invoked through the virtual interface. That is, it is // only to be invoked within a derived class print() method inline void LibraryMaterial:: print(ostream &os) { os <<_loc; } 接着,我们引入一个Book类,它的print函数输出Title, Author等等。在这之前,它调用基类的print函数(LibraryMaterial::print())来显示书本位置(MaterialLocation)。如下: inline void Book:: print(ostream &os) { // ok, this is resolved statically, // and therefore is inline expanded … LibraryMaterial::print(); os << "title:" << _title << "author" << _author<< endl; } AudioBook类,派生于Book类,并加入附加信息,比如旁述,音频格式等等。这些东西都用它的print函数输出。再这之前,我们需要调用Book::print()来显示前面的信息。 inline void AudioBook:: print(ostream &os) { // ok, this is resolved statically, // and therefore is inline expanded … Book::print(); os <<"narrator:"<< _narrator <<endl; } 这和虚析构函数调用链的例子一样,都只是最初调用的虚函数没有被静态决议,其它的都被原地展开。This unnamed hierarchical design pattern is significantly less effective if we never declare a virtual function to be inline. 那么对于第二个原因中代码膨胀的问题呢?我们来分析一下,如果我们写下: LibraryMaterial *p = new AudioBook("Mason & Dixon", "Thomas Pynchon", "Johnny Depp"); // … p->print(); 这个print实例是内联的吗?不,当然不是。这样不得不通过虚拟机制在运行期决议。这让print实例放弃了对它的内联声明了吗?也不是。这个调用转换为下面的形式(伪代码): // Pseudo C++ Code // Possible transformation of p->print() (*p->_vptr[ 2 ])(p); where 2 represents the location of print within the associated virtual function table.因为调用print是通过函数指针_vptr[2]进行的,所以,编译器不能静态的决定这个调用地址,并且,这个函数也不能内联。 当然,虚函数print的内联实体(definition)也必须在某个地方表现出来。 即是说,至少有一个函数实体是在virtual table调用的地址原地展开的。编译器是如何决定在何时展开这个函数实体呢?其中一个编译(implementaion)策略是当virtual table生成的同时,生成这个函数实体。这就是说对于每一个派生类的virtual table都会生成一个函数实体。 在一个可应用的类[b]中有多少vitrual table会被生成呢?呵呵,这是一个好问题。C++标准中对虚函数行为进行了规定,但是没有对函数实现进行规定。由于virtual table没有在C++标准中进行规定,很明显,究竟这个virtual table怎样生成,和究竟要生成多少个vitrual table也没有规定。多少个?当然,我们只要一个。Stroustrup的cfront编译器,很巧妙的处理了这些情况。( Stan and Andy Koenig described the algorithm in the March 1990 C++ Report article, "Optimizing Virtual Tables in C++ Release 2.0.") Moreover, the C++ Standard now requires that inline functions behave as though only one definition for an inline function exists in the program even though the function may be defined in different files。新的规则要求编译器只展开一个内联虚函数。如果一点被广泛采用的话,虚函数的内联导致的代码膨胀问题就会消失。

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

python函数式编程之装饰器(二)

以前用装饰器,都是定义好了装饰器后,使用@装饰器名的方法写入被装饰函数的正上方 在这里,定义的装饰器都是没有参数的 在定义装饰器的函数的时候,没有在括号里定义参数,这就叫做无参装饰器 既然有无参装饰器,那么当然也就会有有参装饰器 有参装饰器的定义和使用 定义一个普通的装饰器 db_path = "db.txt" login_dic = { "user": None, "status": None, } def auth(func): def wrapper(*args, **kwargs): if login_dic['user'] and login_dic['status']: res = func(*args, **kwargs) return res name = input("your name:").strip() password = input("your password:").strip() with open(db_path, "r", encoding="utf-8") as f: user_dic = eval(f.read()) if name in user_dic and password == user_dic[name]: print("login ok") login_dic['user'] = name login_dic['status'] = True res = func(*args, **kwargs) return res else: print("login error") return wrapper @auth def index(): print("welcome to index page") @auth def home(name): print("welcome to %s home page" % name) index() home() 上面的例子是一个典型的基于文件的认证方式的装饰器 在生产环境中,用户的认证方式可能有很多种,比如还有LDAP和数据库的认证方式 如果想把上面的代码修改,添加基于不同认证方式的用户认证 db_path = "db.txt" login_dic = { "user": None, "status": None, } def deco(auth_type): def auth(func): def wrapper(*args, **kwargs): if auth_type == "file": if login_dic['user'] and login_dic['status']: res = func(*args, **kwargs) return res name = input("your name:").strip() password = input("your password:").strip() with open(db_path, "r", encoding="utf-8") as f: user_dic = eval(f.read()) if name in user_dic and password == user_dic[name]: print("login ok") login_dic['user'] = name login_dic['status'] = True res = func(*args, **kwargs) return res else: print("login error") elif auth_type == 'ldap': print("ldap认证方式") elif auth_type == "sql": print("数据库的认证方式") else: print("不知道的认证方式") return wrapper return auth 有参装饰器的调用 @deco(auth_type="file") def index(): print("welcome to index page") @deco(auth_type="abc") def home(name): print("welcome to %s home page" % name) index() home() 在上面的例子里,deco(auth_type="file")这个函数的执行以后就得到了auth函数,但是现在得到的auth函数跟以前的auth函数是不一样的,现在的auth函数内部添加了认证方式这样一个参数, 这样添加auth_type参数后的结果就相当于加在index函数和home函数正上方的是auth函数,这样就为最开始时的auth函数添加了一个参数 函数中的路由功能 先定义3个函数,现在想做的是只需要用户输入字符串,就执行对应的函数 可以通过为每个函数添加装饰器的功能,把普通函数添加到函数字典中,然后到函数字典中找到输入字符串对应的函数地址,加括号就可以运行了 类似于 func_dic = {"f1": f1, "f2": f2, "f3": f3} def f1(): print("f1 func") def f2(): print("f2 func") def f3(): print("f3 func") 这里就要使用到有参装饰器 定义有参装饰器 def make_func_dic(key): def deco(func): func_dic[key] = func return deco 用装饰器make_func_dic装饰函数 func_dic = {} def make_func_dic(key): def deco(func): func_dic[key] = func return deco @make_func_dic("f1") # 等同于deco(f1) def f1(): print("f1 func") @make_func_dic("f2") # 等同于deco(f2) def f2(): print("f2 func") @make_func_dic("f3") # 等同于deco(f3) def f3(): print("f3 func") 打印func_dic,得到结果 {'f1': <function f1 at 0x0000000002D2A510>, 'f2': <function f2 at 0x0000000002D2A598>, 'f3': <function f3 at 0x0000000002D2A620>} 可以看到func_dic字典中,每个字符串对应的是相应字符串的函数的内存地址 这样想运行f1函数,只需要把func_dic中的"f1"的值加括号运行就可以了 然后使用户输入字符串,运行字符串对应的函数 while True: cmd=input(">>: ").strip() if cmd in func_dic: func_dic[cmd]() 这样就可以得到想要的结果了 这样做的好处:只需要输入对应的字符串,就可以执行对应的函数,不需要使用if和elif对输入的字符串进行一条一条的判断了 这就是使用装饰器在代码级别达到函数的路由功能

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

面向对象高级编程:使用枚举类

当我们需要定义常量时,一个办法是用大写变量通过整数来定义,例如月份: JAN = 1 FEB = 2 MAR = 3 ... NOV = 11 DEC = 12 好处是简单,缺点是类型是int,并且仍然是变量。 更好的方法是为这样的枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例。Python提供了Enum类来实现这个功能: from enum import Enum Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) 这样我们就获得了Month类型的枚举类,可以直接使用Month.Jan来引用一个常量,或者枚举它的所有成员: for name, member in Month.__members__.items(): print(name, '=>', member, ',', member.value) value属性则是自动赋给成员的int常量,默认从1开始计数。 如果需要更精确地控制枚举类型,可以从Enum派生出自定义类: from enum import Enum, unique @unique class Weekday(Enum): Sun = 0 # Sun的value被设定为0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6 @unique装饰器可以帮助我们检查保证没有重复值。 访问这些枚举类型可以有若干种方法: >>> day1 = Weekday.Mon >>> print(day1) Weekday.Mon >>> print(Weekday.Tue) Weekday.Tue >>> print(Weekday['Tue']) Weekday.Tue >>> print(Weekday.Tue.value) 2 >>> print(day1 == Weekday.Mon) True >>> print(day1 == Weekday.Tue) False >>> print(Weekday(1)) Weekday.Mon >>> print(day1 == Weekday(1)) True >>> Weekday(7) Traceback (most recent call last): ... ValueError: 7 is not a valid Weekday >>> for name, member in Weekday.__members__.items(): ... print(name, '=>', member) ... Sun => Weekday.Sun Mon => Weekday.Mon Tue => Weekday.Tue Wed => Weekday.Wed Thu => Weekday.Thu Fri => Weekday.Fri Sat => Weekday.Sat 可见,既可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。 练习 把Student的gender属性改造为枚举类型,可以避免使用字符串: # -*- coding: utf-8 -*- from enum import Enum, unique # 测试: bart = Student('Bart', Gender.Male) if bart.gender == Gender.Male: print('测试通过!') else: print('测试失败!') Run 小结 Enum可以把一组相关常量定义在一个class中,且class不可变,而且成员可以直接比较。 转载。原文:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143191235886950998592cd3e426e91687cdae696e64b000

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

面向对象高级编程:使用元类

type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的。 比方说我们要定义一个Hello的class,就写一个hello.py模块: class Hello(object): def hello(self, name='world'): print('Hello, %s.' % name) 当Python解释器载入hello模块时,就会依次执行该模块的所有语句,执行结果就是动态创建出一个Hello的class对象,测试如下: >>> from hello import Hello >>> h = Hello() >>> h.hello() Hello, world. >>> print(type(Hello)) <class 'type'> >>> print(type(h)) <class 'hello.Hello'> type()函数可以查看一个类型或变量的类型,Hello是一个class,它的类型就是type,而h是一个实例,它的类型就是class Hello。 我们说class的定义是运行时动态创建的,而创建class的方法就是使用type()函数。 type()函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object)...的定义: >>> def fn(self, name='world'): # 先定义函数 ... print('Hello, %s.' % name) ... >>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class >>> h = Hello() >>> h.hello() Hello, world. >>> print(type(Hello)) <class 'type'> >>> print(type(h)) <class '__main__.Hello'> 要创建一个class对象,type()函数依次传入3个参数: class的名称; 继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法; class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。 通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class。 正常情况下,我们都用class Xxx...来定义类,但是,type()函数也允许我们动态创建出类来,也就是说,动态语言本身支持运行期动态创建类,这和静态语言有非常大的不同,要在静态语言运行期创建类,必须构造源代码字符串再调用编译器,或者借助一些工具生成字节码实现,本质上都是动态编译,会非常复杂。 metaclass 除了使用type()动态创建类以外,要控制类的创建行为,还可以使用metaclass。 metaclass,直译为元类,简单的解释就是: 当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。 但是如果我们想创建出类呢?那就必须根据metaclass创建出类,所以:先定义metaclass,然后创建类。 连接起来就是:先定义metaclass,就可以创建类,最后创建实例。 所以,metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。 metaclass是Python面向对象里最难理解,也是最难使用的魔术代码。正常情况下,你不会碰到需要使用metaclass的情况,所以,以下内容看不懂也没关系,因为基本上你不会用到。 我们先看一个简单的例子,这个metaclass可以给我们自定义的MyList增加一个add方法: 定义ListMetaclass,按照默认习惯,metaclass的类名总是以Metaclass结尾,以便清楚地表示这是一个metaclass: # metaclass是类的模板,所以必须从`type`类型派生: class ListMetaclass(type): def __new__(cls, name, bases, attrs): attrs['add'] = lambda self, value: self.append(value) return type.__new__(cls, name, bases, attrs) 有了ListMetaclass,我们在定义类的时候还要指示使用ListMetaclass来定制类,传入关键字参数metaclass: class MyList(list, metaclass=ListMetaclass): pass 当我们传入关键字参数metaclass时,魔术就生效了,它指示Python解释器在创建MyList时,要通过ListMetaclass.__new__()来创建,在此,我们可以修改类的定义,比如,加上新的方法,然后,返回修改后的定义。 __new__()方法接收到的参数依次是: 当前准备创建的类的对象; 类的名字; 类继承的父类集合; 类的方法集合。 测试一下MyList是否可以调用add()方法: >>> L = MyList() >>> L.add(1) >> L [1] 而普通的list没有add()方法: >>> L2 = list() >>> L2.add(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'list' object has no attribute 'add' 动态修改有什么意义?直接在MyList定义中写上add()方法不是更简单吗?正常情况下,确实应该直接写,通过metaclass修改纯属变态。 但是,总会遇到需要通过metaclass修改类定义的。ORM就是一个典型的例子。 ORM全称“Object Relational Mapping”,即对象-关系映射,就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码更简单,不用直接操作SQL语句。 要编写一个ORM框架,所有的类都只能动态定义,因为只有使用者才能根据表的结构定义出对应的类来。 让我们来尝试编写一个ORM框架。 编写底层模块的第一步,就是先把调用接口写出来。比如,使用者如果使用这个ORM框架,想定义一个User类来操作对应的数据库表User,我们期待他写出这样的代码: class User(Model): # 定义类的属性到列的映射: id = IntegerField('id') name = StringField('username') email = StringField('email') password = StringField('password') # 创建一个实例: u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd') # 保存到数据库: u.save() 其中,父类Model和属性类型StringField、IntegerField是由ORM框架提供的,剩下的魔术方法比如save()全部由metaclass自动完成。虽然metaclass的编写会比较复杂,但ORM的使用者用起来却异常简单。 现在,我们就按上面的接口来实现该ORM。 首先来定义Field类,它负责保存数据库表的字段名和字段类型: class Field(object): def __init__(self, name, column_type): self.name = name self.column_type = column_type def __str__(self): return '<%s:%s>' % (self.__class__.__name__, self.name) 在Field的基础上,进一步定义各种类型的Field,比如StringField,IntegerField等等: class StringField(Field): def __init__(self, name): super(StringField, self).__init__(name, 'varchar(100)') class IntegerField(Field): def __init__(self, name): super(IntegerField, self).__init__(name, 'bigint') 下一步,就是编写最复杂的ModelMetaclass了: class ModelMetaclass(type): def __new__(cls, name, bases, attrs): if name=='Model': return type.__new__(cls, name, bases, attrs) print('Found model: %s' % name) mappings = dict() for k, v in attrs.items(): if isinstance(v, Field): print('Found mapping: %s ==> %s' % (k, v)) mappings[k] = v for k in mappings.keys(): attrs.pop(k) attrs['__mappings__'] = mappings # 保存属性和列的映射关系 attrs['__table__'] = name # 假设表名和类名一致 return type.__new__(cls, name, bases, attrs) 以及基类Model: class Model(dict, metaclass=ModelMetaclass): def __init__(self, **kw): super(Model, self).__init__(**kw) def __getattr__(self, key): try: return self[key] except KeyError: raise AttributeError(r"'Model' object has no attribute '%s'" % key) def __setattr__(self, key, value): self[key] = value def save(self): fields = [] params = [] args = [] for k, v in self.__mappings__.items(): fields.append(v.name) params.append('?') args.append(getattr(self, k, None)) sql = 'insert into %s (%s) values (%s)' % (self.__table__, ','.join(fields), ','.join(params)) print('SQL: %s' % sql) print('ARGS: %s' % str(args)) 当用户定义一个class User(Model)时,Python解释器首先在当前类User的定义中查找metaclass,如果没有找到,就继续在父类Model中查找metaclass,找到了,就使用Model中定义的metaclass的ModelMetaclass来创建User类,也就是说,metaclass可以隐式地继承到子类,但子类自己却感觉不到。 在ModelMetaclass中,一共做了几件事情: 排除掉对Model类的修改; 在当前类(比如User)中查找定义的类的所有属性,如果找到一个Field属性,就把它保存到一个__mappings__的dict中,同时从类属性中删除该Field属性,否则,容易造成运行时错误(实例的属性会遮盖类的同名属性); 把表名保存到__table__中,这里简化为表名默认为类名。 在Model类中,就可以定义各种操作数据库的方法,比如save(),delete(),find(),update等等。 我们实现了save()方法,把一个实例保存到数据库中。因为有表名,属性到字段的映射和属性值的集合,就可以构造出INSERT语句。 编写代码试试: u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd') u.save() 输出如下: Found model: User Found mapping: email ==> <StringField:email> Found mapping: password ==> <StringField:password> Found mapping: id ==> <IntegerField:uid> Found mapping: name ==> <StringField:username> SQL: insert into User (password,email,username,id) values (?,?,?,?) ARGS: ['my-pwd', 'test@orm.org', 'Michael', 12345] 可以看到,save()方法已经打印出了可执行的SQL语句,以及参数列表,只需要真正连接到数据库,执行该SQL语句,就可以完成真正的功能。 不到100行代码,我们就通过metaclass实现了一个精简的ORM框架,是不是非常简单? 小结 metaclass是Python中非常具有魔术性的对象,它可以改变类创建时的行为。这种强大的功能使用起来务必小心。 转载。原文:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319106919344c4ef8b1e04c48778bb45796e0335839000

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

面向对象高级编程:使用__slots__

正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。先定义class: class Student(object): pass 然后,尝试给实例绑定一个属性: >>> s = Student() >>> s.name = 'Michael' # 动态给实例绑定一个属性 >>> print(s.name) Michael 还可以尝试给实例绑定一个方法: >>> def set_age(self, age): # 定义一个函数作为实例方法 ... self.age = age ... >>> from types import MethodType >>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法 >>> s.set_age(25) # 调用实例方法 >>> s.age # 测试结果 25 但是,给一个实例绑定的方法,对另一个实例是不起作用的: >>> s2 = Student() # 创建新的实例 >>> s2.set_age(25) # 尝试调用方法 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute 'set_age' 为了给所有实例都绑定方法,可以给class绑定方法: >>> def set_score(self, score): ... self.score = score ... >>> Student.set_score = set_score 给class绑定方法后,所有实例均可调用: >>> s.set_score(100) >>> s.score 100 >>> s2.set_score(99) >>> s2.score 99 通常情况下,上面的set_score方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。 使用__slots__ 但是,如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加name和age属性。 为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性: class Student(object): __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称 然后,我们试试: >>> s = Student() # 创建新的实例 >>> s.name = 'Michael' # 绑定属性'name' >>> s.age = 25 # 绑定属性'age' >>> s.score = 99 # 绑定属性'score' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute 'score' 由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。 使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的: >>> class GraduateStudent(Student): ... pass ... >>> g = GraduateStudent() >>> g.score = 9999 除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。 转载。原文:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143186739713011a09b63dcbd42cc87f907a778b3ac73000

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

详解JAVA实现支付宝接口编程

//实现java支付宝很简单,只要从支付宝官方下载 http://help.alipay.com/support/index_sh.htm下载程序,配置一下参数就OK了; 1.先到http://help.alipay.com/support/index_sh.htm下接口程序,右下角有个“接口资料下载”点击下载进入下载页面http://club.alipay.com/read.php?tid=9976972选择你要下载支付宝的接口类型;我是选择“支付宝即时到账收款接口” 2.解压以后,可以看到很多种版本语言的支付宝例子,选择你要的语言类型;这里我是选择的是“alipaydirect\alipaydirect\支付宝即时到帐接口\java\create_direct_pay_by_user_jsp_utf8”是UTR-8的程序; 3.将项目导入到你的开发平台上,也就是myeclipse平台上,就可以看到项目的结构了。然后配置支付宝,作为测试的话这里只要修改一个文件就可以了,其他文件都不需要修改的,这个文件就是“AlipayConfig.java”里面的// ↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // 合作身份者ID,以2088开头由16位纯数字组成的字符串 public static String partner = ""; // 交易安全检验码,由数字和字母组成的32位字符串 public static String key = ""; // 签约支付宝账号或卖家收款支付宝帐户 public static String seller_email = ""; // 支付宝服务器通知的页面 要用 http://格式的完整路径,不允许加?id=123这类自定义参数 // 必须保证其地址能够在互联网中访问的到 public static String notify_url = "http://www.xxx.cn/create_direct_pay_by_user_jsp_utf8/notify_url.jsp"; // 当前页面跳转后的页面 要用 http://格式的完整路径,不允许加?id=123这类自定义参数 // 域名不能写成http://localhost/create_direct_pay_by_user_jsp_utf8/return_url.jsp ,否则会导致return_url执行无效 public static String return_url = "http://127.0.0.1:8080/create_direct_pay_by_user_jsp_utf8/return_url.jsp"; //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 4.然后开启服务器,运行index.jsp页面就可以看到效果了; 5.若需要了解具体得信息,在下载的文件里面有一个帮助文档PDF文件“支付宝即时到账接口集成教程.pdf”和“即时到账交易接口(create_direct_pay_by_user).pdf”; 在这个“alipaydirect\alipaydirect\支付宝即时到帐接口\java\create_direct_pay_by_user_jsp_utf8\”还有一个“readme.txt”帮助文件;仔细看一下帮助文档就可以明白的! 接下来用一点实例更加详细的解释一下: 1:拥有自己的支付宝企业账号。去产品商店选择适合自己的方案。并签约合同。 2:选择合适的商家收款产品并去签约。填写相应的信息 3:在商家服务会有PID和KEY是关键的东西。 4:选择自己签约的产品类型,下载对应的接口api与测试代码 即时到账收款 --alipaydirect 网银支付 --alipaydirect_bankpay_single 担保交易收款 --alipaytescow 双功能收款 --alipaydualfun 快捷支付(无线) --WS_SECURE_PAY_SDK 手机网站支付 --WS_WAP_PAYWAP 扫码即时到账 --alipaymobileqrcode 扫码担保交易--alipaymobileqrcode 批量付款到支付宝账户 --alipaytranspay 快捷登录 --alipayfastlogin 5:alipaydirect_bankpay_single 测试 在核心代码alipayconfig需要更改自己的partner和key 6:网银银行简码 网银银行简码 BOCB2C 中国银行 ICBCB2C 中国工商银行 ICBCBTB 中国工商银行(B2B) CMB 招商银行 CCB 中国建设银行 CCBBTB 中国建设银行(B2B) ABC 中国农业银行 ABCBTB 中国农业银行(B2B) SPDB 上海浦东发展银行 SPDBB2B 上海浦东发展银行(B2B) CIB 兴业银行 GDB 广东发展银行 SDB 深圳发展银行 CMBC 中国民生银行 COMM 交通银行 CITIC 中信银行 CEBBANK 光大银行 NBBANK 宁波银行 HZCBB2C 杭州银行 SHBANK 上海银行 SPABANK 平安银行 BJRCB 北京农村商业银行 fdb101 富滇银行 PSBC-DEBIT 中国邮政储蓄银行 BJBANK 北京银行 7:错误代码错误说明 误代码 说明 EXPARTNER_INFO_UNCORRECT 传入外部商户接口信息不正确 TRADE_BUYER_NOT_MATCH 买家账户与交易中不一致 TRADE_SELLER_NOT_MATCH 卖家账户与交易中不一致 TRADE_DATA_NOT_MATCH 请求数据与交易中不一致 SELLER_NOT_IN_SPECIFIED_SELLERS 卖家不在指定的商户限制卖家中 ILLEGAL_SIGN 签名验证出错 ILLEGAL_ARGUMENT 输入参数有错误 HASH_NO_PRIVILEGE 没有权限访问该服务 ILLEGAL_SERVICE service参数不正确 ILLEGAL_PARTNER 合作身份者ID不正确 HAS_NO_PUBLICKEY 没有上传公钥 USER_NOT_EXIST 会员不存在 OUT_TRADE_NO_EXIST 外部交易号已经存在 TRADE_NOT_EXIST 交易不存在 ILLEGAL_PAYMENT_TYPE 无效支付类型 BUYER_NOT_EXIST 买家不存在 SELLER_NOT_EXIST 卖家不存在 BUYER_SELLER_EQUAL 买家、卖家是同一帐户 ILLEGAL_SIGN_TYPE 签名类型不正确 COMMISION_ID_NOT_EXIST 佣金收取帐户不存在 COMMISION_SELLER_DUPLICATE 收取佣金帐户和卖家是同一帐户 出现的错误代码为ILLEGAL_PARTNER_EXTERFACE 1、没有签约这个接口的合同。 2、签约了相应的接口合同,但没有生效。 3、签约了相应的接口合同,但由于违规违法等原因被审核部门强制关闭。 8:页面需要修改的东西alipayapi.jsp 9:跳转页面第6步有截图。卖家账号收款的账号。不是付款的账号哦。 如果调试登录了收款的支付宝账号。会出错的哦。错误截图如下 错误代码:BUYER_SELLER_EQUAL 如果调试登录了收款的支付宝账号。而且页面填写的卖家账号非卖家账号(收款账号)会出现如下错误 错误代码:SELLER_NOT_IN_SPECIFIED_SELLERS 如果没有错误。则会直接跳转付款页面。输入买家账号即可。 10:成功付款的页面。付款页面需要输入购买用户的支付宝账号和支付密码 11:使用springMVC封装写符合自己网站需求的代码。以下代码仅参考 这个是ALIPAYAPI代码要获取数据的 [java] view plain copy <codeclass="hljsjavascript"style=""><spanclass="hljs-built_in"style="">Date</span>date=<spanclass="hljs-keyword"style="">new</span><spanclass="hljs-built_in"style="">Date</span>(); <spanclass="hljs-comment"style="">//支付类型必填不必修改</span> <spanclass="hljs-built_in"style="">String</span>payment_type=<spanclass="hljs-string"style="">"1"</span>; <spanclass="hljs-comment"style="">//服务器异步通知页面路径</span> <spanclass="hljs-comment"style="">//需http://格式的完整路径,不能加?id=123这类自定义参数</span> <spanclass="hljs-built_in"style="">String</span>notify_url=<spanclass="hljs-string"style="">"http://localhost:8080/alipay/async"</span>; <spanclass="hljs-comment"style="">//页面跳转同步通知页面路径</span> <spanclass="hljs-comment"style="">//需http://格式的完整路径,不能加?id=123这类自定义参数,不能写成http://localhost/</span> <spanclass="hljs-built_in"style="">String</span>return_url=<spanclass="hljs-string"style="">"http://192.168.0.222:8080/alipay/return_url"</span>; <spanclass="hljs-comment"style="">//订单名称</span> <spanclass="hljs-comment"style="">//必填</span> <spanclass="hljs-comment"style="">//Stringsubject=newString(request.getParameter("WIDsubject").getBytes("ISO-8859-1"),"UTF-8");</span> <spanclass="hljs-built_in"style="">String</span>subject=<spanclass="hljs-keyword"style="">new</span><spanclass="hljs-built_in"style="">String</span>(<spanclass="hljs-string"style="">"测试商品"</span>.getBytes(<spanclass="hljs-string"style="">"ISO-8859-1"</span>),<spanclass="hljs-string"style="">"UTF-8"</span>); <spanclass="hljs-comment"style="">//付款金额</span> <spanclass="hljs-comment"style="">//必填</span> <spanclass="hljs-comment"style="">//Stringtotal_fee=newString(request.getParameter("WIDtotal_fee").getBytes("ISO-8859-1"),"UTF-8");</span> <spanclass="hljs-built_in"style="">String</span>total_fee=<spanclass="hljs-string"style="">"0.01"</span>; <spanclass="hljs-built_in"style="">Map</span><<spanclass="hljs-built_in"style="">String</span>,<spanclass="hljs-built_in"style="">String</span>>sParaTemp=<spanclass="hljs-keyword"style="">new</span>HashMap<<spanclass="hljs-built_in"style="">String</span>,<spanclass="hljs-built_in"style="">String</span>>(); sParaTemp.put(<spanclass="hljs-string"style="">"service"</span>,<spanclass="hljs-string"style="">"create_direct_pay_by_user"</span>);<spanclass="hljs-comment"style="">//接口服务----即时到账</span> sParaTemp.put(<spanclass="hljs-string"style="">"partner"</span>,AlipayConfig.partner);<spanclass="hljs-comment"style="">//支付宝PID</span> sParaTemp.put(<spanclass="hljs-string"style="">"_input_charset"</span>,AlipayConfig.input_charset);<spanclass="hljs-comment"style="">//统一编码</span> sParaTemp.put(<spanclass="hljs-string"style="">"payment_type"</span>,payment_type);<spanclass="hljs-comment"style="">//支付类型</span> sParaTemp.put(<spanclass="hljs-string"style="">"notify_url"</span>,notify_url);<spanclass="hljs-comment"style="">//异步通知页面</span> sParaTemp.put(<spanclass="hljs-string"style="">"return_url"</span>,return_url);<spanclass="hljs-comment"style="">//页面跳转同步通知页面</span> sParaTemp.put(<spanclass="hljs-string"style="">"seller_email"</span>,Constants.SELLER_EMAIL);<spanclass="hljs-comment"style="">//卖家支付宝账号</span> sParaTemp.put(<spanclass="hljs-string"style="">"out_trade_no"</span>,date.getTime()+payment_type);<spanclass="hljs-comment"style="">//商品订单编号</span> sParaTemp.put(<spanclass="hljs-string"style="">"subject"</span>,subject);<spanclass="hljs-comment"style="">//商品名称</span> sParaTemp.put(<spanclass="hljs-string"style="">"total_fee"</span>,total_fee);<spanclass="hljs-comment"style="">//价格</span> <spanclass="hljs-comment"style="">//建立请求</span> <spanclass="hljs-built_in"style="">String</span>sHtmlText=AlipaySubmit.buildRequest(sParaTemp,<spanclass="hljs-string"style="">"get"</span>,<spanclass="hljs-string"style="">"立即付款"</span>); request.setAttribute(<spanclass="hljs-string"style="">"sHtmlText"</span>,sHtmlText); <spanclass="hljs-keyword"style="">return</span><spanclass="hljs-literal"style="">null</span>;</code> 付款是否成功的代码 [java] view plain copy <codeclass="hljsjavascript"style=""><spanclass="hljs-built_in"style="">Map</span><<spanclass="hljs-built_in"style="">String</span>,<spanclass="hljs-built_in"style="">String</span>>params=<spanclass="hljs-keyword"style="">new</span>HashMap<<spanclass="hljs-built_in"style="">String</span>,<spanclass="hljs-built_in"style="">String</span>>(); <spanclass="hljs-built_in"style="">Map</span>requestParams=request.getParameterMap(); <spanclass="hljs-keyword"style="">for</span>(Iteratoriter=requestParams.keySet().iterator();iter.hasNext();){ <spanclass="hljs-built_in"style="">String</span>name=(<spanclass="hljs-built_in"style="">String</span>)iter.next(); <spanclass="hljs-built_in"style="">String</span>[]values=(<spanclass="hljs-built_in"style="">String</span>[])requestParams.get(name); <spanclass="hljs-built_in"style="">String</span>valueStr=<spanclass="hljs-string"style="">""</span>; <spanclass="hljs-keyword"style="">for</span>(inti=<spanclass="hljs-number"style="">0</span>;i<values.length;i++){ valueStr=(i==values.length-<spanclass="hljs-number"style="">1</span>)?valueStr+values[i]:valueStr+values[i]+<spanclass="hljs-string"style="">","</span>; } params.put(name,valueStr); } <spanclass="hljs-built_in"style="">String</span>tradeNo=request.getParameter(<spanclass="hljs-string"style="">"out_trade_no"</span>); <spanclass="hljs-built_in"style="">String</span>tradeStatus=request.getParameter(<spanclass="hljs-string"style="">"trade_status"</span>); <spanclass="hljs-keyword"style="">if</span>(AlipayNotify.verify(params)){ <spanclass="hljs-keyword"style="">if</span>(tradeStatus.equals(<spanclass="hljs-string"style="">"TRADE_FINISHED"</span>)||tradeStatus.equals(<spanclass="hljs-string"style="">"TRADE_SUCCESS"</span>)){ System.out.println(<spanclass="hljs-string"style="">"ok!>>>>>>>>"</span>+tradeNo); } <spanclass="hljs-keyword"style="">return</span><spanclass="hljs-string"style="">"success"</span>; }<spanclass="hljs-keyword"style="">else</span>{ <spanclass="hljs-keyword"style="">return</span><spanclass="hljs-string"style="">"fail"</span>; } }</code> 12:使用springMVC封装写符合自己网站需求的代码。以下代码仅参考 全部都写在一个Controller里面 [java] view plain copy <codeclass="hljstypescript"style=""><spanclass="hljs-comment"style="">/** *支付宝Controller *@author宗潇帅 *@修改日期2014-9-25下午1:29:53 */</span> @Controller @RequestMapping(value=<spanclass="hljs-string"style="">"/aliapi"</span>) <spanclass="hljs-keyword"style="">public</span><spanclass="hljs-keyword"style="">class</span>AlipayApiController{ <spanclass="hljs-keyword"style="">private</span><spanclass="hljs-keyword"style="">static</span>Loglog=LogFactory.getLog(AlipayApiController.class); @RequestMapping(value=<spanclass="hljs-string"style="">"/index"</span>) <spanclass="hljs-keyword"style="">public</span><spanclass="hljs-built_in"style="">String</span>index(HttpServletRequestrequest, HttpServletResponseresponse){ <spanclass="hljs-keyword"style="">return</span><spanclass="hljs-string"style="">"web/pay/fund"</span>;<spanclass="hljs-comment"style="">//付款的页面。本页面是为了测试而使用的</span> } @RequestMapping(value=<spanclass="hljs-string"style="">"/deposit"</span>,method=RequestMethod.POST,produces=<spanclass="hljs-string"style="">"application/json"</span>) <spanclass="hljs-keyword"style="">public</span><spanclass="hljs-built_in"style="">String</span>deposit(HttpServletRequestrequest,HttpServletResponseresponse,Modelmodel)throwsException{ <spanclass="hljs-comment"style="">//PrintWriterout=response.getWriter();</span> <spanclass="hljs-built_in"style="">String</span>result=<spanclass="hljs-string"style="">""</span>; <spanclass="hljs-built_in"style="">Date</span>date=<spanclass="hljs-keyword"style="">new</span><spanclass="hljs-built_in"style="">Date</span>(); <spanclass="hljs-comment"style="">//支付类型</span> <spanclass="hljs-comment"style="">//必填,不能修改</span> <spanclass="hljs-built_in"style="">String</span>payment_type=<spanclass="hljs-string"style="">"1"</span>; <spanclass="hljs-comment"style="">//服务器异步通知页面路径</span> <spanclass="hljs-comment"style="">//需http://格式的完整路径,不能加?id=123这类自定义参数</span> <spanclass="hljs-built_in"style="">String</span>notify_url=<spanclass="hljs-string"style="">"http://192.168.0.222:8080/live/aliapi/async"</span>; <spanclass="hljs-comment"style="">//页面跳转同步通知页面路径</span> <spanclass="hljs-comment"style="">//需http://格式的完整路径,不能加?id=123这类自定义参数,不能写成http://localhost/</span> <spanclass="hljs-built_in"style="">String</span>return_url=<spanclass="hljs-string"style="">"http://192.168.0.222:8080/live/aliapi/return_url"</span>; <spanclass="hljs-comment"style="">//商户订单号.</span> <spanclass="hljs-comment"style="">//商户网站订单系统中唯一订单号,必填</span> <spanclass="hljs-comment"style="">//Stringout_trade_no=date.getTime()+"";</span> <spanclass="hljs-comment"style="">//订单名称</span> <spanclass="hljs-comment"style="">//必填</span> <spanclass="hljs-built_in"style="">String</span>subject=<spanclass="hljs-string"style="">"充值测试"</span>; <spanclass="hljs-comment"style="">//防钓鱼时间戳</span> <spanclass="hljs-comment"style="">//若要使用请调用类文件submit中的query_timestamp函数</span> <spanclass="hljs-built_in"style="">String</span>anti_phishing_key=<spanclass="hljs-string"style="">""</span>; <spanclass="hljs-comment"style="">//客户端的IP地址</span> <spanclass="hljs-comment"style="">//非局域网的外网IP地址,如:221.0.0.1</span> <spanclass="hljs-built_in"style="">String</span>exter_invoke_ip=<spanclass="hljs-string"style="">""</span>; <spanclass="hljs-built_in"style="">String</span>total_fee=ServletRequestUtils.getStringParameter(request,<spanclass="hljs-string"style="">"amount"</span>,<spanclass="hljs-string"style="">""</span>); <spanclass="hljs-built_in"style="">String</span>body=ServletRequestUtils.getStringParameter(request,<spanclass="hljs-string"style="">"body"</span>,<spanclass="hljs-string"style="">"test"</span>); <spanclass="hljs-comment"style="">//商品展示地址</span> <spanclass="hljs-built_in"style="">String</span>show_url=ServletRequestUtils.getStringParameter(request,<spanclass="hljs-string"style="">"show_url"</span>,<spanclass="hljs-string"style="">"http://www.elve.cn"</span>); <spanclass="hljs-comment"style="">//需以http://开头的完整路径,例如:http://www.xxx.com/myorder.html</span> Map<<spanclass="hljs-built_in"style="">String</span>,<spanclass="hljs-built_in"style="">String</span>>sParaTemp=<spanclass="hljs-keyword"style="">new</span>HashMap<<spanclass="hljs-built_in"style="">String</span>,<spanclass="hljs-built_in"style="">String</span>>(); sParaTemp.put(<spanclass="hljs-string"style="">"service"</span>,<spanclass="hljs-string"style="">"create_direct_pay_by_user"</span>);<spanclass="hljs-comment"style="">//接口服务----即时到账</span> sParaTemp.put(<spanclass="hljs-string"style="">"partner"</span>,AlipayConfig.partner);<spanclass="hljs-comment"style="">//支付宝PID</span> sParaTemp.put(<spanclass="hljs-string"style="">"_input_charset"</span>,AlipayConfig.input_charset);<spanclass="hljs-comment"style="">//统一编码</span> sParaTemp.put(<spanclass="hljs-string"style="">"payment_type"</span>,payment_type);<spanclass="hljs-comment"style="">//支付类型</span> sParaTemp.put(<spanclass="hljs-string"style="">"notify_url"</span>,notify_url);<spanclass="hljs-comment"style="">//异步通知页面</span> sParaTemp.put(<spanclass="hljs-string"style="">"return_url"</span>,return_url);<spanclass="hljs-comment"style="">//页面跳转同步通知页面</span> sParaTemp.put(<spanclass="hljs-string"style="">"seller_email"</span>,Constants.SELLER_EMAIL);<spanclass="hljs-comment"style="">//卖家支付宝账号</span> sParaTemp.put(<spanclass="hljs-string"style="">"out_trade_no"</span>,date.getTime()+payment_type);<spanclass="hljs-comment"style="">//商品订单编号</span> sParaTemp.put(<spanclass="hljs-string"style="">"subject"</span>,subject);<spanclass="hljs-comment"style="">//商品名称</span> sParaTemp.put(<spanclass="hljs-string"style="">"total_fee"</span>,total_fee);<spanclass="hljs-comment"style="">//价格</span> sParaTemp.put(<spanclass="hljs-string"style="">"body"</span>,body); sParaTemp.put(<spanclass="hljs-string"style="">"show_url"</span>,show_url); sParaTemp.put(<spanclass="hljs-string"style="">"anti_phishing_key"</span>,anti_phishing_key); sParaTemp.put(<spanclass="hljs-string"style="">"exter_invoke_ip"</span>,exter_invoke_ip); <spanclass="hljs-comment"style="">//建立请求</span> <spanclass="hljs-keyword"style="">try</span>{ <spanclass="hljs-built_in"style="">String</span>sHtmlText=AlipaySubmit.buildRequest(sParaTemp,<spanclass="hljs-string"style="">"post"</span>,<spanclass="hljs-string"style="">"确认"</span>); Gsongson=<spanclass="hljs-keyword"style="">new</span>GsonBuilder().setDateFormat(<spanclass="hljs-string"style="">"yyyy-MM-ddHH:mm:ss"</span>).create(); <spanclass="hljs-built_in"style="">String</span>s=gson.toJson(sHtmlText); model.addAttribute(<spanclass="hljs-string"style="">"sHtmlText"</span>,s); request.setAttribute(<spanclass="hljs-string"style="">"sHtmlText"</span>,s); result=<spanclass="hljs-string"style="">"{\"success\":true,\"msg\":\"跳转成功\"}"</span>; StringUtil.writeToWeb(sHtmlText,<spanclass="hljs-string"style="">"html"</span>,response); <spanclass="hljs-keyword"style="">return</span><spanclass="hljs-literal"style="">null</span>; }<spanclass="hljs-keyword"style="">catch</span>(Exceptione){ <spanclass="hljs-keyword"style="">if</span>(log.isErrorEnabled()){ log.error(<spanclass="hljs-string"style="">"ddddddddddddddddddddd"</span>); } result=<spanclass="hljs-string"style="">"{\"success\":false,\"msg\":\"跳转失败,请稍候再试!\"}"</span>; StringUtil.writeToWeb(result,<spanclass="hljs-string"style="">"html"</span>,response); <spanclass="hljs-keyword"style="">return</span><spanclass="hljs-literal"style="">null</span>; } } <spanclass="hljs-comment"style="">/** *同步通知的页面的Controller *@paramrequest *@paramresponse *@return *@author宗潇帅 */</span> @RequestMapping(value=<spanclass="hljs-string"style="">"/return_url"</span>) <spanclass="hljs-keyword"style="">public</span><spanclass="hljs-built_in"style="">String</span>Return_url(HttpServletRequestrequest,HttpServletResponseresponse){ <spanclass="hljs-keyword"style="">return</span><spanclass="hljs-string"style="">"web/pay/success"</span>; } <spanclass="hljs-comment"style="">/** *异步通知付款状态的Controller *@paramrequest *@paramresponse *@return *@author宗潇帅 */</span> @SuppressWarnings(<spanclass="hljs-string"style="">"rawtypes"</span>) @RequestMapping(value=<spanclass="hljs-string"style="">"/async"</span>,method=RequestMethod.GET) <spanclass="hljs-keyword"style="">public</span><spanclass="hljs-built_in"style="">String</span>async(HttpServletRequestrequest, HttpServletResponseresponse){ Map<<spanclass="hljs-built_in"style="">String</span>,<spanclass="hljs-built_in"style="">String</span>>params=<spanclass="hljs-keyword"style="">new</span>HashMap<<spanclass="hljs-built_in"style="">String</span>,<spanclass="hljs-built_in"style="">String</span>>(); MaprequestParams=request.getParameterMap(); <spanclass="hljs-keyword"style="">for</span>(Iteratoriter=requestParams.keySet().iterator();iter.hasNext();){ <spanclass="hljs-built_in"style="">String</span>name=(<spanclass="hljs-built_in"style="">String</span>)iter.next(); <spanclass="hljs-built_in"style="">String</span>[]values=(<spanclass="hljs-built_in"style="">String</span>[])requestParams.get(name); <spanclass="hljs-built_in"style="">String</span>valueStr=<spanclass="hljs-string"style="">""</span>; <spanclass="hljs-keyword"style="">for</span>(inti=<spanclass="hljs-number"style="">0</span>;i<values.length;i++){ valueStr=(i==values.length-<spanclass="hljs-number"style="">1</span>)?valueStr+values[i]:valueStr+values[i]+<spanclass="hljs-string"style="">","</span>; } params.put(name,valueStr); } <spanclass="hljs-built_in"style="">String</span>tradeNo=request.getParameter(<spanclass="hljs-string"style="">"out_trade_no"</span>); <spanclass="hljs-built_in"style="">String</span>tradeStatus=request.getParameter(<spanclass="hljs-string"style="">"trade_status"</span>); <spanclass="hljs-comment"style="">//StringnotifyId=request.getParameter("notify_id");</span> <spanclass="hljs-keyword"style="">if</span>(AlipayNotify.verify(params)){<spanclass="hljs-comment"style="">//验证成功</span> <spanclass="hljs-keyword"style="">if</span>(tradeStatus.equals(<spanclass="hljs-string"style="">"TRADE_FINISHED"</span>)||tradeStatus.equals(<spanclass="hljs-string"style="">"TRADE_SUCCESS"</span>)){ <spanclass="hljs-comment"style="">//要写的逻辑。自己按自己的要求写</span> log.error(<spanclass="hljs-string"style="">"ok......."</span>); System.out.println(<spanclass="hljs-string"style="">">>>>>充值成功"</span>+tradeNo); } <spanclass="hljs-keyword"style="">return</span><spanclass="hljs-string"style="">"web/pay/success"</span>; }<spanclass="hljs-keyword"style="">else</span>{<spanclass="hljs-comment"style="">//验证失败</span> <spanclass="hljs-keyword"style="">return</span><spanclass="hljs-string"style="">"web/pay/fail"</span>; } } }</code> 13:JSP付款页面表单提交数据并弹出付款页面 <%@pagecontentType="text/html;charset=UTF-8"%><!DOCTYPEhtml><htmlxmlns="http://www.w3.org/1999/xhtml"><head><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><%@includefile="/common/webMeta.jsp"%><title>www.elve.cn</title><metacontent="www.elve.cn"name="keywords"/><metacontent="www.elve.cn"name="description"/></head><scripttype="text/javascript">$(function(){$("#amount").focus();$("#doSubmit").click(function(){form1.submit();});});</script><body><formid="form1"action="${ctx}/aliapi/deposit"method="post"target="_blank"><tablecellpadding="10"><tr><td>充值测试</td><tdclass="balance"id="userBalance"></td></tr><tr><td><iclass="zfb"></i></td><tdstyle="padding-bottom:0px;">亲爱的<spanclass="suppliment_user"id="suppliment_user"></span>,您可以使用支付宝充值积善分,请填写以下信息</td></tr><tr><td></td><td>金额<inputtype="text"name="amount"id="amount"></td></tr><tr><td></td><td><ahref="javascript:void(0);"id="doSubmit"class="blank_btn">确认</a></td></tr></table></form></body></html> 如果以上还是有问题,那就直接去看支付宝接口文档吧! 原文地址http://www.bieryun.com/603.html

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

[IOS]陀螺仪和加速仪编程

如何实现iPhone的重力感应还有旋转感应,也就是术语上的陀螺仪和加速器?下面我们来用一个简单的Demo入门一下吧! 由于模拟器上不能运行这个,所以只能贴出代码,没有截图。 ViewController.h: #import <UIKit/UIKit.h> @interface BIDViewController : UIViewController<UIAccelerometerDelegate> @property (weak, nonatomic) IBOutlet UILabel *accelerometerLabel; @property (weak, nonatomic) IBOutlet UILabel *gyroscopeLabel; @end ViewController.m: #import "BIDViewController.h" #import <CoreMotion/CoreMotion.h> @interface BIDViewController () @property (strong, nonatomic) CMMotionManager *motionManager; @property (strong, nonatomic) NSOperationQueue *queue; @end @implementation BIDViewController - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.motionManager = [[CMMotionManager alloc] init]; self.queue = [[NSOperationQueue alloc] init]; if (self.motionManager.accelerometerAvailable) { self.motionManager.accelerometerUpdateInterval = 1.0 / 10.0; [self.motionManager startAccelerometerUpdatesToQueue:self.queue withHandler: ^(CMAccelerometerData *accelerometerData, NSError *error) { NSString *labelText; labelText = [NSString stringWithFormat: @"Accelerometer\n-----------\nx: %+.2f\ny: %+.2f\nz: %+.2f", accelerometerData.acceleration.x, accelerometerData.acceleration.y, accelerometerData.acceleration.z]; NSLog(@"%@",labelText); }]; } else { self.accelerometerLabel.text = @"This device has no accelerometer."; } if (self.motionManager.gyroAvailable) { self.motionManager.gyroUpdateInterval = 1.0 / 10.0; [self.motionManager startGyroUpdatesToQueue:self.queue withHandler: ^(CMGyroData *gyroData, NSError *error) { NSString *labelText; labelText = [NSString stringWithFormat: @"Gyroscope\n--------\nx: %+.2f\ny: %+.2f\nz: %+.2f", gyroData.rotationRate.x, gyroData.rotationRate.y, gyroData.rotationRate.z]; NSLog(@"%@",labelText); }]; } else { self.gyroscopeLabel.text = @"This device has no gyroscope"; } } @end 切记要导入CoreMotion.framework框架 本文转蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366411,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

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

Spring

Spring

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

Sublime Text

Sublime Text

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

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册