前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Restful 介绍及SpringMVC+restful 实例讲解

Restful 介绍及SpringMVC+restful 实例讲解

作者头像
肖哥哥
发布2019-02-22 10:40:29
4720
发布2019-02-22 10:40:29
举报

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

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

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

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

本次讲的restful大致如下

文采不好,开始贴代码:

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

代码语言:javascript
复制
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);
    }
}

② 模块枚举定义类

代码语言:javascript
复制
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;
    }
}

③ 参数封装类

代码语言:javascript
复制
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;

 ④ 核心调用类

代码语言:javascript
复制
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();  
        }  
    }  
}

⑤ 调用入口

代码语言:javascript
复制
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层参数封装、调用、返回结果处理类

代码语言:javascript
复制
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层测试类,包含调用入口和服务方法,此处为静态返回,可以根据具体业务书写,和常见代码一样

代码语言:javascript
复制
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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-04-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档