涉及到spring配置redis 和示例代码

applicationContext.xml 这里网上有许多版本 ,但是copy过来不是版本不符就是各种找不到类

用到的版本

jedis-2.6.0.jar

spring-data-redis-1.4.1.RELEASE.jar

对应spring集成的版本是4.0

下面是 applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:use-pool="true"
p:host-name="111.111.111.111" p:port="6379" p:password="abc" />
<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory">
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="hashKeySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="hashValueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="stringSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
</bean>

下面是比较重要的Controller层实现的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.controller;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.service.TestService;
import com.util.alibaba.fastjson.JSON;
import com.util.alibaba.fastjson.JSONObject;
@Controller
public class TestController {
@Autowired
private TestService testService;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@RequestMapping("/index")
public ModelAndView index(HttpServletRequest request,
HttpServletResponse response, HttpSession session,
String pageNo,String pageCount, String name,
ModelMap modelMap) throws IOException, ParseException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
JSONObject json=new JSONObject();
if (pageNo == null || pageNo.equals("") || pageCount == null
|| pageCount.equals("")) {
pageNo = "1";
pageCount = "10";
}
if ((Integer.parseInt(pageNo)-1)*Integer.parseInt(pageCount)>210) {
pageNo="21";
pageNo="10";
}
if (name!=null&&!name.equals("")) {
if (name.contains("%")) {
modelMap.put("name", URLEncoder.encode(name, "UTF-8"));
name=URLDecoder.decode(URLDecoder.decode(name, "UTF-8"), "UTF-8");
}else {
modelMap.put("name", URLEncoder.encode(URLEncoder.encode(name, "UTF-8"), "UTF-8"));
}
modelMap.put("yname", URLDecoder.decode(name, "UTF-8"));
}else{
modelMap.put("name", "");
name="";
}
String tmpname=name;
if (tmpname.equals("")) {
tmpname="AllSerachResult";
}
Object redisname=redisTemplate.opsForValue().get(tmpname);
if (redisname!=null&&redisname.toString().length()>2) {
String Strname=redisname.toString().trim();
json=JSON.parseObject(Strname);
modelMap.addAllAttributes(json);
return new ModelAndView("/news", modelMap);
}
modelMap.put("pageNo", Integer.parseInt(pageNo));
modelMap.put("pageCount", Integer.parseInt(pageCount));
Long totleCount = testService.getCatsByUserCount(name);//TODO
if (totleCount % 10 != 0) {
totleCount = totleCount / 10 + 1;
} else {
totleCount = totleCount / 10;
}
List<Integer> totleCountList = new ArrayList<Integer>();
for (int i = 0; i < totleCount; i++) {
totleCountList.add(i + 1);
}
modelMap.put("totleCountList", totleCountList);
List<Map> list = testService.getCatsByUser(name,pageNo,pageCount);//TODO
modelMap.put("list", list);
json.putAll(modelMap);
redisTemplate.opsForValue().set(tmpname,json.toJSONString(), 10);
return new ModelAndView("/news", modelMap);
}
}

涉及到spring aop

下面是 applicationContext.xml

需要多配置两个读的数据源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->
<context:component-scan base-package="com" />
<!-- 配置数据源 destroy-method="close"-->
<!-- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
连接池中保留的最小连接数。
<property name="minPoolSize">
<value>5</value>
</property>
连接池中保留的最大连接数。Default: 15
<property name="maxPoolSize">
<value>30</value>
</property>
初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3
<property name="initialPoolSize">
<value>10</value>
</property>
最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0
<property name="maxIdleTime">
<value>60</value>
</property>
当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3
<property name="acquireIncrement">
<value>5</value>
</property>
JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0
<property name="maxStatements">
<value>0</value>
</property>
每60秒检查所有连接池中的空闲连接。Default: 0
<property name="idleConnectionTestPeriod">
<value>60</value>
</property>
定义在从数据库获取新连接失败后重复尝试的次数。Default: 30
<property name="acquireRetryAttempts">
<value>30</value>
</property>
获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
获取连接失败后该数据源将申明已断开并永久关闭。Default: false
<property name="breakAfterAcquireFailure">
<value>true</value>
</property>
因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
等方法来提升连接测试的性能。Default: false
<property name="testConnectionOnCheckout">
<value>false</value>
</property>
<property name="automaticTestTable">
<value>true</value>
</property>
</bean>
<bean id="dynamicDataSource" class="com.hyjf.datasource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="dataSourceWrite" key="dataSourceWrite"></entry>
<entry value-ref="dataSourceRead1" key="dataSourceRead1"></entry>
<entry value-ref="dataSourceRead2" key="dataSourceRead2"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSourceWrite">
</property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:Configuration.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sqlSessionTemplate"
class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
配置事务管理器
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />
通过AOP配置提供事务增强,让controller包下所有Bean的所有方法拥有事务
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethod"
expression=" execution(* com.controller.*..*(..))" />
<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice> -->
<!-- 主从分离根据方法名 -->
<!-- AOP式方法级权限检查 -->
<aop:config proxy-target-class="true"></aop:config>
<!-- service切面查询方法拦截 -->
<!-- <aop:config>
<aop:pointcut
expression="execution(* com..*Service.query*(..))"
id="readBeforeQuery" />
<aop:advisor advice-ref="beforeRead" pointcut-ref="readBeforeQuery" />
</aop:config>
<aop:config>
<aop:pointcut
expression="execution(* com..*Service.query*(..))"
id="readAfterQuery" />
<aop:advisor advice-ref="afterRead" pointcut-ref="readAfterQuery" />
</aop:config>
<aop:config>
<aop:pointcut
expression="execution(* com..*Service.get*(..))"
id="readBeforeGet" />
<aop:advisor advice-ref="beforeRead" pointcut-ref="readBeforeGet" />
</aop:config>
<aop:config>
<aop:pointcut
expression="execution(* com..*Service.get*(..))"
id="readAfterGet" />
<aop:advisor advice-ref="afterRead" pointcut-ref="readAfterGet" />
</aop:config>
<aop:config>
<aop:pointcut
expression="execution(* com..*Service.select*(..))"
id="readBeforeSelect" />
<aop:advisor advice-ref="beforeRead" pointcut-ref="readBeforeSelect" />
</aop:config>
<aop:config>
<aop:pointcut
expression="execution(* com..*Service.select*(..))"
id="readAfterSelect" />
<aop:advisor advice-ref="afterRead" pointcut-ref="readAfterSelect" />
</aop:config>
<aop:config>
<aop:pointcut
expression="execution(* com..*Service.count*(..))"
id="readBeforeCount" />
<aop:advisor advice-ref="beforeRead" pointcut-ref="readBeforeCount" />
</aop:config>
<aop:config>
<aop:pointcut
expression="execution(* com..*Service.count*(..))"
id="readAfterCount" />
<aop:advisor advice-ref="afterRead" pointcut-ref="readAfterCount" />
</aop:config>
<aop:config>
<aop:pointcut
expression="execution(* com..*Service.search*(..))"
id="readBeforeCountSearch" />
<aop:advisor advice-ref="beforeRead" pointcut-ref="readBeforeCountSearch" />
</aop:config>
<aop:config>
<aop:pointcut
expression="execution(* com..*Service.search*(..))"
id="readAfterCountSearch" />
<aop:advisor advice-ref="afterRead" pointcut-ref="readAfterCountSearch" />
</aop:config> -->
</beans>

