zoukankan      html  css  js  c++  java
  • Restful 介绍及SpringMVC+restful 实例讲解

    restful不是一个框架,称为一种编码更烦更贴切吧,其核心类位于spring-web.jar中,即RestTemplate.class

    restful是rpc通过http协议的一种实现方式,和webservice一样,请参阅我的其他文章

    今天我将在springmvc环境中进行演示,首先请看我其他博客文章下载整理好的源码,整理好的源码可以直接用于商业项目开发

    整理好的代码项目结构如下:

    本次讲的restful大致如下

    文采不好,开始贴代码:

    ① 常量工具类,用于保存http、:、?、=、&这些的

    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);
        }
    }

    ② 模块枚举定义类

    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;

     ④ 核心调用类

    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

    相关技术均可以通过我的博客了解学习到,请锁定关注。

  • 相关阅读:
    build、host和target选项
    第一篇博客
    C++中的new和delete
    新分类:C++复习笔记
    泛读英文小说推荐
    借助查询分析器对遗留项目进行分析
    程序员等级(非本人观点)
    线程并发时的四种数据同步方法
    单元测试之什么是优秀的单元测试
    多线程之进度条
  • 原文地址:https://www.cnblogs.com/xiaochangwei/p/5419244.html
Copyright © 2011-2022 走看看