在JSON.org上看到java實現的源碼,想著自己寫一個Result支持JSON的返回,但是一看webwork的新版本2.2.7版本已經支持JSON了
,但是有bug,第一,jsonObjectProperty的setter方法寫成了setJSONObjectProperty所以,在配置中若使用了jsonObjectProperty做為參數名,那么是不能set參數進去的。另外,它不支持自定義返回js的編碼,造成亂碼,或者干脆都無法正常調用js,還有就是我覺得可以再封裝得好一點,對于JSONObject的生成,可以利用反射來做,而不是在每個Action中都手工的寫生成JSONObject的代碼,所以我做了一下改進:
1
package com.csair.hunan.common.web;
2
3
import java.io.OutputStream;
4
import java.lang.reflect.Field;
5
6
import javax.servlet.http.HttpServletResponse;
7
8
import org.apache.commons.logging.Log;
9
import org.apache.commons.logging.LogFactory;
10
import org.json.JSONObject;
11
12
import com.opensymphony.webwork.ServletActionContext;
13
import com.opensymphony.webwork.WebWorkException;
14
import com.opensymphony.xwork.ActionContext;
15
import com.opensymphony.xwork.ActionInvocation;
16
import com.opensymphony.xwork.Result;
17
18
public class JSONResult implements Result {
19
20
private static final Log LOG = LogFactory.getLog(JSONResult.class);
21
22
private String jsonObjectProperty = "jsonObject";
23
private String contentType = "application/json";
24
private String encoding = "utf-8";
25
26
public void setEncoding(String encoding) {
27
this.encoding = encoding;
28
}
29
/**
30
* Returns the property which will be used to lookup {@link JSONObject} in WebWork's ValueStack. Default to
31
* 'jsonObject'.
32
*
33
* @return String
34
*/
35
36
public String getJsonObjectProperty() {
37
return jsonObjectProperty;
38
}
39
/**
40
* Set the property which will be used to lookup {@link JSONObject} in WebWork's ValueStack. Default to
41
* 'jsonObject'.
42
*
43
* @param jsonObject
44
*/
45
46
public void setJsonObjectProperty(String jsonObjectProperty) {
47
this.jsonObjectProperty = jsonObjectProperty;
48
}
49
50
/**
51
* Returns the content-type header to be used. Default to 'application/json'.
52
*
53
* @return String
54
*/
55
public String getContentType() {
56
return contentType;
57
}
58
59
/**
60
* Set the content-type header to be used. Default to 'application/json'.
61
*
62
* @param contentType
63
*/
64
public void setContentType(String contentType) {
65
this.contentType = contentType;
66
}
67
68
69
/**
70
* Writes the string representation of {@link JSONObject} defined through {@link #getJSONObjectProperty()}
71
* to {@link javax.servlet.http.HttpServletResponse}'s outputstream.
72
*
73
* @param invocation
74
* @throws Exception
75
*/
76
public void execute(ActionInvocation invocation) throws Exception {
77
78
if (LOG.isDebugEnabled()) {
79
LOG.debug("executing JSONResult");
80
}
81
82
JSONObject jsonObject = getJSONObject(invocation);
83
if (jsonObject != null) {
84
String json = jsonObject.toString();
85
HttpServletResponse response = getServletResponse(invocation);
86
response.setContentType(getContentType());
87
//encoding
88
byte[] bs = json.getBytes(this.encoding);
89
response.setContentLength(bs.length);
90
91
OutputStream os = response.getOutputStream();
92
os.write(bs);
93
os.flush();
94
95
if (LOG.isDebugEnabled()) {
96
LOG.debug("written ["+json+"] to HttpServletResponse outputstream");
97
}
98
}
99
}
100
101
/**
102
* Attempt to look up a {@link com.opensymphony.webwork.dispatcher.json.JSONObject} instance through the property
103
* ({@link #getJSONObjectProperty()}) by looking up the property in WebWork's ValueStack. It shall be found if there's
104
* accessor method for the property in WebWork's action itself.
105
* <p/>
106
* Returns null if one cannot be found.
107
* <p/>
108
* We could override this method to return the desired JSONObject when writing testcases.
109
*
110
* @param invocation
111
* @return {@link JSONObject} or null if one cannot be found
112
*/
113
protected JSONObject getJSONObject(ActionInvocation invocation) throws Exception {
114
ActionContext actionContext = invocation.getInvocationContext();
115
Object obj = actionContext.getValueStack().findValue(jsonObjectProperty);
116
117
118
if (obj == null) {
119
LOG.error("property ["+ jsonObjectProperty +"] returns null, expecting JSONObject", new WebWorkException());
120
return null;
121
}
122
//if the assigned object is not an instance of JSONObject, try to build one use reflection
123
if (! JSONObject.class.isInstance(obj)) {
124
LOG.warn("property ["+ jsonObjectProperty +"] is ["+obj+"] especting an instance of JSONObject", new WebWorkException());
125
LOG.debug("build json object by reflection.");
126
JSONObject jsonObj = new JSONObject();
127
for (Field field : obj.getClass().getDeclaredFields()) {
128
String getter = "get" + Character.toUpperCase(field.getName().charAt(0)) + field.getName().substring(1);
129
jsonObj.append(field.getName(), obj.getClass().getDeclaredMethod(getter).invoke(obj));
130
}
131
return jsonObj;
132
}
133
134
return (JSONObject) obj;
135
}
136
137
138
/**
139
* Returns a {@link javax.servlet.http.HttpServletResponse} by looking it up through WebWork's ActionContext Map.
140
* </p>
141
* We could override this method to return the desired Mock HttpServletResponse when writing testcases.
142
*
143
* @param invocation
144
* @return {@link javax.servlet.http.HttpServletResponse}
145
*/
146
protected HttpServletResponse getServletResponse(ActionInvocation invocation) {
147
return (HttpServletResponse) invocation.getInvocationContext().getContextMap().get(ServletActionContext.HTTP_RESPONSE);
148
}
149
}
150

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
