restful不是一個框架,稱爲一種編碼更煩更貼切吧,其核心類位於spring-web.jar中,即RestTemplate.classjava
restful是rpc經過http協議的一種實現方式,和webservice同樣,請參閱個人其餘文章web
今天我將在springmvc環境中進行演示,首先請看我其餘博客文章下載整理好的源碼,整理好的源碼能夠直接用於商業項目開發spring
整理好的代碼項目結構以下:apache
本次講的restful大體以下json
文采很差,開始貼代碼:restful
① 常量工具類,用於保存http、:、?、=、&這些的mvc
package xiaochangwei.zicp.net.restful.tools; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; public class CommonUtils { private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); private static ObjectMapper objectMapper = new ObjectMapper(); public static String HTTP_SLASH = "/"; public static String HTTP_COLON = ":"; public static String HTTP_QUESTION_MARK = "?"; public static String HTTP_EQUAL_MARK = "="; public static String HTTP_AMPERSAND = "&"; public static int INIT_VALUE = -1; public static String changeObjectToJsonStr(Object object) throws JsonProcessingException { String content = objectMapper.writeValueAsString(object); logger.debug("content = [{}].", content); return content; } public static <T> T changeJsonStrToObject(String content, Class<T> valueType) throws JsonParseException, JsonMappingException, IOException { return objectMapper.readValue(content, valueType); } }
② 模塊枚舉定義類app
package xiaochangwei.zicp.net.restful.tools; public enum ModuleEnum { MODULE_SERVICE("services", 1), MODULE_ACCESS("icp/url", 2), MODULE_SMSSend("sms/Api/Send.do", 3), MODULE_TEST("project-web/restful/restfulService", 4),; private String name; private int index; private ModuleEnum(String name, int index) { this.name = name; this.index = index; } public static String getName(int index) { for (ModuleEnum m : ModuleEnum.values()) { if (m.getIndex() == index) { return m.name; } } return null; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } }
③ 參數封裝類框架
package xiaochangwei.zicp.net.restful.tools; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.springframework.http.HttpMethod; public class ParamEntity { // IP地址。 private String ipaddr; // IP端口。 private String port;
④ 核心調用類dom
package xiaochangwei.zicp.net.restful.tools; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.client.HttpClient; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; @SuppressWarnings("deprecation") public class HttpClientUtils { private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); private static String HTTP_PROTOCOL = "http://"; public static ResponseEntity<String> Execute(ParamEntity paramEntity) { HttpClient httpClient = null; try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), Integer.valueOf(paramEntity.getPort()))); registry.register(new Scheme("https", sf, Integer.valueOf(paramEntity.getPort()))); ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry); httpClient = new DefaultHttpClient(ccm); } catch (Exception e) { logger.info("httpclient建立錯誤."); } HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); httpComponentsClientHttpRequestFactory.setConnectTimeout(120*1000); httpComponentsClientHttpRequestFactory.setReadTimeout(120*1000); RestTemplate rt = new RestTemplate(httpComponentsClientHttpRequestFactory); String url = HttpClientUtils.generateUrl(paramEntity); HttpEntity<String> requestEntity = HttpClientUtils.generateHttpEntity(paramEntity); try { System.out.println("httpMethod = " + paramEntity.getHttpMethod()); System.out.println("url = " + url); System.out.println("requestEntity = " + requestEntity); ResponseEntity<String> responseEntity = rt.exchange(url, paramEntity.getHttpMethod(), requestEntity, String.class); logger.debug("responseEntity = [{}].", responseEntity); System.out.println("responseEntity = " + responseEntity); return responseEntity; } catch (Exception e) { System.out.println("info: " + e.getMessage()); logger.debug("error info: = [{}].", e.getMessage()); return generateRespWhenException(e); } } private static ResponseEntity<String> generateRespWhenException(Exception e) { String msg = e.getMessage(); String[] strs = msg.split(" "); HttpStatus retCode; try { retCode = HttpStatus.valueOf(Integer.valueOf(strs[0])); } catch (NumberFormatException ex) { retCode = HttpStatus.SERVICE_UNAVAILABLE; } return new ResponseEntity<String>(retCode); } private static String generateUrl(ParamEntity paramEntity) { StringBuilder url = new StringBuilder(); url.append(HTTP_PROTOCOL) .append(paramEntity.getIpaddr()) .append(CommonUtils.HTTP_COLON) .append(paramEntity.getPort()) .append(CommonUtils.HTTP_SLASH); if (!StringUtils.isEmpty(paramEntity.getVersion())) { url.append(paramEntity.getVersion()).append(CommonUtils.HTTP_SLASH); } ModuleEnum module = paramEntity.getModule(); switch (module) { case MODULE_SERVICE: addServiceUri(url); break; case MODULE_SMSSend: addSMSSendUri(url, paramEntity); break; case MODULE_TEST: addUserUri(url, paramEntity); break; default: logger.error("module [{}] does not exist.", module.getName()); break; } logger.debug("url = [{}].", url.toString()); return url.toString(); } private static HttpEntity<String> generateHttpEntity(ParamEntity frontInfo) { String data = frontInfo.getData(); HttpHeaders headers = new HttpHeaders(); for (String headerKey : frontInfo.getHeadersMap().keySet()) { String headerValue = frontInfo.getHeadersMap().get(headerKey); if (!StringUtils.isEmpty(headerValue)) { headers.add(headerKey, headerValue); } } HttpEntity<String> requestEntity = new HttpEntity<String>(data, headers); logger.debug("requestEntity = [{}].", requestEntity); return requestEntity; } private static void addServiceUri(StringBuilder url) { url.append(ModuleEnum.MODULE_SERVICE.getName()); } private static void addUserUri(StringBuilder url, ParamEntity frontInfo) { url.append(ModuleEnum.MODULE_TEST.getName()); if (!StringUtils.isEmpty(frontInfo.getUser_id())) { url.append(CommonUtils.HTTP_SLASH).append(frontInfo.getUser_id()); } } private static void addSMSSendUri(StringBuilder url, ParamEntity frontInfo) { url.append(ModuleEnum.MODULE_SMSSend.getName()); boolean hasParam = false; hasParam = addParamsToUri(hasParam, "SpCode", frontInfo.getSmsSpCode(), url); hasParam = addParamsToUri(hasParam, "LoginName", frontInfo.getSmsLoginName(), url); hasParam = addParamsToUri(hasParam, "Password", frontInfo.getSmsPassword(), url); hasParam = addParamsToUri(hasParam, "MessageContent", frontInfo.getSmsMessageContent(), url); hasParam = addParamsToUri(hasParam, "UserNumber", frontInfo.getSmsUserNumber(), url); hasParam = addParamsToUri(hasParam, "SerialNumber", frontInfo.getSmsSerialNumber(), url); hasParam = addParamsToUri(hasParam, "ScheduleTime", frontInfo.getSmsScheduleTime(), url); hasParam = addParamsToUri(hasParam, "f", frontInfo.getSmsf(), url); } private static boolean addParamsToUri(boolean hasParam, String descripition, String param, StringBuilder url) { if (!StringUtils.isEmpty(param) && !param.equals("null")) { if (hasParam) { url.append(CommonUtils.HTTP_AMPERSAND); } else { url.append(CommonUtils.HTTP_QUESTION_MARK); } url.append(descripition).append(CommonUtils.HTTP_EQUAL_MARK).append(param); return true; } return false; } private static class MySSLSocketFactory extends SSLSocketFactory { SSLContext sslContext = SSLContext.getInstance("TLS"); public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(truststore); TrustManager tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; sslContext.init(null, new TrustManager[] { tm }, null); } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); } @Override public Socket createSocket() throws IOException { return sslContext.getSocketFactory().createSocket(); } } }
⑤ 調用入口
package xiaochangwei.zicp.net.restful.operation.impl; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import xiaochangwei.zicp.net.restful.operation.RestfulTestOperation; import xiaochangwei.zicp.net.restful.tools.ParamEntity; import xiaochangwei.zicp.net.restful.tools.HttpClientUtils; import xiaochangwei.zicp.net.restful.tools.ModuleEnum; /** * @author http://www.cnblogs.com/xiaochangwei * @date 2016年4月20日 * */ @Component public class RestfulTestOperationImpl implements RestfulTestOperation { public ResponseEntity<String> restfulTestMethod(ParamEntity paramEntity) { paramEntity.setModule(ModuleEnum.MODULE_TEST); paramEntity.setHttpMethod(HttpMethod.POST); ResponseEntity<String> responseEntity = HttpClientUtils.Execute(paramEntity); return responseEntity; } }
⑥ service層參數封裝、調用、返回結果處理類
package xiaochangwei.zicp.net.service.restful; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import xiaochangwei.zicp.net.restful.operation.RestfulTestOperation; import xiaochangwei.zicp.net.restful.tools.ParamEntity; /** * @author http://www.cnblogs.com/xiaochangwei * @date 2016年4月20日 * */ @Service public class RestfulTestServiceImpl implements RestfulTestService { @Autowired private RestfulTestOperation restfulTestOperation; public String restfulTestMethod() { ParamEntity info = new ParamEntity(); Map<String, Map<String, Object>> dataMap = new HashMap<String, Map<String, Object>>(); Map<String, Object> userEntity = new HashMap<String, Object>(); userEntity.put("default_project_id", "pid"); userEntity.put("description", "user.getDescription()"); userEntity.put("domain_id", "default"); userEntity.put("email", "user.getEmail()"); userEntity.put("enabled", true); userEntity.put("name", "user.getUsername()"); userEntity.put("password", "user.getStrPassword()"); dataMap.put("user", userEntity); String data = JSON.toJSONString(dataMap); info.setData(data); info.setIpaddr("127.0.0.1"); info.setPort("808"); ResponseEntity<String> response = restfulTestOperation.restfulTestMethod(info); // 當建立某個用戶失敗時 if (response == null || !response.getStatusCode().equals(HttpStatus.CREATED)) { throw new RuntimeException("調用接口建立用戶失敗!"); } else { JSONObject object = JSONObject.parseObject(response.getBody().toString()); JSONObject userJson = JSONObject.parseObject(object.getString("user")); System.out.println("解析body爲json後的用戶id爲:"+userJson.getString("id")); //return userJson.getString("id"); return response.getBody().toString(); } } }
⑦ controller層測試類,包含調用入口和服務方法,此處爲靜態返回,能夠根據具體業務書寫,和常見代碼同樣
package xiaochangwei.zicp.net.web.controller; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSON; import xiaochangwei.zicp.net.entity.TestEntity; import xiaochangwei.zicp.net.service.restful.RestfulTestService; /** * @author http://www.cnblogs.com/xiaochangwei * @date 2016年4月20日 * */ @Controller @RequestMapping("restful") public class RestfulTestController { @Autowired private RestfulTestService restfulTestService; /** * 處理restClient請求的的方法體 */ @RequestMapping("restfulService") public ResponseEntity<String> testRestClientAdd( @RequestHeader("Accept") String Accept, @RequestBody String userStr) { System.out.println("接收到的請求信息-Accept:" + Accept); System.out.println("接收到的請求信息-body:" + userStr); // 能夠根據請請進行業務處理,這裏略了 只是打印出來肯定消息傳遞過來沒 // 返回處理結果給調用者 TestEntity en = new TestEntity(); en.setId(1); en.setName("name1"); Map<String, Object> map = new HashMap<String, Object>(); map.put("user", en); String body = JSON.toJSONString(map); System.out.println("準備返回給調用者的body content:" + body); ResponseEntity<String> responseEntity = new ResponseEntity<String>( body, HttpStatus.CREATED); return responseEntity; } /** * 調用rest接口方法進行rpc調用 */ @RequestMapping("restfulClientCall") public @ResponseBody String t() { return restfulTestService.restfulTestMethod(); } }
⑧ 見證奇蹟的時候又到了
輸入 http://www.xiaochangwei.com:808/project-web/restful/restfulClientCall 進行調用,restful會訪問咱們這個controller中的restfulService
同時控制檯也看到以下信息,證實咱們的調用成功
至此,restful使用講解完畢,不過須要提醒的時,restful是經過http協議進行傳輸的,同等條件下速度比tcp慢,因此實時性較高請使用tcp實現的rpc或者採用jms
相關技術都可以經過個人博客瞭解學習到,請鎖定關注。