下面是比较重要的datasource实现的代码
DynamicDataSource.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
* Copyright(c) 2012-2014 JD Pharma.Ltd. All Rights Reserved.
*/
package com.datasource;
import java.util.Random;
import java.util.ResourceBundle;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
*
* 此处为类说明
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
public static String[] dataSourceArray;
public static String randomInt;
public static final Random random = new Random();
static {
ResourceBundle rb = ResourceBundle.getBundle("datasource");
randomInt = rb.getString("datasource.read.randomInt");
dataSourceArray = rb.getString("datasource.read").split(",");
}
@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getCustomerType();
}
public static String getRandomReadDataSource() {
return dataSourceArray[random.nextInt(Integer.parseInt(randomInt))];
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
* Copyright(c) 2012-2014 JD Pharma.Ltd. All Rights Reserved.
*/
package com.datasource;
/**
*
* 此处为类说明
*/
public class DatabaseContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setCustomerType(String customerType) {
contextHolder.set(customerType);
}
public static String getCustomerType() {
return contextHolder.get();
}
public static void clearCustomerType() {
contextHolder.remove();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
* Copyright(c) 2012-2014 JD Pharma.Ltd. All Rights Reserved.
*/
package com.datasource.aop;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.stereotype.Component;
import com.datasource.DatabaseContextHolder;
/**
*
* 清除当前绑定的数据源
* @author renxingchen
*/
@Component("afterRead")
public class AfterReadAdvice implements AfterReturningAdvice {
/**
*
* 方法执行完毕清除当前绑定的数据源
* @param returnValue
* @param method
* @param args
* @param target
* @throws Throwable
* @see org.springframework.aop.AfterReturningAdvice#afterReturning(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
*/
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
DatabaseContextHolder.clearCustomerType();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*
* Copyright(c) 2012-2014 JD Pharma.Ltd. All Rights Reserved.
*/
package com.datasource.aop;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;
import com.datasource.DatabaseContextHolder;
import com.datasource.DynamicDataSource;
/**
*
* 动态进行数据源的切换
*/
@Component("beforeRead")
public class BeforeReadAdvice implements MethodBeforeAdvice {
/**
*
* 动态进行数据源的切换
* @author
* @param method
* @param args
* @param target
* @throws Throwable
* @see org.springframework.aop.MethodBeforeAdvice#before(java.lang.reflect.Method,
* java.lang.Object[], java.lang.Object)
*/
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
String dataSourceName = DynamicDataSource.getRandomReadDataSource();
DatabaseContextHolder.setCustomerType(dataSourceName);
}
}

datasource.properties

1
2
datasource.read=dataSourceRead1,dataSourceRead2
datasource.read.randomInt=2

java反射 获取 /List<实体> objData 泛型后的属性值,clazz为实体类

//List<实体> objData ,实体.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void getProperties( List<?> objData, Class clazz) {
//java反射调用get方法获取对象里的值
Field[] obj=clazz.getDeclaredFields();
//循环写入表中数据
for (int i = 0; i < objData.size(); i++) {
//循环插值
int cellcount=0;
for (int j = 0; j < obj.length; j++) {
String tmpname="get"+(obj[j].getName().substring(0, 1)).toUpperCase()+obj[j].getName().substring(1,obj[j].getName().length());
Object object= clazz.newInstance();
object = objData.get(i);
Method m1 = clazz.getDeclaredMethod(tmpname);
Object result= m1.invoke(object);
System.out.println(result);
}
}
}

可以导出List<实体>、List、List<实体包含实体> 三种类型的数据

调用代码 (最下面为工具类)

导出List<实体>:

response 为 HttpServletResponse ,如果查出的字段全部导出的话 tmarray为null

1
2
3
4
5
6
List<BorrowCreditCustomize> recordList = XXXXX;//赋值
//导出列表
String[] keys = new String[] { "编号", "用户名","状态"};
String tmarray=",creditNid,username,creditStatusName,";
JxlExcelUtils.exportexcle(response, "列表", recordList, "work", keys,BorrowCreditCustomize.class,null,tmarray);
return null;

导出List<实体包含实体>:

1
2
3
4
5
6
7
8
9
List<AdminBorrowCreditRepayCustomize> recordList = 查出的数据赋值;
//导出列表
String[] keys = new String[] { "借款编号", "应还日期"};
//包含的内部实体
Class[] contantsClass=new Class[]{CreditRepay.class,Borrow.class};
//想要的字段 全要 是null
String tmarray=",borrowNid,addip,";
JxlExcelUtils.exportexcle(response, "详情列表", recordList, "work", keys,AdminBorrowCreditRepayCustomize.class,contantsClass,tmarray);
return null;

导出List

注意 Hap转换成有序的LinkedHashMap再调用,key是取查出数据最多的行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
for (int i = 0; i < list.size()-1; i++) {
Object[] ss= list.get(i).keySet().toArray();
Object[] vv= list.get(i+1).keySet().toArray();
if(key==null){
if(ss.length>=vv.length){
key=ss;
}else{
key=vv;
}
}else{
if(key.length<vv.length){
key=vv;
}
}
}
}
Map<String, String> mapParm= new HashMap<String, String>();
mapParm.put("dlrs", "队列人数");
mapParm.put("yhm", "用户名");
mapParm.put("sfkq", "是否开启");
mapParm.put("tblx", "投标类型");
mapParm.put("hkfs", "还款方式");
mapParm.put("tbed", "投标额度");
for (int i = 0; i < key.length; i++) {
if(mapParm.get(key[i])!=null){
key[i]=mapParm.get(key[i]);
}
}
JxlExcelUtils.exportexcle(response, "自投条件数据", list, "work", key,null,null,null);
return null;

工具类

JxlExcelUtils.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
package com.hyjf.common.util;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import jxl.SheetSettings;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Colour;
import jxl.format.VerticalAlignment;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
/**
* jxl导出excel
* @author zhouxiaoshuai
* @date 2016-06-01
*/
public class JxlExcelUtils {
/**
* @author
* @param objData 导出内容数组
* @param sheetName 导出工作表的名称
* @param contantsClass
* @param objects 导出Excel的表头数组
* @return
*/
public static int exportToExcel(HttpServletResponse response, List<?> objData, String sheetName,Object[] key,Class clazz, Class[] contantsClass,String tmarray) {
int flag = 0;
//声明工作簿jxl.write.WritableWorkbook
WritableWorkbook wwb;
try {
//根据传进来的file对象创建可写入的Excel工作薄
OutputStream os = response.getOutputStream();
wwb = Workbook.createWorkbook(os);
/*
* 创建一个工作表、sheetName为工作表的名称、"0"为第一个工作表
* 打开Excel的时候会看到左下角默认有3个sheet、"sheet1、sheet2、sheet3"这样
* 代码中的"0"就是sheet1、其它的一一对应。
* createSheet(sheetName, 0)一个是工作表的名称,另一个是工作表在工作薄中的位置
*/
WritableSheet ws = wwb.createSheet(sheetName, 0);
SheetSettings ss = ws.getSettings();
ss.setVerticalFreeze(1);//冻结表头
WritableFont font1 =new WritableFont(WritableFont.createFont("微软雅黑"), 10 ,WritableFont.BOLD);
WritableFont font2 =new WritableFont(WritableFont.createFont("微软雅黑"), 9 ,WritableFont.NO_BOLD);
WritableCellFormat wcf = new WritableCellFormat(font1);
WritableCellFormat wcf2 = new WritableCellFormat(font2);
WritableCellFormat wcf3 = new WritableCellFormat(font2);//设置样式,字体
//创建单元格样式
//WritableCellFormat wcf = new WritableCellFormat();
//背景颜色
wcf.setBackground(jxl.format.Colour.YELLOW);
wcf.setAlignment(Alignment.CENTRE); //平行居中
wcf.setVerticalAlignment(VerticalAlignment.CENTRE); //垂直居中
wcf3.setAlignment(Alignment.CENTRE); //平行居中
wcf3.setVerticalAlignment(VerticalAlignment.CENTRE); //垂直居中
wcf3.setBackground(Colour.LIGHT_ORANGE);
wcf2.setAlignment(Alignment.CENTRE); //平行居中
wcf2.setVerticalAlignment(VerticalAlignment.CENTRE); //垂直居中
/*
* 这个是单元格内容居中显示
* 还有很多很多样式
*/
wcf.setAlignment(Alignment.CENTRE);
//判断一下表头数组是否有数据
if (key != null && key.length > 0) {
int tmp=0;
//循环写入表头
for (int i = 0; i < key.length; i++) {
/*
* 添加单元格(Cell)内容addCell()
* 添加Label对象Label()
* 数据的类型有很多种、在这里你需要什么类型就导入什么类型
* 如:jxl.write.DateTime 、jxl.write.Number、jxl.write.Label
* Label(i, 0, columns[i], wcf)
* 其中i为列、0为行、columns[i]为数据、wcf为样式
* 合起来就是说将columns[i]添加到第一行(行、列下标都是从0开始)第i列、样式为什么"色"内容居中
*/
String str=key[i].toString();
if(!str.equals("key")){
if(tmp==1){
ws.addCell(new Label(i-1, 0, str, wcf));
}else{
ws.addCell(new Label(i, 0, str, wcf));
}
}else{
tmp=1;
}
}
//判断表中是否有数据
if (objData != null && objData.size() > 0) {
if (clazz!=null) {
//处理list<实体>的导出
try {
Field[] obj=clazz.getDeclaredFields();
//循环写入表中数据
for (int i = 0; i < objData.size(); i++) {
//循环插值
int cellcount=0;
for (int j = 0; j < obj.length; j++) {
if (contantsClass!=null) {
int flag2=0;
//如果实体里包含实体
for (int j2 = 0; j2 < contantsClass.length; j2++) {
if (contantsClass[j2].getName().toLowerCase().equals(obj[j].getName().toLowerCase())) {
//java反射调用get方法获取对象里的值
String tmpname="get"+(obj[j].getName().substring(0, 1)).toUpperCase()+obj[j].getName().substring(1,obj[j].getName().length());
Object object= clazz.newInstance();
object = objData.get(i);
Method m1 = clazz.getDeclaredMethod(tmpname);
//内部实体
Object inside= contantsClass[j2].newInstance();
inside= m1.invoke(object);
Field[] insideField=contantsClass[j2].getDeclaredFields();
//写入内部实体的字段
for (int k = 0; k < insideField.length; k++) {
if (tmarray==null||tmarray.contains(","+insideField[k].getName()+",")) {
String tmpname2="get"+(insideField[k].getName().substring(0, 1)).toUpperCase()+insideField[k].getName().substring(1,obj[j].getName().length());
Method m2 = contantsClass[j2].getDeclaredMethod(tmpname2);
Object result2= m2.invoke(inside);
ws.addCell(new Label(cellcount,i+1,String.valueOf(result2)));
cellcount++;
}
}
flag2=1;
}
}
//处理不是实体的情况
if (flag2==0) {
if (tmarray==null||tmarray.contains(","+obj[j].getName()+",")) {
//java反射调用get方法获取对象里的值
String tmpname="get"+(obj[j].getName().substring(0, 1)).toUpperCase()+obj[j].getName().substring(1,obj[j].getName().length());
Object object= clazz.newInstance();
object = objData.get(i);
Method m1 = clazz.getDeclaredMethod(tmpname);
Object result= m1.invoke(object);
ws.addCell(new Label(cellcount,i+1,String.valueOf(result)));
cellcount++;
}
}
}else {
if (tmarray==null||tmarray.contains(","+obj[j].getName()+",")) {
//java反射调用get方法获取对象里的值
String tmpname="get"+(obj[j].getName().substring(0, 1)).toUpperCase()+obj[j].getName().substring(1,obj[j].getName().length());
Object object= clazz.newInstance();
object = objData.get(i);
Method m1 = clazz.getDeclaredMethod(tmpname);
Object result= m1.invoke(object);
ws.addCell(new Label(cellcount,i+1,String.valueOf(result)));
cellcount++;
}
}
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} else {
//处理list<LinkedHashMap>
//循环写入表中数据
for (int i = 0; i < objData.size(); i++) {
//转换成map集合{activyName:测试功能,count:2}
LinkedHashMap<String, Object> map = (LinkedHashMap<String, Object>)objData.get(i);
//循环输出map中的子集:既列值
int j=0;
for(Object o:map.keySet()){
//ps:因为要“”通用”“导出功能,所以这里循环的时候不是get("Name"),而是通过map.get(o)
ws.addCell(new Label(j,i+1,String.valueOf(map.get(o))));
j++;
}
}
}
}else{
flag = -1;
}
//写入Exel工作表
wwb.write();
//关闭Excel工作薄对象
wwb.close();
//关闭流
os.flush();
os.close();
os =null;
}
}catch (IllegalStateException e) {
System.err.println(e.getMessage());
}
catch (Exception ex) {
flag = 0;
ex.printStackTrace();
}
return flag;
}
/**
* 下载excel
* @author
* @param response
* @param filename 文件名 ,如:20110808.xls
* @param listData 数据源
* @param sheetName 表头名称
* @param key 列名称集合,如:{物品名称,数量,单价}
* @param clazz 传入实体的class (如果list里是linkedmap则传null)
* @param contantsClass 用于实体内包含实体的数组 (如果list里是linkedmap则传null,如果实体里没有包含的实体也传null)
* @param tmarray 以逗号间隔要包含导出的字段
*/
public static void exportexcle(HttpServletResponse response,String filename,List<?> listData,String sheetName,String[] key,Class clazz,Class[] contantsClass,String tmarray)
{
//调用上面的方法、生成Excel文件
response.setContentType("application/vnd.ms-excel");
//response.setHeader("Content-Disposition", "attachment;filename="+filename);
try {
response.setHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("gb2312"), "ISO8859-1") + ".xls");
exportToExcel(response, listData, sheetName, key ,clazz,contantsClass,tmarray);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public static String getEncoding(String str) {
String encode = "GB2312";
try {
if (str.equals(new String(str.getBytes(encode), encode))) {
String s = encode;
return s;
}
} catch (Exception exception) {
}
encode = "ISO-8859-1";
try {
if (str.equals(new String(str.getBytes(encode), encode))) {
String s1 = encode;
return s1;
}
} catch (Exception exception1) {
}
encode = "UTF-8";
try {
if (str.equals(new String(str.getBytes(encode), encode))) {
String s2 = encode;
return s2;
}
} catch (Exception exception2) {
}
encode = "GBK";
try {
if (str.equals(new String(str.getBytes(encode), encode))) {
String s3 = encode;
return s3;
}
} catch (Exception exception3) {
}
return "";
}
}

顺带下maven的依赖

1
2
3
4
5
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6</version>
</dependency>

涉及到springmvc自动注入和模糊查询分页

applicationContext.xml 这里网上有许多版本 ,但是copy过来不是版本不符就是各种找不到类

用到的版本

mongodb2.10.jar

mongo-java-driver-3.0.1.jar

对应spring集成的版本必须是4.0以上

mongodb和spring jar:https://yun.baidu.com/share/link?shareid=3559056118&uk=958682606

下面是 applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:defaultEncoding="utf-8" />
<mongo:mongo host="host" port="port"/>
<mongo:db-factory dbname="XXX"
username="XXX"
password="XXX"
mongo-ref="mongo"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>
</beans>

下面是比较重要的daoImpl实现层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
TestDaoImpl.java
package com.dao.implement;
import java.sql.Array;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import com.dao.TestDao;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MapReduceCommand;
import com.mongodb.MapReduceOutput;
@Repository("TestDaoImpl")
public class TestDaoImpl implements TestDao {
/* @Autowired
private SqlSessionTemplate sqlSessionTemplate;*/
@Autowired
private MongoTemplate mongoTemplate;
private static String DBNAME_BAIDUURL="baiduurl";
private static String DBNAME_P2PURL="projectlist";
@Override
public List<Map> getCatsByUser(String id, String pageNo, String pageCount) {
/* 1、完全匹配 Pattern pattern = Pattern.compile("^name$", Pattern.CASE_INSENSITIVE);
2、右匹配 Pattern pattern = Pattern.compile("^.*name$", Pattern.CASE_INSENSITIVE);
3、左匹配 Pattern pattern = Pattern.compile("^name.*$", Pattern.CASE_INSENSITIVE);
4、模糊匹配 Pattern pattern = Pattern.compile("^.*name8.*$", Pattern.CASE_INSENSITIVE);*/
Pattern pattern = Pattern.compile("^.*"+id+".*$", Pattern.CASE_INSENSITIVE);
Date date=new Date();
List<Map> list=mongoTemplate.find(new Query(new Criteria("projectTitle").regex(pattern))
.skip((Integer.parseInt(pageNo)-1)*Integer.parseInt(pageCount))
.limit(Integer.parseInt(pageCount)), Map.class,DBNAME_P2PURL);
System.out.println(new Date()+":关键词:"+id+":分页:"+pageNo+","+pageCount+":查询耗时"+(new Date().getTime()-date.getTime())/1000);
return list;
/* Date date1=new Date();
String map = "function(){emit(this.name,this.url);}";
String reduce = "function(key, values) { " +
"var sum = 0; " +
"values.forEach(function(doc) { " +
"sum += 1; "+
"}); " +
"return {baiduurl: sum};} ";
//另一种方法
//com.mongodb.MapReduceOutput.getDuration() 找不到此方法
MapReduceResults<Map> mrrList=mongoTemplate.mapReduce(
new Query(new Criteria("name").regex(pattern)),
"baiduurl",
map,
reduce, Map.class);*/
/* DBCollection baiduurl = mongoTemplate.getCollection("baiduurl");
MapReduceCommand cmd = new MapReduceCommand(baiduurl, map, reduce,
null, MapReduceCommand.OutputType.INLINE, null );
MapReduceOutput out = baiduurl.mapReduce(cmd);
System.out.println("用mapreduce的查询耗时"+(new Date().getTime()-date1.getTime())/1000);*/
}
@Override
public Long getCatsByUserCount(String name) {
Pattern pattern = Pattern.compile("^.*"+name+".*$", Pattern.CASE_INSENSITIVE);
Long lo=mongoTemplate.count(new Query(new Criteria("projectTitle").regex(pattern)),DBNAME_P2PURL);
if (lo>210) {
lo=210l;
}
return lo;
}
}

之前的php项目全是””空串没有null。。。。。改为java做后台就造成了 这个问题

解决方法和网上的 不太一样 因为SerializerProvider 为StdSerializerProvider的父类,直接从SerializerProvider .setNullValueSerializer()方法 不允许 所以通过子类StdSerializerProvider调用此方法

applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
<property name="objectMapper">
<bean class="com.interceptor.ObjectMappingCustomer"></bean>
</property>
</bean>
</list>
</property>
</bean>

ObjectMappingCustomer.java

package com.interceptor;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.io.IOException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.ser.StdSerializerProvider;
public class ObjectMappingCustomer extends ObjectMapper
{
public ObjectMappingCustomer()
{
super();
// 允许单引号
this.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 字段和值都加引号
this.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 数字也加引号
this.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true);
this.configure(JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS, true);
// 空值处理为空串
StdSerializerProvider sp = (StdSerializerProvider) this.getSerializerProvider();
sp.setNullValueSerializer(new JsonSerializer<Object>(){
@Override
public void serialize(Object value, JsonGenerator jg,
SerializerProvider sp) throws IOException,
JsonProcessingException {
jg.writeString("");
}
});
}
}

然后在springmvc controller里加 @ResponseBody注解就可以了

需要jackson-all.jar

其实步骤就是前台授权页 返回给咱们code->根据code获取access_token和openid和unionid->通过access_token和openid获取用户信息 然后把这些参数拼成xml 发送到https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack 具体见正文

这里springmvc的配置 请见我别的文章http://my.oschina.net/angleshuai/blog/410960

这里只写微信相关的代码(相关jar包和源码会在最下面为大家呈上)

前台可以引导用户到此页授权scope参数中的snsapi_base和snsapi_userinfo。 redirect_uri就是下面/hongbao/index的连接

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=/hongbao/index&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

首先放上根据code获取access_token和openid和unionid的代码

@RequestMapping("/hongbao/index")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@ResponseBody
public Object hongbaoIndex(String code,String STATE,HttpServletRequest request,
HttpServletResponse response, HttpSession session) throws Exception {
if(code==null){
return "code为空";
}
Map<String , Object> map= new HashMap<String, Object>();
URL url=new URL("https://api.weixin.qq.com/sns/oauth2/access_token?appid="+WeiXinRequest.appId+"&secret="+WeiXinRequest.appSecret+"&code="+code+"&grant_type=authorization_code");
System.out.println("code+++++++++++++++++++++ "+code);
System.out.println("url+++++++++++++++++++++ "+url);
JSONObject param= WeiXinRequest.getConnection(url);
System.out.println("JSONparam+++++++++++++++++++++ "+param);
String access_token=param.getString("access_token");
String refresh_token=param.getString("refresh_token");//刷新token
String openid=param.getString("openid");
String scope=param.getString("scope");
String unionid=param.getString("unionid");
System.out.println("access_token+++++++++++++++++++++ "+access_token);
System.out.println("openid+++++++++++++++++++++ "+openid);
System.out.println("unionid+++++++++++++++++++++ "+unionid);
if(access_token==null){
return "access_token为空";
}else if(openid==null){
return "access_token为空";
}
map.put("access_token", access_token);
map.put("openid", openid);
map.put("refresh_token", access_token);
map.put("unionid", access_token);
//前台可以验证https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID 是否有效
return map;
}

那个getconnection的方法

public static JSONObject getConnection(URL url) throws IOException {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("GET");
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.connect();
JSONObject jsono = new JSONObject(new JSONTokener(
new InputStreamReader(connection.getInputStream())));
connection.disconnect();
return jsono;
}

然后是比较关键的发红包的方法

@RequestMapping("/hongbao")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
@ResponseBody
public Object hongbao(String access_token,String re_openid,String total_amount,HttpServletRequest request,
HttpServletResponse response, HttpSession session) throws Exception {
URL urlUnionInfo=new URL("https://api.weixin.qq.com/sns/userinfo?access_token="+access_token+"&openid="+re_openid+"&lang=zh_CN");
String urlhongbao="https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack" ;
JSONObject UnionInfo= WeiXinRequest.getConnection(urlUnionInfo);
String nick_name ="";
if(UnionInfo.toString().contains("nickname")){
nick_name=UnionInfo.getString("nickname");
}else{
}
/*String city =UnionInfo.getString("city");
String province =UnionInfo.getString("province");
String country =UnionInfo.getString("country");
String headimgurl =UnionInfo.getString("country");//用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
*/
//解决XStream对出现双下划线的bug
XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
xStreamForRequestPostData.alias("xml", xml.class);
Random random = new Random();
SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMdd");
String mch_billno =WeiXinRequest.mch_id+sdf.format(new Date())+random.nextInt();
String client_ip = request.getHeader("X-Forwarded-For");
if (client_ip == null || client_ip.length() == 0
|| "unknown".equalsIgnoreCase(client_ip)) {
client_ip = request.getHeader("Proxy-Client-IP");
}
if (client_ip == null || client_ip.length() == 0
|| "unknown".equalsIgnoreCase(client_ip)) {
client_ip = request.getHeader("WL-Proxy-Client-IP");
}
if (client_ip == null || client_ip.length() == 0
|| "unknown".equalsIgnoreCase(client_ip)) {
client_ip = request.getRemoteAddr();
}
if(client_ip.length()>15){
client_ip=client_ip.split(",")[0];
}
Map<String, String> map=new HashMap<String, String>();
map.put("nick_name", nick_name);
map.put("nonce_str", random.nextInt(1000000)+"");
map.put("wxappid", WeiXinRequest.appId);
map.put("mch_id", WeiXinRequest.mch_id);
map.put("mch_billno", mch_billno);
map.put("wxappid", WeiXinRequest.appId);
map.put("send_name", "优卖网");
map.put("re_openid", re_openid);
map.put("total_amount", total_amount);
map.put("min_value", total_amount);
map.put("max_value", total_amount);
map.put("total_num", "1");
map.put("wishing", "感谢您对优卖网的支持!");
map.put("client_ip",client_ip);
map.put("act_name", "优卖发钱活动");
map.put("remark", "不要白不要");
map.put("logo_imgurl","http://umaiw.com/favicon.ico");
map.put("share_content", "快点接啊过24小时就没啦");
map.put("share_url", "http://www.baidu.com");
map.put("share_imgurl", "https://wx.baidu.com/mch/img/ico-logo.png");
//string签名
Set<String> sr= map.keySet();
Object[] oj= sr.toArray();
Arrays.sort(oj);
String stringA="";
for(int i=0;i<oj.length;i++){
stringA+=oj[i]+"="+map.get(oj[i]);
if(i!=(oj.length-1)){
stringA+="&&";
}
}
String stringSignTemp= stringA+"&key="+WeiXinRequest.key;
String sign=MD5Ecode.getMD5Str(stringSignTemp).toUpperCase();
//发送xml
xml xml=new xml(WeiXinRequest.appId,
WeiXinRequest.mch_id,
random.nextInt(1000000)+"",
sign,
mch_billno,
"",
nick_name,
"优卖网",
re_openid,
total_amount,
total_amount,
total_amount,
"1",
"感谢您对优卖网的支持!",
client_ip,
"优卖发钱活动",
"不要白不要",
"http://umaiw.com/favicon.ico",
"快点接啊过24小时就没啦",
"http://www.baidu.com",
"https://wx.baidu.com/mch/img/ico-logo.png");
//将要提交给API的数据对象转换成XML格式数据Post给API
String postDataXML = xStreamForRequestPostData.toXML(xml);
System.out.println("发送的xml++++++++++++++++++++++++++++++++++"+postDataXML);
String result = null;
HttpPost httpPost = new HttpPost(urlhongbao);
//得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
httpPost.addHeader("Content-Type", "text/xml");
httpPost.setEntity(postEntity);
System.out.println("executing request" + httpPost.getRequestLine());
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File(WeiXinRequest.certLocalPath));//加载本地的证书进行https加密传输
try {
keyStore.load(instream,WeiXinRequest.certPassword.toCharArray());//设置证书密码
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} finally {
instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, WeiXinRequest.certPassword.toCharArray())
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
//根据默认超时限制初始化requestConfig //连接超时时间,默认10秒 //传输超时时间,默认30秒
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(30000).build();
//设置请求器的配置
httpPost.setConfig(requestConfig);
try {
HttpResponse response1 = httpClient.execute(httpPost);
HttpEntity entity = response1.getEntity();
result = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
httpPost.abort();
}
return result;
}

其中的参数含义大家可以参考http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html 这个微信开发文档

证书什么的 大家去申请微信支付 通过就会给你了

然后是转xml的实体(这里用的xstream来实体转xml的)

com.model;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
public class xml {
private String wxappid;
private String mch_id;
private String nonce_str;
private String sign;
private String mch_billno;
private String sub_mch_id;
private String nick_name;
private String send_name;
private String re_openid;
private String total_amount;
private String min_value;
private String max_value;
private String total_num;
private String wishing;
private String client_ip ;
private String act_name;
private String remark;
private String logo_imgurl;
private String share_content;
private String share_url;
private String share_imgurl;
public xml(String wxappid, String mch_id, String nonce_str, String sign,
String mch_billno, String sub_mch_id, String nick_name,
String send_name, String re_openid, String total_amount,
String min_value, String max_value, String total_num,
String wishing, String client_ip, String act_name, String remark,
String logo_imgurl, String share_content, String share_url,
String share_imgurl) {
super();
this.wxappid = wxappid;
this.mch_id = mch_id;
this.nonce_str = nonce_str;
this.sign = sign;
this.mch_billno = mch_billno;
this.sub_mch_id = sub_mch_id;
this.nick_name = nick_name;
this.send_name = send_name;
this.re_openid = re_openid;
this.total_amount = total_amount;
this.min_value = min_value;
this.max_value = max_value;
this.total_num = total_num;
this.wishing = wishing;
this.client_ip = client_ip;
this.act_name = act_name;
this.remark = remark;
this.logo_imgurl = logo_imgurl;
this.share_content = share_content;
this.share_url = share_url;
this.share_imgurl = share_imgurl;
}
public xml() {
}
public String getWxappid() {
return wxappid;
}
public void setWxappid(String wxappid) {
this.wxappid = wxappid;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getMch_billno() {
return mch_billno;
}
public void setMch_billno(String mch_billno) {
this.mch_billno = mch_billno;
}
public String getSub_mch_id() {
return sub_mch_id;
}
public void setSub_mch_id(String sub_mch_id) {
this.sub_mch_id = sub_mch_id;
}
public String getNick_name() {
return nick_name;
}
public void setNick_name(String nick_name) {
this.nick_name = nick_name;
}
public String getSend_name() {
return send_name;
}
public void setSend_name(String send_name) {
this.send_name = send_name;
}
public String getRe_openid() {
return re_openid;
}
public void setRe_openid(String re_openid) {
this.re_openid = re_openid;
}
public String getTotal_amount() {
return total_amount;
}
public void setTotal_amount(String total_amount) {
this.total_amount = total_amount;
}
public String getMin_value() {
return min_value;
}
public void setMin_value(String min_value) {
this.min_value = min_value;
}
public String getMax_value() {
return max_value;
}
public void setMax_value(String max_value) {
this.max_value = max_value;
}
public String getTotal_num() {
return total_num;
}
public void setTotal_num(String total_num) {
this.total_num = total_num;
}
public String getWishing() {
return wishing;
}
public void setWishing(String wishing) {
this.wishing = wishing;
}
public String getClient_ip() {
return client_ip;
}
public void setClient_ip(String client_ip) {
this.client_ip = client_ip;
}
public String getAct_name() {
return act_name;
}
public void setAct_name(String act_name) {
this.act_name = act_name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getLogo_imgurl() {
return logo_imgurl;
}
public void setLogo_imgurl(String logo_imgurl) {
this.logo_imgurl = logo_imgurl;
}
public String getShare_content() {
return share_content;
}
public void setShare_content(String share_content) {
this.share_content = share_content;
}
public String getShare_url() {
return share_url;
}
public void setShare_url(String share_url) {
this.share_url = share_url;
}
public String getShare_imgurl() {
return share_imgurl;
}
public void setShare_imgurl(String share_imgurl) {
this.share_imgurl = share_imgurl;
}
}

http://yun.baidu.com/share/link?shareid=3003351432&uk=958682606&third=0

这里的cxf在请求的header进行了权限验证,以前做的项目拿出来溜溜

spring里面的dao啊service啊 什么的还有mybiats配置文件之类的 这里就只列一个例子
主要的还是webservice cxf

先把重点拿出来

最下面会把整个例子项目打包给大家

先是webservice接口方法实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package org.wsdl.cxf.ws.impl;
import java.util.Date;
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebService;
import org.wsdl.domain.ArrayOf_tns2_SubInfo;
import org.wsdl.domain.Cat;
import org.wsdl.domain.User;
import org.wsdl.service.UserService;
import org.wsdl.service.test;
import org.wsdl.until.LogUntil;
import org.wsdl.cxf.ws.HelloWord;
/**
'* 此类是webservice的实现接口,在此类中定义需要暴露的方法,
'* 其中的service需要在applicationContext.xml里配置spring注入
' * 如果自定义参数名需要在接口HelloWord里参数前加@WebParam(name="name")来标识此元素,防止参数自动变成arg0
'* @param zhouxs
*/
@WebService(endpointInterface="org.wsdl.cxf.ws.HelloWord",serviceName="Ws")
public class HelloWordWs implements HelloWord{
private UserService us;
private test test;
@Override
public String SayHi( String name) {
LogUntil loginfo= new LogUntil();
loginfo.writeLogInfo("进入SayHi方法");
return name+",你好 现在时间是"+new Date();
}
@Override
public List<Cat> getCatsByUser(User user) {
LogUntil loginfo= new LogUntil();
loginfo.writeLogInfo("进入getCatsByUser方法");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return us.getCatByUser(user);
}
@Override
public void insertCat(List<Cat> s) {
LogUntil loginfo= new LogUntil();
loginfo.writeLogInfo("进入insertCat方法");
test.insertCat(s);
}
@Override
public List<Cat> Test(User user) {
LogUntil loginfo= new LogUntil();
loginfo.writeLogInfo("进入Test方法");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return test.getCatsByUser(user);
}
public UserService getUs() {
return us;
}
public void setUs(UserService us) {
this.us = us;
}
public test getTest() {
return test;
}
public void setTest(test test) {
this.test = test;
}
@Override
public String orderRelationUpdateNotifyRequest(String recordSequenceId,
ArrayOf_tns2_SubInfo subNotify) {
// TODO Auto-generated method stub
return null;
}
}

接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.wsdl.cxf.ws;
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebService;
import org.wsdl.domain.ArrayOf_tns2_SubInfo;
import org.wsdl.domain.Cat;
import org.wsdl.domain.User;
@WebService
public interface HelloWord {
String SayHi(@WebParam(name="name") String name );
List <Cat> getCatsByUser(User user);
List <Cat> Test(User user);
void insertCat(List<Cat> s);
public String orderRelationUpdateNotifyRequest(String recordSequenceId,ArrayOf_tns2_SubInfo subNotify);
}

拦截器

package org.wsdl.cxf.ws.auth;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.util.List;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
/*
*此拦截器用于添加消息帐号密码验证(可不用)
*
*
*
*/
//通过PhaseInterceptor可以指定拦截器在哪个阶段起作用
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
public AuthInterceptor() {
//显式调用父类有参数构造器
//显式调用父类构造器后程序将不会隐式调用无参数构造器
super(Phase.PRE_INVOKE);//在调用之前获取soap消息
}
//实现自己拦截器时,需要实现handleMessage方法
//handleMessage形参就是得到的sopa消息
@Override
public void handleMessage(SoapMessage msg) throws Fault {
System.out.println("==========="+msg);
/*//得到消息的head
List<Header> headers=msg.getHeaders();
if(headers==null||headers.size()<1){
throw new Fault(new IllegalArgumentException("没有账号密码不允许访问"));
}*/
}
}

dao的实现类

package org.wsdl.dao.impl;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.List;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.wsdl.dao.TestDao;
import org.wsdl.domain.Cat;
import org.wsdl.domain.User;
public class TestDaoImpl extends SqlSessionDaoSupport implements TestDao {
@Override
public List<Cat> getCatsByUser(User user) {
return getSqlSession().selectList("getCatsByUser", user);
}
@Override
public void insertCat(Cat cat) {
getSqlSession().insert("insertCat", cat);
}
}

service实现类

package org.wsdl.service.impl;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.List;
import org.springframework.transaction.annotation.Transactional;
import org.wsdl.dao.TestDao;
import org.wsdl.domain.Cat;
import org.wsdl.domain.User;
import org.wsdl.service.test;
@Transactional
public class testImpl implements test {
private TestDao testDao;
@Override
public List<Cat> getCatsByUser(User user) {
return testDao.getCatsByUser(user);
}
public TestDao getTestDao() {
return testDao;
}
public void setTestDao(TestDao testDao) {
this.testDao = testDao;
}
@Override
public void insertCat(List<Cat> s) {
for (int i=0;i<s.size();i++)
{
testDao.insertCat(s.get(i));
}
}
}

sql文件getCatmap.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
<select id="getCatsByUser" parameterType="org.wsdl.domain.User" resultType="org.wsdl.domain.Cat">
<![CDATA[
SELECT * FROM cat where id=#{id}
]]>
</select>
<insert id="insertCat" parameterType="org.wsdl.domain.Cat" >
<![CDATA[
insert into cat (id,name,color)values (#{ID},#{NAME},#{COLOR})
]]>
</insert>
</mapper>

sql的配置文件Configuration.xml

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<mappers>
<!--查猫 -->
<mapper resource="org/wsdl/maps/getCatmap.xml"/>
</mappers>
</configuration>

spring配置文件applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.mtea" />
<!--数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="jdbc:oracle:thin:@XXXXXXXXXX:1521:orcl" />
<property name="user" value="XXXX" />
<property name="password" value="XXXX" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="30" />
<property name="initialPoolSize" value="1" />
<property name="testConnectionOnCheckout" value="false" />
<property name="maxIdleTime" value="2400" />
<property name="maxStatements" value="0" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:Configuration.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<!-- transaction support-->
<!-- PlatformTransactionMnager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- enable transaction annotation support -->
<tx:annotation-driven transaction-manager="txManager" />
<!-- web应用类加载路径 -->
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<bean name="userService" class="org.wsdl.service.impl.UserServiceImpl">
</bean>
<bean name="Test" class="org.wsdl.service.impl.testImpl">
<property name="testDao" ref="tDao"></property>
</bean>
<!-- implementor指定webservice服务提供形式
A。直接给定服务器提供者的类名
B。设置为容器中一个bean 采用
#后不认为是类名-->
<bean id="helloWordWs" class="org.wsdl.cxf.ws.impl.HelloWordWs">
<property name="test" ref="Test"></property>
<property name="us" ref="userService"></property>
</bean>
<bean id="tDao" class="org.wsdl.dao.impl.TestDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<jaxws:endpoint implementor="#helloWordWs" address="/ws">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>contextConfigLoction</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<!--保证在web应用启动时加载spring容器 -->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 下面配置表明所有来自/ws/*请求都交给CXFServlet处理 -->
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
</web-app>

http://yun.baidu.com/share/link?shareid=2127183393&uk=958682606

如果大家不用web程序 也可以写成小程序来执行 这时候配置文件变化下 再写个服务端就ok啦

详情也会给大家在最下面发出来

applicationContext.xml内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://cxf.apache.org/configuration/security"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://cxf.apache.org/configuration/security
http://cxf.apache.org/schemas/configuration/security.xsd
http://cxf.apache.org/transports/http/configuration
http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://cxf.apache.org/transports/http-jetty/configuration
http://cxf.apache.org/schemas/configuration/http-jetty.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.mtea" />
<!--数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="jdbc:oracle:thin:@133.224.7.162:1521:orcl" />
<property name="user" value="ca_new" />
<property name="password" value="ca_new" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="30" />
<property name="initialPoolSize" value="1" />
<property name="testConnectionOnCheckout" value="false" />
<property name="maxIdleTime" value="2400" />
<property name="maxStatements" value="0" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:Configuration.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 注解支持-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<!--
web应用类加载路径
<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
-->
<!--业务组件 -->
<bean name="userService" class="org.wsdl.service.impl.UserServiceImpl">
</bean>
<bean name="Test" class="org.wsdl.service.impl.testImpl">
<property name="testDao" ref="tDao"></property>
</bean>
<!-- implementor指定webservice服务提供形式
A。直接给定服务器提供者的类名
B。设置为容器中一个bean 采用
#后不认为是类名-->
<bean id="helloWordWs" class="org.wsdl.cxf.ws.impl.HelloWordWs">
<property name="test" ref="Test"></property>
<property name="us" ref="userService"></property>
</bean>
<bean id="tDao" class="org.wsdl.dao.impl.TestDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<!-- jetty服务器配置文件 -->
<!-- <httpj:engine-factory bus="cxf" >
<httpj:engine port="9090">
<httpj:tlsServerParametersRef id="secure" />
<httpj:threadingParameters minThreads="5"
maxThreads="15" />
<httpj:connector>
<bean class="org.eclipse.jetty.server.bio.SocketConnector">
<property name = "port" value="9090"></property>
</bean>
</httpj:connector>
<httpj:handlers>
<bean class="org.eclipse.jetty.server.handler.DefaultHandler"/>
</httpj:handlers>
<httpj:sessionSupport>true</httpj:sessionSupport>
</httpj:engine>
</httpj:engine-factory> -->
</beans>

服务器端

Server.java

package ServerMain;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import java.io.IOException;
import javax.xml.ws.Endpoint;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.transport.Destination;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.wsdl.cxf.ws.HelloWord;
import org.wsdl.cxf.ws.auth.AuthInterceptor;
import org.wsdl.cxf.ws.auth.AuthInterceptorOut;
import org.wsdl.cxf.ws.impl.HelloWordWs;
import org.wsdl.until.LogUntil;
public class Server {
/**
* webservice启动方法
* 若更改发布地址或增加新方法的话需要重新生成客户端
* 自定义拦截器可加可不加,在拦截器内可获取或者修改soap消息报文头的信息,用来验证
*
* 若做多媒体数据支持请参照http://yufenfei.iteye.com/blog/1685910 用注解@XmlMimeType("application/octet-stream")修改实体类中的参数类型
* 并在jaxws:endpoint 标签内添加如下配置文件启用MTOM支持(客户端和服务器端都需要开启MTOM的支持)
* <jaxws:properties>
* <entry key="mtom-enabled" value="true" />
*</jaxws:properties>
* MTOM将数据转换成无编码格式的二进制数据传输,速度更快
*
* @param zhouxs
* @throws InterruptedException
* @throws IOException
*/
public static void main(String[] args) throws InterruptedException, IOException {
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");//手动加载spring
HelloWord hw=context.getBean("helloWordWs", HelloWordWs.class);//spring注入实现类
//Endpoint e=Endpoint.publish("http://10.64.4.202:9090/cxf_spring/ws/ws?wsdl", hw);//此发布方法无法添加拦截器,若不需要拦截器的话可以打开,删除下面的发布方法
//调用Endpoint发布webservers
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
//设置Service Class
factory.setServiceClass(HelloWordWs.class);//实现类
factory.setAddress("http://10.64.4.202:9090/cxf_spring/ws/ws");
//设置ServiceBean对象
factory.getInInterceptors().add(new AuthInterceptor());//添加自定义进入权限拦截器
factory.getInInterceptors().add(new LoggingInInterceptor());//添加日志拦截器
factory.getOutInterceptors().add(new LoggingOutInterceptor());//添加日志拦截器
factory.getOutInterceptors().add(new AuthInterceptorOut());//添加自定义推出拦截器
factory.setServiceBean(hw);
org.apache.cxf.endpoint.Server server= factory.create();
server.start();
System.out.println("WebServices 启动成功!");
LogUntil loginfo= new LogUntil();
loginfo.writeLogInfo("WebServices 启动成功!服务地址是http://133.224.7.164:9090/cxf_spring/ws/ws");
}
}

两个拦截器一个拦截进来的请 一个拦截出去的消息

AuthInterceptor.java

package org.wsdl.cxf.ws.auth;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.tools.common.extensions.soap.SoapBody;
import org.wsdl.until.LogUntil;
/*
*此拦截器用于添加消息帐号密码验证(可不用)
*
*
*
*/
//通过PhaseInterceptor可以指定拦截器在哪个阶段起作用
public class AuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
public AuthInterceptor() {
//显式调用父类有参数构造器
//显式调用父类构造器后程序将不会隐式调用无参数构造器
super(Phase.PRE_INVOKE);//在调用之前获取soap消息
}
//实现自己拦截器时,需要实现handleMessage方法
//handleMessage形参就是得到的sopa消息
@Override
public void handleMessage(SoapMessage msg) throws Fault {
LogUntil loginfo= new LogUntil();
loginfo.writeLogInfo("handleMessage接收消息时触发:");
/*//得到消息的head
List<Header> headers=msg.getHeaders();
if(headers==null||headers.size()<1){
throw new Fault(new IllegalArgumentException("没有账号密码不允许访问"));
}//要求第一个header里携带了用户名密码
Header firstHeader= headers.get(0);
Element ele= (Element) firstHeader.getObject();
NodeList userId= ele.getElementsByTagName("userID");
NodeList password= ele.getElementsByTagName("password");
if(userId.getLength()!=1){
throw new Fault(new IllegalArgumentException("用户帐号名格式不对"));
}
if(userId.getLength()!=1){
throw new Fault(new IllegalArgumentException("密码格式不对"));
}
String uid=userId.item(0).getTextContent();
String pass=password.item(0).getTextContent();
//查询数据库看用户名密码是否正确
//TODO*/
}
}

AuthInterceptorOut.java拦截出去的请求

package org.wsdl.cxf.ws.auth;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.tools.common.extensions.soap.SoapBody;
import org.wsdl.until.LogUntil;
/*
*此拦截器用于添加消息帐号密码验证(可不用)
*
*
*
*/
//通过PhaseInterceptor可以指定拦截器在哪个阶段起作用
public class AuthInterceptorOut extends AbstractPhaseInterceptor<SoapMessage> {
public AuthInterceptorOut() {
//显式调用父类有参数构造器
//显式调用父类构造器后程序将不会隐式调用无参数构造器
super(Phase.WRITE_ENDING);//在写出之后获取soap消息
}
//实现自己拦截器时,需要实现handleMessage方法
//handleMessage形参就是得到的sopa消息
@Override
public void handleMessage(SoapMessage msg) throws Fault {
LogUntil loginfo= new LogUntil();
loginfo.writeLogInfo("handleMessage发送消息后触发:");
}
}

http://yun.baidu.com/share/link?shareid=2211335353&uk=958682606

ios前端比较懒~囧~~,还有已安装的app用户 ,不愿意更新等问题 导致 请求头无法补全给服务端springmvc发送过来。。。。。悲剧了

只能服务端自己处理这个不全的http请求空参无法解析的问题

尝试处理方法

1 增加springmvc过滤器对请求进行过滤(失败)

测试发现在访问控制层匹配请求地址之前就已经报错,应该是dispatcher那里出了问题

虽然失败, 把代码配置贴出来~~

applicationContext.xml

1
2
3
4
5
6
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.interceptor.ForIosParam"></bean>
</mvc:interceptor>
</mvc:interceptors>

ForIosParam.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ForIosParam implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
StringBuffer url=request.getRequestURL();
Map requestParams=request.getParameterMap();
Method method=requestParams.getClass().getMethod("setLocked",new Class[]{boolean.class});
method.invoke(requestParams,new Object[]{new Boolean(false)});
requestParams.put("ForIosParam", "ForIosParam");
Map map1=request.getParameterMap();
request.getRequestURL().append("?ForIosParam=ForIosParam");
request.setAttribute("ForIosParam", "ForIosParam");
StringBuffer url1=request.getRequestURL();
return true;
}
}

