介绍RESTful架构风格
REST是REST之父Roy Thomas创造的,当时提出来了REST的6个特点:客户端-服务器的、无状态的、可缓存的、统一接口、分层系统和按需编码。其具有跨语言和跨平台的优势。
REST是一种架构风格。其描述性的状态包括资源数据的内容和表达格式(XML,JSON等)。请求其中一个资源:方为一个指定性和描述性的URI,经由HTTP将资源的表达从服务器转移到客户端,或者相反方向。
REST不是一种技术,也不是一个标准或者协议,它拥有标准:HTTP+URI+XML(JSON),来实现其要求的架构风格。
泥瓦匠的记忆宫殿:“REST其实就像万能规则一样。如果你遵循它的规则的话,就能得她提供给你的资源数据。”
Spring配置CXF
泥瓦匠用的是Spring4.0.x和CXF3.0.x版本。有兄长说过让我用其他的轻量级的Web Service框架,我最后考虑了下还是用CXF。
1、第一步配置所需的依赖包jars
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
< dependency > < groupId >org.apache.cxf</ groupId > < artifactId >cxf-rt-frontend-jaxws</ artifactId > < version >3.0.3</ version > </ dependency > < dependency > < groupId >org.apache.cxf</ groupId > < artifactId >cxf-rt-transports-http</ artifactId > < version >3.0.3</ version > </ dependency > < dependency > < groupId >org.apache.cxf</ groupId > < artifactId >cxf-rt-frontend-jaxrs</ artifactId > < version >3.0.3</ version > </ dependency > |
在以前2.x的CXF上,bug和配置上很复杂。3.0以后很方便,用了MAVEN后,就是直接拷贝下上面的代码放到pom.xml即可。
2、配置Spring文件
首先配置CXF所需的XSD地址,表死我们引用了这个结构定义。
1 <beans xmlns="http://www.springframework.org/schema/beans" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 3 xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 6 http://www.springframework.org/schema/context 7 http://www.springframework.org/schema/context/spring-context-4.0.xsd 8 http://cxf.apache.org/jaxws 9 http://cxf.apache.org/schemas/jaxws.xsd 10 http://cxf.apache.org/jaxrs 11 http://cxf.apache.org/schemas/jaxrs.xsd"> 12 13 <bean id="regUser" 14 class="com.lq.controller.UserInfoController"></bean> 15 16 17 <!-- CXF 拦截器 <ref bean="tokenInterceptor" /> 18 <bean id="tokenInterceptor" class="com.xidian.wq.imaopay.interceptor.cxf.TokenInterceptor"></bean> 19 --> 20 <!-- address-请求路径 --> 21 <jaxrs:server id="imaoPayService" address="/ipservice"> 22 23 <!-- 输入拦截器设置 --> 24 <jaxrs:inInterceptors> 25 </jaxrs:inInterceptors> 26 27 28 <!-- 输出拦截器设置 --> 29 <jaxrs:outInterceptors> 30 </jaxrs:outInterceptors> 31 32 <!-- serviceBeans-暴露的WebService服务类 --> 33 <jaxrs:serviceBeans> 34 <ref bean="regUser" /> 35 </jaxrs:serviceBeans> 36 37 <!-- 支持的协议 --> 38 <jaxrs:extensionMappings> 39 <entry key="json" value="application/json" /> 40 <entry key="xml" value="application/xml" /> 41 </jaxrs:extensionMappings> 42 43 44 <!-- 编码格式 --> 45 <jaxrs:languageMappings> 46 <entry key="en" value="en-gb"/> 47 </jaxrs:languageMappings> 48 49 50 51 </jaxrs:server> 52 </beans>
然后泥瓦匠用配置核心的配置。在<beans></beans>直接加入所需要的cxf配置。
根据代码的备注,泥瓦匠想让大家记住几点重要性的点。
address=”/ipservice” 表示我们以后用此地址访问所提供的地址。
<jaxrs:serviceBeans><jaxrs:serviceBeans/> 之间加入我们要暴露出去的服务类。这里泥瓦匠以一个简单的注册类来提供。
jaxrs:extensionMappings 是表示我们需要支持的协议。
3、UserInfoController是我们需要完成的暴露服务类。下面泥瓦匠说一下初设计(这点请大家指点指点)。
三层初设计,实现WebService接口层
初设计:
按着原来的SpringMVC的三层架构,我这边把原来的Controller层转为暴露在出来的接口服务类。自然View层也就没了。
UserInfoController的代码如下:
1 package com.lq.controller; 2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 9 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.stereotype.Controller; 11 import org.springframework.web.bind.annotation.RequestMapping; 12 13 import com.lq.entity.User; 14 import com.lq.service.CustomerService; 15 import com.lq.service.UserService; 16 17 //注入controller 18 @Controller 19 @RequestMapping("/user") 20 public class UserController { 21 22 //注入service 23 @Autowired 24 private UserService userService; 25 26 @Autowired 27 private CustomerService customerService; 28 29 @RequestMapping("/getAllUser") 30 public String getAllUser(HttpServletRequest request) { 31 request.setAttribute("userList", userService.getAllUser()); 32 return "/index"; 33 } 34 35 @RequestMapping("/getUser") 36 public String getUser(String id, HttpServletRequest request) { 37 request.setAttribute("user", userService.getUser(id)); 38 return "/editUser"; 39 } 40 41 @RequestMapping("/toAddUser") 42 public String toAddUser() { 43 return "/addUser"; 44 } 45 46 @RequestMapping("/addUser") 47 public String addUser(User user, HttpServletRequest request) { 48 try { 49 userService.addUser(user); 50 return "redirect:/user/getAllUser"; 51 } catch (Exception e) { 52 return "/error"; 53 } 54 } 55 56 @RequestMapping("/delUser") 57 public void delUser(String id, HttpServletResponse response) { 58 String result = "{\"result\":\"error\"}"; 59 60 if (userService.delUser(id)) { 61 result = "{\"result\":\"success\"}"; 62 } 63 response.setContentType("application/json"); 64 try { 65 PrintWriter out = response.getWriter(); 66 out.write(result); 67 } catch (IOException e) { 68 e.printStackTrace(); 69 } 70 } 71 72 @RequestMapping("/updateUser") 73 public String updateUser(User user, HttpServletRequest request) { 74 if (userService.updateUser(user)) { 75 user = userService.getUser(user.getId()); 76 request.setAttribute("user", user); 77 return "redirect:/user/getAllUser"; 78 } else { 79 return "/error"; 80 } 81 } 82 }
暴露的接口层,也可以用inteface类加实现类来完成。泥瓦匠觉得多此一举,兴许我大言不惭。
泥瓦匠总结如下:
@POST 表示HTTP的访问模式
@Path 表示访问路径
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 响应内容 MIME 类型
HTTPClient 客户端,并实现简单调用
“实践出真理。”拿出来遛一遛即可。泥瓦匠简单的用HTTPClient访问
核心代码如下:
1 package com.xidian.wq.imaopay.model.mesdata.base; 2 3 import java.io.UnsupportedEncodingException; 4 import java.text.SimpleDateFormat; 5 import java.util.ArrayList; 6 import java.util.Date; 7 import java.util.HashMap; 8 import java.util.List; 9 import java.util.Map; 10 import java.util.Random; 11 import java.util.UUID; 12 13 import net.sf.ehcache.util.TimeUtil; 14 15 import org.apache.commons.lang.RandomStringUtils; 16 17 public class HttpClient { 18 /** 19 * 20 * 注册报文发送案例 21 */ 22 23 private void doRegXml()throws Exception{ 24 25 /** 构造测试报文头对象 */ 26 RandomStringUtils.randomNumeric(8); 27 DataBean dataBean = new DataBean(); 28 29 dataBean.setBatch_no("N20150204"); 30 31 dataBean.setData_type("000001"); 32 33 dataBean.setVersion("v1.0"); 34 35 dataBean.setUser_name("13957706713"); 36 37 dataBean.setMsg_sign("未知"); 38 39 dataBean.setRd_num(UUID.randomUUID().toString()); 40 41 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 42 String date = sdf.format(new Date(System.currentTimeMillis()*1000L)); 43 dataBean.setRd_time(date); 44 45 dataBean.setK_sign("aaaaaa"); 46 47 48 /** 构造测试报文体对象 */ 49 50 RegBean regBean = new RegBean(); 51 52 regBean.setReg_sn("REG20150204"); 53 54 regBean.setUser_id(15); 55 56 regBean.setReg_no("33"); 57 58 regBean.setReg_way("pc"); 59 60 regBean.setSet_time(new Date().toLocaleString()); 61 62 regBean.setRet_url("未知"); 63 64 regBean.setRemarks("无备注"); 65 66 67 68 RegBean regBean2 = new RegBean(); 69 70 regBean2.setReg_sn("REG20150203"); 71 72 regBean2.setUser_id(13); 73 74 regBean2.setReg_no("44"); 75 76 regBean2.setReg_way("mobile"); 77 78 regBean2.setSet_time(new Date().toLocaleString()); 79 80 regBean2.setRet_url("未知"); 81 82 regBean2.setRemarks("无备注"); 83 84 85 86 List<RegBean> regBeans = new ArrayList<RegBean>(); 87 88 regBeans.add(regBean); 89 90 regBeans.add(regBean2); 91 92 93 94 MsgRegBean msgRegBean = new MsgRegBean(); 95 96 msgRegBean.setDataBean(dataBean); 97 98 msgRegBean.setRegBeans(regBeans); 99 100 101 102 String regRequestXml = JaxbObjectAndXmlUtil.object2Xml(msgRegBean);//构造报文 XML 格式的字符串 103 104 105 System.out.println("\n 请求报文XML: \n"+regRequestXml); 106 /** 获取的Result报文,然后客户端处理业务。 */ 107 108 String resultString = HttpUtils.httpPost("http://localhost:8080/imaopay/pay/ipservice/user/doTest",regRequestXml); 109 110 111 112 System.out.println("\n 获取的Result报文: \n"+resultString); 113 114 } 115 116 public static void main(String[] args) throws UnsupportedEncodingException { 117 118 /** 构造测试报文头对象 */ 119 RandomStringUtils.randomNumeric(8); 120 DataBean dataBean = new DataBean(); 121 122 dataBean.setBatch_no("N20150204"); 123 124 dataBean.setData_type("000001"); 125 126 dataBean.setVersion("v1.0"); 127 128 dataBean.setUser_name("13957706713"); 129 130 dataBean.setMsg_sign("未知"); 131 132 dataBean.setRd_num(UUID.randomUUID().toString()); 133 134 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 135 String date = sdf.format(new Date(System.currentTimeMillis()*1000L)); 136 dataBean.setRd_time(date); 137 138 dataBean.setK_sign("aaaaaa"); 139 140 141 /** 构造测试报文体对象 */ 142 143 RegBean regBean = new RegBean(); 144 145 regBean.setReg_sn("REG20150204"); 146 147 regBean.setUser_id(15); 148 149 regBean.setReg_no("33"); 150 151 regBean.setReg_way("pc"); 152 153 regBean.setSet_time(new Date().toLocaleString()); 154 155 regBean.setRet_url("未知"); 156 157 regBean.setRemarks("无备注"); 158 159 160 161 RegBean regBean2 = new RegBean(); 162 163 regBean2.setReg_sn("REG20150203"); 164 165 regBean2.setUser_id(13); 166 167 regBean2.setReg_no("44"); 168 169 regBean2.setReg_way("mobile"); 170 171 regBean2.setSet_time(new Date().toLocaleString()); 172 173 regBean2.setRet_url("未知"); 174 175 regBean2.setRemarks("无备注"); 176 177 178 179 List<RegBean> regBeans = new ArrayList<RegBean>(); 180 181 regBeans.add(regBean); 182 183 regBeans.add(regBean2); 184 185 186 187 MsgRegBean msgRegBean = new MsgRegBean(); 188 189 msgRegBean.setDataBean(dataBean); 190 191 msgRegBean.setRegBeans(regBeans); 192 193 194 195 String regRequestXml = JaxbObjectAndXmlUtil.object2Xml(msgRegBean);//构造报文 XML 格式的字符串 196 197 198 System.out.println("\n 请求报文XML: \n"+regRequestXml); 199 /** 获取的Result报文,然后客户端处理业务。 */ 200 201 String resultString= HttpUtils.httpPost("http://localhost:8080/Spring-MVC-model/webservice/ipservice/user/doTest",regRequestXml); 202 203 204 205 System.out.println("\n 获取的Result报文: \n"+resultString); 206 } 207 }
运行后,控制台打印出如下结果:
客户端打印如下:
服务端获取结果如下: