[代码] [Java]代码
01 | package com.ssh2.util; |
02 |
03 | public class Constants { |
04 |
05 | /** |
06 | * 页面显示的数字 最大到20 1...20 |
07 | */ |
08 | public static int MAX_PAGE_INDEX = 20 ; |
09 | |
10 |
11 | /** |
12 | * 每页的记录数 |
13 | */ |
14 | public static int PAGE_SIZE = 10 ; |
15 | } |
[图片] 11.JPG
![](http://static.oschina.net/uploads/code/201203/21162931_rQjy.jpg)
[图片] 22.JPG
![](http://static.oschina.net/uploads/code/201203/21162931_Wven.jpg)
[图片] 33.JPG
![](http://static.oschina.net/uploads/code/201203/21162931_vyI7.jpg)
[代码] 分页算法部分
01 | package com.ssh2.util; |
02 |
03 | /** |
04 | * 分页代码 |
05 | * |
06 | * @author 袁旭云 |
07 | * @version 1.0 |
08 | */ |
09 | public class Pager { |
10 | private int current; // 当前记录的位置 |
11 | private int size; // 数据总记录 |
12 | private int length; // 每页显示的记录条数 |
13 | private String url; // URL 调用Action里分页请求的URL |
14 | private String pageHeader; // 导航条前文字 |
15 |
16 | set get 及 构造省去了............... |
17 | 核心算法 |
18 | /** |
19 | * 返回分页导航条 |
20 | * |
21 | * @param Current |
22 | * int 当前记录的位置 |
23 | * @param size |
24 | * int 总记录数 |
25 | * @param length |
26 | * int 每页显示的记录数(步长) |
27 | * @param url |
28 | * String 调用Action里分页请求的URL |
29 | * @param pageHeader |
30 | * String 导航条前文字提示 |
31 | * @return String |
32 | */ |
33 |
34 | public String getPageNavigation() { |
35 | String pageNavigation = "" ; // 最终返回的分页导航条 |
36 | // 记录数超过一页,需要分页 |
37 | if (size > length) { |
38 | String pref; // 前缀 |
39 | if (url.indexOf( "?" ) > - 1 ) { |
40 | // 如果url中已经包含了其他的参数,就把current参数接在后面 |
41 | pref = "&" ; |
42 | } else { |
43 | // 如果url中没有别的参数 |
44 | pref = "?" ; |
45 | } |
46 | // 如果导航条包含header |
47 | if (pageHeader != null && pageHeader.length() > 0 ) { |
48 | pageNavigation = pageHeader + " : " ; |
49 | } |
50 | // 如果不是第一页,导航条将包含“<<”(第一页)和“<”(前一页) |
51 | if (current > 0 ) { |
52 | pageNavigation += "<a href='" + url + pref |
53 | + "current=0'>[首页]</a>\n" + "<a href='" + url + pref |
54 | + "current=" + (current - length) + "'>[<]</a>\n" ; |
55 | } |
56 | // 导航条中,排头的那一页的current值 |
57 | int startOffset; |
58 | // 位于导航条中间的那一页的current值(索引值) |
59 | int radius = Constants.MAX_PAGE_INDEX / 2 * length; |
60 | // 如果当前的current值小于索引值 |
61 | if (current < radius |
62 | || this .pageCount() <= Constants.MAX_PAGE_INDEX) { |
63 | // 那么第一页排头 |
64 | startOffset = 0 ; |
65 | } else if (current < size - radius) { |
66 | startOffset = current - radius; |
67 | } else { |
68 | startOffset = (size / length - Constants.MAX_PAGE_INDEX) |
69 | * length; |
70 | } |
71 | for ( int i = startOffset; i < size |
72 | && i < startOffset + Constants.MAX_PAGE_INDEX * length; i += length) { |
73 | if (i == current) { |
74 | // 当前页号,加粗显示 |
75 | pageNavigation += "<b>" + (i / length + 1 ) + "</b>\n" ; |
76 | } else { |
77 | // 其他页号,包含超链接 |
78 | pageNavigation += "<a href='" + url + pref + "current=" + i |
79 | + "'>" + (i / length + 1 ) + "</a>\n" ; |
80 | } |
81 | } |
82 | // 如果不是最后一页,导航条将包含“>”(下一页)和“>>”(最后一页) |
83 | if (current < size - length) { |
84 | pageNavigation += "<a href='" + url + pref + "current=" |
85 | + (current + length) + "'>[>]</a>\n" + "<a href='" |
86 | + url + pref + "current=" + lastPageOffset() |
87 | + "'>[尾页]</a>\n" ; |
88 | } |
89 | // System.out.println("radius : " + radius); |
90 | // System.out.println("start offset : " + startOffset); |
91 | return pageNavigation; |
92 | } |
93 | // 记录不超过一页,不需要分页 |
94 | else { |
95 | return "" ; |
96 | } |
97 | } |
[代码] 接口
01 | -----------------------dao包 |
02 | package com.ssh2.dao; |
03 |
04 | import java.util.List; |
05 |
06 | import com.ssh2.pojo.Car; |
07 | import com.ssh2.pojo.Vendor; |
08 |
09 | public interface CarDao { |
10 | /******* |
11 | * 获得所有厂商 |
12 | * @return |
13 | */ |
14 | public List<Vendor> getVdList(); |
15 | /****** |
16 | * 获得所有汽车 |
17 | * @return |
18 | */ |
19 | public List<Car> getAllCar(); |
20 | |
21 | /****** |
22 | * 根据编号获得汽车 |
23 | * @return |
24 | */ |
25 | public Car getCadById( int cid); |
26 | |
27 | /******* |
28 | * 保存一个汽车 |
29 | * @param car |
30 | */ |
31 | public void save(Car car); |
32 | |
33 | |
34 | /******* |
35 | * 删除一个汽车 |
36 | * @param car |
37 | */ |
38 | public void del( int cid); |
39 | |
40 | /******* |
41 | *更新 |
42 | * @param car |
43 | */ |
44 | public void update(Car car); |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | public List<Car> findAll( int offset, int length); |
51 | |
52 | |
53 | |
54 | |
55 | public int getRsCarCount() ; |
56 | |
57 | |
58 | |
59 | } |
60 | --------------------------------------- |
61 | package com.ssh2.dao; |
62 |
63 | import com.ssh2.pojo.Vendor; |
64 |
65 | public interface VendorDao { |
66 | |
67 | /**** |
68 | * 添加一个厂商 |
69 | * @param vd |
70 | */ |
71 | public void save(Vendor vd); |
72 |
73 | } |
[代码] 接口实现类
001 | ----------------------- |
002 | package com.ssh2.dao.impl; |
003 |
004 | import java.util.List; |
005 |
006 | import javax.annotation.Resource; |
007 |
008 | import org.hibernate.Query; |
009 | import org.hibernate.SessionFactory; |
010 | import org.springframework.transaction.annotation.Propagation; |
011 | import org.springframework.transaction.annotation.Transactional; |
012 |
013 | import com.ssh2.dao.CarDao; |
014 | import com.ssh2.pojo.Car; |
015 | import com.ssh2.pojo.Vendor; |
016 |
017 | @Transactional |
018 | public class CarDaoImpl implements CarDao { |
019 |
020 | @Resource private SessionFactory sessionFactory; |
021 | public void del( int cid) { |
022 | sessionFactory.getCurrentSession().delete( |
023 | sessionFactory.getCurrentSession().load(Car. class , cid) |
024 | ); |
025 |
026 | } |
027 |
028 | public List<Car> getAllCar() { |
029 | List<Car> car = sessionFactory.getCurrentSession().createQuery( "from Car" ).list(); |
030 | return car; |
031 | } |
032 |
033 | @Transactional (propagation =Propagation.NOT_SUPPORTED,readOnly = true ) |
034 | public Car getCadById( int cid) { |
035 | Car car =(Car) sessionFactory.getCurrentSession().get(Car. class , cid); |
036 | return car; |
037 | } |
038 |
039 | public List<Vendor> getVdList() { |
040 | List<Vendor> vd = sessionFactory.getCurrentSession().createQuery( "from Vendor" ).list(); |
041 | return vd; |
042 | } |
043 |
044 | public void save(Car car) { |
045 | sessionFactory.getCurrentSession().persist(car); |
046 |
047 | } |
048 |
049 | public void update(Car car) { |
050 | sessionFactory.getCurrentSession().merge(car); |
051 |
052 | } |
053 |
054 | public List<Car> findAll( int offset, int length) { |
055 |
056 | |
057 | String hql = "from Car" ; |
058 | |
059 | Query query =sessionFactory.getCurrentSession().createQuery(hql); |
060 | query.setFirstResult(offset); |
061 | query.setMaxResults(length); |
062 | List<Car> list = query.list(); |
063 | return list; |
064 | } |
065 |
066 | public int getRsCarCount() { |
067 | /* String hql = "select count(ca) from Car ca"; |
068 | Query query =sessionFactory.getCurrentSession().createQuery(hql); |
069 | int total = (Integer)query.uniqueResult();*/ |
070 | |
071 | |
072 | String hql = "select count(*) from Car" ; |
073 | |
074 | Query query =sessionFactory.getCurrentSession().createQuery(hql); |
075 | |
076 | int total = ( new Integer(query.uniqueResult().toString())); |
077 | |
078 | return total; |
079 | |
080 | } |
081 |
082 | } |
083 | ----------------- |
084 | package com.ssh2.dao.impl; |
085 |
086 | import javax.annotation.Resource; |
087 |
088 | import org.hibernate.SessionFactory; |
089 | import org.springframework.transaction.annotation.Transactional; |
090 |
091 | import com.ssh2.dao.VendorDao; |
092 | import com.ssh2.pojo.Vendor; |
093 |
094 | @Transactional |
095 | public class VendorDaoImpl implements VendorDao { |
096 |
097 | //用注解的方式注入sessionFactory |
098 | @Resource private SessionFactory sessionFactory; |
099 | |
100 | public void save(Vendor vd) { |
101 | System.out.println( "kkkkkk" ); |
102 | |
103 | sessionFactory.getCurrentSession().save(vd); |
104 |
105 | } |
106 |
107 | } |
[代码] service接口
01 | package com.ssh2.service; |
02 |
03 | import java.util.List; |
04 |
05 | import com.ssh2.pojo.Car; |
06 | import com.ssh2.pojo.Vendor; |
07 |
08 | public interface CarService { |
09 | |
10 | /******* |
11 | * 获得所有厂商 |
12 | * @return |
13 | */ |
14 | public List<Vendor> getVdList(); |
15 | /****** |
16 | * 获得所有汽车 |
17 | * @return |
18 | */ |
19 | public List<Car> getAllCar(); |
20 | |
21 | /****** |
22 | * 根据编号获得汽车 |
23 | * @return |
24 | */ |
25 | public Car getCadById( int cid); |
26 | |
27 | /******* |
28 | * 保存一个汽车 |
29 | * @param car |
30 | */ |
31 | public void save(Car car); |
32 | |
33 | |
34 | /******* |
35 | * 删除一个汽车 |
36 | * @param car |
37 | */ |
38 | public void del( int cid); |
39 | |
40 | /******* |
41 | *更新 |
42 | * @param car |
43 | */ |
44 | public void update(Car car); |
45 | |
46 | |
47 |
48 | |
49 |
50 | |
51 | |
52 | public List<Car> findAll( int offset, int length); |
53 | |
54 | |
55 | |
56 | |
57 | public int getRsCarCount() ; |
58 | } |
59 | ------ |
60 | package com.ssh2.service; |
61 |
62 | import com.ssh2.pojo.Vendor; |
63 |
64 | public interface VendorService { |
65 | |
66 | /**** |
67 | * 添加一个厂商 |
68 | * @param vd |
69 | */ |
70 | public void save(Vendor vd); |
71 |
72 | } |
[代码] service接口实现类
01 | package com.ssh2.service.impl; |
02 |
03 | import java.util.List; |
04 |
05 | import com.ssh2.dao.CarDao; |
06 | import com.ssh2.pojo.Car; |
07 | import com.ssh2.pojo.Vendor; |
08 | import com.ssh2.service.CarService; |
09 |
10 | public class CarServiceIMpl implements CarService { |
11 |
12 | private CarDao carDao; |
13 | |
14 | public void setCarDao(CarDao carDao) { |
15 | this .carDao = carDao; |
16 | } |
17 |
18 | public void del( int cid) { |
19 | carDao.del(cid); |
20 |
21 | } |
22 |
23 | public List<Car> getAllCar() { |
24 | |
25 | return carDao.getAllCar(); |
26 | } |
27 |
28 | public Car getCadById( int cid) { |
29 | |
30 | return carDao.getCadById(cid); |
31 | } |
32 |
33 | public List<Vendor> getVdList() { |
34 | |
35 | return carDao.getVdList(); |
36 | } |
37 |
38 | public void save(Car car) { |
39 | carDao.save(car); |
40 |
41 | } |
42 |
43 | public void update(Car car) { |
44 | carDao.update(car); |
45 |
46 | } |
47 |
48 | public List<Car> findAll( int offset, int length) { |
49 | // TODO Auto-generated method stub |
50 | return carDao.findAll(offset, length); |
51 | } |
52 |
53 | public int getRsCarCount() { |
54 | // TODO Auto-generated method stub |
55 | return carDao.getRsCarCount(); |
56 | } |
57 |
58 | } |
59 | ----------- |
60 | package com.ssh2.service.impl; |
61 |
62 | import com.ssh2.dao.VendorDao; |
63 | import com.ssh2.pojo.Vendor; |
64 | import com.ssh2.service.VendorService; |
65 |
66 | public class VendorServiceImpl implements VendorService{ |
67 |
68 | private VendorDao vendorDao ; |
69 | |
70 | |
71 | public void setVendorDao(VendorDao vendorDao) { |
72 | this .vendorDao = vendorDao; |
73 | } |
74 |
75 |
76 | public void save(Vendor vd) { |
77 | vendorDao.save(vd); |
78 | |
79 | } |
80 |
81 | } |
[代码] action
001 | package com.ssh2.web.action; |
002 |
003 | import java.util.List; |
004 |
005 | import javax.annotation.Resource; |
006 | import javax.servlet.http.HttpServletRequest; |
007 |
008 | import org.apache.struts2.ServletActionContext; |
009 | import org.springframework.context.annotation.Scope; |
010 |
011 | import com.opensymphony.xwork2.ActionContext; |
012 | import com.ssh2.pojo.Car; |
013 | import com.ssh2.pojo.Vendor; |
014 | import com.ssh2.service.impl.CarServiceIMpl; |
015 | import com.ssh2.util.Constants; |
016 | import com.ssh2.util.Pager; |
017 |
018 |
019 | public class CarlAction { |
020 | |
021 | @Resource private CarServiceIMpl carService ; |
022 | |
023 | private List<Car> cars; |
024 |
025 | public List<Car> getCars() { |
026 | return cars; |
027 | } |
028 |
029 | public void setCars(List<Car> cars) { |
030 | this .cars = cars; |
031 | } |
032 | |
033 | private Car car; |
034 |
035 | public Car getCar() { |
036 | return car; |
037 | } |
038 |
039 | public void setCar(Car car) { |
040 | this .car = car; |
041 | } |
042 | |
043 | |
044 | private List<Vendor> vendor; |
045 | |
046 | |
047 |
048 | public List<Vendor> getVendor() { |
049 | return vendor; |
050 | } |
051 |
052 | public void setVendor(List<Vendor> vendor) { |
053 | this .vendor = vendor; |
054 | } |
055 |
056 | |
057 | |
058 | |
059 | private int current; //起始记录的位置//每页显示的记录数 |
060 | |
061 | |
062 | |
063 | public int getCurrent() { |
064 | return current; |
065 | } |
066 |
067 | public void setCurrent( int current) { |
068 | this .current = current; |
069 | } |
070 | |
071 | /****** |
072 | * 全查询 |
073 | * @return |
074 | */ |
075 | public String getAll(){ |
076 | int offset = this .getCurrent(); |
077 | int pagesize = Constants.PAGE_SIZE; |
078 | this .cars = carService.findAll( this .current, pagesize); |
079 | |
080 | int size = carService.getRsCarCount(); |
081 | HttpServletRequest request=ServletActionContext.getRequest(); |
082 | String path=request.getRequestURI(); |
083 | String queryInfo=request.getQueryString(); |
084 | |
085 | |
086 | String url = "http://localhost:8080/SSH2/car/car_getAll.action" ; |
087 | Pager p = new Pager(offset, size, pagesize, url, "" ); |
088 | request.setAttribute( "pager" , p); |
089 | |
090 | request.setAttribute( "list" , this .cars); |
091 | |
092 | System.out.println(cars.size()); |
093 | return "list" ; |
094 | } |
095 | /****** |
096 | * 添加界面 |
097 | * @return |
098 | */ |
099 | public String addUI(){ |
100 | this .vendor = carService.getVdList(); |
101 | System.out.println( "厂商" +vendor.size()); |
102 | return "addUI" ; |
103 | } |
104 | /****** |
105 | * 添加 |
106 | * @return |
107 | */ |
108 | public String add(){ |
109 | carService.save(car); |
110 | return "add" ; |
111 | } |
112 | |
113 | |
114 | /****** |
115 | * 修改界面 |
116 | * @return |
117 | */ |
118 | public String updateUI(){ |
119 | |
120 | this .vendor = carService.getVdList(); |
121 | |
122 | Car carbyid =carService.getCadById( this .car.getCarid()); |
123 | this .setCar(carbyid); |
124 | // ActionContext.getContext().getSession().put("cars", carbyid); |
125 | return "updateUI" ; |
126 | } |
127 | /****** |
128 | * 修改 |
129 | * @return |
130 | */ |
131 | public String update(){ |
132 | |
133 | try { |
134 | Car carbyid =carService.getCadById( this .car.getCarid()); |
135 | carbyid.setCname( this .car.getCname()); |
136 | carbyid.setCtime( this .car.getCtime()); |
137 | carbyid.getVendor().setVid( this .car.getVendor().getVid()); |
138 | carService.update(carbyid); |
139 | } catch (Exception e) { |
140 | System.out.println( "错误" +e.getMessage()); |
141 | } |
142 | return "update" ; |
143 | } |
144 | /****** |
145 | * 删除 |
146 | * @return |
147 | */ |
148 | public String del(){ |
149 | carService.del( this .car.getCarid()); |
150 | |
151 | return "del" ; |
152 | } |
153 | |
154 |
155 | |
156 | public String toList() { |
157 | System.out.println( "lbubububu" ); |
158 | |
159 | int offset = this .getCurrent(); |
160 | int pagesize = Constants.PAGE_SIZE; |
161 | |
162 | List<Car> list = carService.findAll( 1 , pagesize); |
163 | |
164 | int size = carService.getRsCarCount(); |
165 | HttpServletRequest request=ServletActionContext.getRequest(); |
166 | String path=request.getRequestURI(); |
167 | String queryInfo=request.getQueryString(); |
168 | System.out.println(path); |
169 | System.out.println( "请求的URL" +path +queryInfo); |
170 | |
171 | String url = "http://localhost/SSH2/car/car_toList.action" ; |
172 | |
173 | System.out.println( "mmmm" +url); |
174 | Pager p = new Pager(offset, size, pagesize, url, "Page Navigation" ); |
175 | request.setAttribute( "pager" , p); |
176 | System.out.println( "11111" +p.getPageNavigation()); |
177 | request.setAttribute( "list" , list); |
178 | |
179 | return "lists" ; |
180 | } |
181 | |
182 | |
183 | |
184 | |
185 | } |
186 | ------------------ |
[代码] pojo
001 | package com.ssh2.pojo; |
002 |
003 |
004 |
005 | public class Car { |
006 |
007 | // Fields |
008 |
009 | private Integer carid; |
010 | private Vendor vendor; |
011 | private String cname; |
012 | private String ctime; |
013 |
014 | |
015 | public Car() { |
016 | } |
017 |
018 | |
019 | public Car(Vendor vendor, String cname, String ctime) { |
020 | this .vendor = vendor; |
021 | this .cname = cname; |
022 | this .ctime = ctime; |
023 | } |
024 |
025 | |
026 |
027 | public Integer getCarid() { |
028 | return this .carid; |
029 | } |
030 |
031 | public void setCarid(Integer carid) { |
032 | this .carid = carid; |
033 | } |
034 |
035 | public Vendor getVendor() { |
036 | return this .vendor; |
037 | } |
038 |
039 | public void setVendor(Vendor vendor) { |
040 | this .vendor = vendor; |
041 | } |
042 |
043 | public String getCname() { |
044 | return this .cname; |
045 | } |
046 |
047 | public void setCname(String cname) { |
048 | this .cname = cname; |
049 | } |
050 |
051 | public String getCtime() { |
052 | return this .ctime; |
053 | } |
054 |
055 | public void setCtime(String ctime) { |
056 | this .ctime = ctime; |
057 | } |
058 |
059 | } |
060 |
061 | ---------------- |
062 | package com.ssh2.pojo; |
063 |
064 | import java.util.HashSet; |
065 | import java.util.Set; |
066 |
067 |
068 |
069 | public class Vendor { |
070 |
071 | // Fields |
072 |
073 | private Integer vid; |
074 | private String vname; |
075 | private String remark; |
076 | @SuppressWarnings ( "unchecked" ) |
077 | private Set cars = new HashSet( 0 ); |
078 |
079 | // Constructors |
080 |
081 | |
082 | public Vendor() { |
083 | } |
084 |
085 | |
086 | public Vendor(String vname, String remark, Set cars) { |
087 | this .vname = vname; |
088 | this .remark = remark; |
089 | this .cars = cars; |
090 | } |
091 |
092 | // Property accessors |
093 |
094 | public Integer getVid() { |
095 | return this .vid; |
096 | } |
097 |
098 | public void setVid(Integer vid) { |
099 | this .vid = vid; |
100 | } |
101 |
102 | public String getVname() { |
103 | return this .vname; |
104 | } |
105 |
106 | public void setVname(String vname) { |
107 | this .vname = vname; |
108 | } |
109 |
110 | public String getRemark() { |
111 | return this .remark; |
112 | } |
113 |
114 | public void setRemark(String remark) { |
115 | this .remark = remark; |
116 | } |
117 |
118 | public Set getCars() { |
119 | return this .cars; |
120 | } |
121 |
122 | public void setCars(Set cars) { |
123 | this .cars = cars; |
124 | } |
125 |
126 | } |
[代码] xml
01 | <?xml version= "1.0" encoding= "utf-8" ?> |
02 | <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" |
03 | "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > |
04 | <!-- |
05 | Mapping file autogenerated by MyEclipse Persistence Tools |
06 | --> |
07 | <hibernate-mapping> |
08 | < class name= "com.ssh2.pojo.Car" table= "car" lazy= "false" > |
09 | <id name= "carid" type= "integer" > |
10 | <column name= "carid" /> |
11 | <generator class = "native" /> |
12 | </id> |
13 | <!-- 多个汽车对应一个厂商 --> |
14 | <many-to-one name= "vendor" class = "com.ssh2.pojo.Vendor" fetch= "select" > |
15 | <column name= "vid" /> |
16 | </many-to-one> |
17 | <property name= "cname" type= "string" > |
18 | <column name= "cname" length= "50" /> |
19 | </property> |
20 | <property name= "ctime" type= "string" > |
21 | <column name= "ctime" length= "20" /> |
22 | </property> |
23 | </ class > |
24 | </hibernate-mapping> |
25 |
26 | ----------------- |
27 | <?xml version= "1.0" encoding= "utf-8" ?> |
28 | <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" |
29 | "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > |
30 | <!-- |
31 | Mapping file autogenerated by MyEclipse Persistence Tools |
32 | --> |
33 | <hibernate-mapping> |
34 | < class name= "com.ssh2.pojo.Vendor" table= "vendor" lazy= "false" > |
35 | <id name= "vid" type= "integer" > |
36 | <column name= "vid" /> |
37 | <generator class = "native" /> |
38 | </id> |
39 | <property name= "vname" type= "string" > |
40 | <column name= "vname" length= "50" /> |
41 | </property> |
42 | <property name= "remark" type= "string" > |
43 | <column name= "remark" length= "100" /> |
44 | </property> |
45 | <set name= "cars" inverse= "true" > |
46 | <key> |
47 | <column name= "vid" /> |
48 | </key> |
49 | <!-- 一个厂商有多种汽车 --> |
50 | <one-to-many class = "com.ssh2.pojo.Car" /> |
51 | </set> |
52 | </ class > |
53 | </hibernate-mapping> |
http://www.oschina.net/code/snippet_251973_9435