2 使用servlet在接收到请求之后发送再次自己给自己发送一个http完整的请求 (失败,为毛请求发出去了,然后就没有然后了一点反应也木有。。。。必须异步的吗? 不管那么多了。。。换)这个网上搜就可以java发送http post请求

3 使用 servlet利用post在接收到请求之后,增加参数再服务器跳转forward到springmvc 的get方式接收的方法里(失败啊。。。。。每次都是servlet拦截到。。。。。悲催 为毛 不管那么多 。。。。换)

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.util;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import com.model.umaiw_app_system;
import com.service.GetInitKeyService;
import com.service.GetTheBestServerService;
import com.service.implement.GetInitKeyServiceImpl;
import com.service.implement.GetTheBestServerServiceImpl;
import com.test.HttpRequest;
public class getTheBestServerServlet extends HttpServlet{
public void doPost (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/json; charset=gb2312");
Map requestParams=request.getParameterMap();
Method method;
try {
method = requestParams.getClass().getMethod("setLocked",new Class[]{boolean.class});
method.invoke(requestParams,new Object[]{new Boolean(false)});
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
requestParams.put("ForIosParam", "ForIosParam");
Map map1=request.getParameterMap();
request.getRequestURL().append("?ForIosParam=ForIosParam");
request.setAttribute("ForIosParam", "ForIosParam");
ServletContext sc = getServletContext();
RequestDispatcher rd = null;
rd = sc.getRequestDispatcher(request.getRequestURI()); //定向的页面
rd.forward(request, response);
StringBuffer url=request.getRequestURL();
//response.sendRedirect(url.toString());
}
}

5 干脆 直接用servlet吧无参的http请求处理掉(成功啦~~ )

不过这种方式因为是单独走的servlet没有走spring mvc和spring框架的支持(木有jdbcTemplate,木有自动注入,木有数据库连接池~~~OMG 对付吧 ,不管三七二十一拼了,谁让他不补全标准的http请求哒)

代码如下(不能注入就实例化)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package com.util;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import com.model.umaiw_app_system;
import com.service.GetInitKeyService;
import com.service.GetTheBestServerService;
import com.service.implement.GetInitKeyServiceImpl;
import com.service.implement.GetTheBestServerServiceImpl;
import com.test.HttpRequest;
public class getTheBestServerServlet extends HttpServlet{
public void doPost (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
GetInitKeyServiceImpl getInitKeyService=new GetInitKeyServiceImpl();
GetTheBestServerServiceImpl getTheBestServerService= new GetTheBestServerServiceImpl();
Map<String, String> map = new HashMap<String, String>();
map.put("request", "getTheBestServer");
map.put("status", "0");
//阿里云获取真实ip,这个也让人头疼。。。。。
String ip=request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
String initKey ="";
umaiw_app_system uas = getInitKeyService.getinitKey(ip);
if ( null== uas ) {
String uuid = UUID.randomUUID().toString();
initKey = uuid.substring(uuid.length()-8);
String uuidkey = UUID.randomUUID().toString();
String key = uuidkey.substring(uuidkey.length()-8);
try {
getTheBestServerService.insertKey(ip, initKey, new Date(),key);
} catch (Exception e) {
map.put("status", "1");
}
} else {
initKey=uas.getInit_key();
}
try {
map.put("serverIp", DesUtil.encrypt(
"XX.XX.XX.XX"(可以使负载均衡的ip),initKey));
} catch (Exception e) {
e.printStackTrace();
}
map.put("initKey", initKey);
map.put("ip", ip);
JSONObject jsonObject = JSONObject.fromObject(map);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(jsonObject.toString());
}
}
```
web.xml
```XML<servlet>
<servlet-name>getTheBestServerServlet</servlet-name>
<servlet-class>com.util.getTheBestServerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getTheBestServerServlet</servlet-name>
<url-pattern>/system/getTheBestServer</url-pattern>
</servlet-mapping>

数据库访问层用最基本的jdbc访问(别忘了使用完连接 关了它,,,,,)

附上 阿里云获取真实ip的tomcat下

server.xml最后一行的配置

1
<Valve className="org.apache.catalina.valves.AccessLogValve" pattern="%{X-Forwarded-For}i %h %l %u %t "%r" %s %b" suffix=".txt" prefix="localhost_access_log." directory="logs"/>

大功告成 这样就可以单独处理无参不全请求头的死ios的http请求啦。。。。。

如果是json字符串请求服务器端的话 springmvc默认 是text/plian这种键值对的接收方式 (也就是浏览器发送过来的形式)

但是 如果是 application/json这种的contenttype的话 是接收不到参数的 ,(在拦截器里设置请求的请求的contenttype也不行)只好让手机端改成键值对的形式

(不是真正的带入了, 而是变相的 将 group by 之后的语句, 为了不增加第二层子查询, 导致无法识别最外层的字段,采用distinct方法)

SELECT (
1
2
3
4
5
6
7
8
9
10
select count(*) from BORROW_LIST
where DELETE_FLAG=0 and BORROW_ID=c.BORROW_ID
** group by LOAN_USER_ID**
) as cyrs_COUNT,sum(...) ....
from BORROW c

这样查出来的数量是多个结果,无法对应其他字段 ,并且数据 并不是总人数

LOAN_USER_ID USER_NAME ………………

1 啊啊啊

23 啵啵啵

23 纯纯粹粹

35 点点滴滴

但是如果写成下面这样 的话 是无法取到c.BORROW_ID 的

SELECT (**select count(*) from (**
1
2
3
4
5
6
7
8
9
10
select count(*) from BORROW_LIST
where DELETE_FLAG=0 and BORROW_ID=**c.BORROW_ID **
group by LOAN_USER_ID ) **d**
) as cyrs_COUNT,sum(...) ....
from BORROW c

那么只有这样了~换个方法

SELECT (
1
2
3
4
5
6
7
8
select **count(distinct(LOAN_USER_ID))** from BORROW_LIST
where DELETE_FLAG=0 and BORROW_ID=**c.BORROW_ID **
) as cyrs_COUNT,sum(...) ....
from BORROW c

这样就不用再套一层子查询了