精华内容
下载资源
问答
  • java自定义http请求

    千次阅读 2016-05-31 23:12:28
    HttpResponser.java package com.cg.scoket.httpscodket; import java.util.Vector; /** * 响应对象 */ public class HttpResponser { String urlString; int defaultPort; String file; String ...

    HttpResponser.java

    package com.cg.scoket.httpscodket;
    import java.util.Vector;
     
    /**
     * 响应对象
     */
    public class HttpResponser {
     
    	String urlString;
     
    	int defaultPort;
     
    	String file;
     
    	String host;
     
    	String path;
     
    	int port;
     
    	String protocol;
     
    	String query;
     
    	String ref;
     
    	String userInfo;
     
    	String contentEncoding;
     
    	String content;
     
    	String contentType;
     
    	int code;
     
    	String message;
     
    	String method;
     
    	int connectTimeout;
     
    	int readTimeout;
     
    	Vector<String> contentCollection;
     
    	public String getContent() {
    		return content;
    	}
     
    	public String getContentType() {
    		return contentType;
    	}
     
    	public int getCode() {
    		return code;
    	}
     
    	public String getMessage() {
    		return message;
    	}
     
    	public Vector<String> getContentCollection() {
    		return contentCollection;
    	}
     
    	public String getContentEncoding() {
    		return contentEncoding;
    	}
     
    	public String getMethod() {
    		return method;
    	}
     
    	public int getConnectTimeout() {
    		return connectTimeout;
    	}
     
    	public int getReadTimeout() {
    		return readTimeout;
    	}
     
    	public String getUrlString() {
    		return urlString;
    	}
     
    	public int getDefaultPort() {
    		return defaultPort;
    	}
     
    	public String getFile() {
    		return file;
    	}
     
    	public String getHost() {
    		return host;
    	}
     
    	public String getPath() {
    		return path;
    	}
     
    	public int getPort() {
    		return port;
    	}
     
    	public String getProtocol() {
    		return protocol;
    	}
     
    	public String getQuery() {
    		return query;
    	}
     
    	public String getRef() {
    		return ref;
    	}
     
    	public String getUserInfo() {
    		return userInfo;
    	}
     
    }
    
    	    			
    HttpUtils.java

    package com.cg.scoket.httpscodket;  
          
        import java.io.BufferedReader;  
        import java.io.ByteArrayOutputStream;  
        import java.io.IOException;  
        import java.io.InputStream;  
        import java.io.InputStreamReader;  
        import java.io.OutputStream;  
        import java.net.HttpURLConnection;  
        import java.net.InetAddress;  
        import java.net.Socket;  
        import java.net.URL;  
        import java.net.URLConnection;  
        import java.net.URLEncoder;  
        import java.nio.charset.Charset;  
        import java.util.HashMap;  
        import java.util.Map;  
        import java.util.Map.Entry;  
        import java.util.Set;  
        import java.util.Vector;  
          
        /** 
         * @author JetChen
         * @date 2016-5-31 晚上23:08 
         * @version 1.0-SNAPSHOT 
         */  
        public class HttpUtils {  
          
            private String defaultContentEncoding;  
          
            public HttpUtils() {  
                this.defaultContentEncoding = Charset.defaultCharset().name();  
            }  
          
            /** 
             * 发送GET请求 
             *  
             * @param urlString  URL地址 
             * @return 响应对象 
             * @throws IOException 
             */  
            public HttpResponser sendGet(String urlString) throws IOException {  
                return this.send(urlString, "GET", null, null);  
            }  
          
            /** 
             * 发送GET请求 
             *  
             * @param urlString  URL地址 
             * @param params 参数集合 
             * @return 响应对象 
             * @throws IOException 
             */  
            public HttpResponser sendGet(String urlString, Map<String, String> params) throws IOException {  
                return this.send(urlString, "GET", params, null);  
            }  
          
            /** 
             * 发送GET请求 
             *  
             * @param urlString URL地址 
             * @param params 参数集合 
             * @param propertys 请求属性 
             * @return 响应对象 
             * @throws IOException 
             */  
            public HttpResponser sendGet(String urlString, Map<String, String> params, Map<String, String> propertys)  
                    throws IOException {  
                return this.send(urlString, "GET", params, propertys);  
            }  
          
            /** 
             * 发送POST请求 
             *  
             * @param urlString URL地址 
             * @return 响应对象 
             * @throws IOException 
             */  
            public HttpResponser sendPost(String urlString) throws IOException {  
                return this.send(urlString, "POST", null, null);  
            }  
          
            /** 
             * 发送POST请求 
             *  
             * @param urlString URL地址 
             * @param params 参数集合 
             * @return 响应对象 
             * @throws IOException 
             */  
            public HttpResponser sendPost(String urlString, Map<String, String> params) throws IOException {  
                return this.send(urlString, "POST", params, null);  
            }  
          
            /** 
             * 发送POST请求 
             *  
             * @param urlString URL地址 
             * @param params 参数集合 
             * @param propertys 请求属性 
             * @return 响应对象 
             * @throws IOException 
             */  
            public HttpResponser sendPost(String urlString, Map<String, String> params, Map<String, String> propertys)  
                    throws IOException {  
                return this.send(urlString, "POST", params, propertys);  
            }  
          
            /** 
             * 发送HTTP请求 
             *  
             * @param urlString 地址 
             * @param method  get/post 
             * @param parameters  添加由键值对指定的请求参数 
             * @param propertys  添加由键值对指定的一般请求属性 
             * @return 响映对象 
             * @throws IOException 
             */  
            private HttpResponser send(String urlString, String method, Map<String, String> parameters,  
                    Map<String, String> propertys) throws IOException {  
                HttpURLConnection urlConnection = null;  
          
                if (method.equalsIgnoreCase("GET") && parameters != null) {  
                    StringBuffer param = new StringBuffer();  
                    int i = 0;  
                    for (String key : parameters.keySet()) {  
                        if (i == 0)  
                            param.append("?");  
                        else  
                            param.append("&");  
                        param.append(key).append("=").append(parameters.get(key));  
                        i++;  
                    }  
                    urlString += param;  
                }  
          
                URL url = new URL(urlString);  
                urlConnection = (HttpURLConnection) url.openConnection();  
                urlConnection.setRequestMethod(method);  
                urlConnection.setDoOutput(true);  
                urlConnection.setDoInput(true);  
                urlConnection.setUseCaches(false);  
          
                if (propertys != null)  
                    for (String key : propertys.keySet()) {  
                        urlConnection.addRequestProperty(key, propertys.get(key));  
                    }  
          
                if (method.equalsIgnoreCase("POST") && parameters != null) {  
                    StringBuffer param = new StringBuffer();  
                    for (String key : parameters.keySet()) {  
                        param.append("&");  
                        param.append(key).append("=").append(parameters.get(key));  
                    }  
                    urlConnection.getOutputStream().write(param.toString().getBytes());  
                    urlConnection.getOutputStream().flush();  
                    urlConnection.getOutputStream().close();  
                }  
                return this.makeContent(urlString, urlConnection);  
            }  
          
            /** 
             * 得到响应对象 
             *  
             * @param urlConnection 
             * @return 响应对象 
             * @throws IOException 
             */  
            private HttpResponser makeContent(String urlString, HttpURLConnection urlConnection) throws IOException {  
                HttpResponser HttpResponserer = new HttpResponser();  
                try {  
                    InputStream in = urlConnection.getInputStream();  
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));  
                    HttpResponserer.contentCollection = new Vector<String>();  
                    StringBuffer temp = new StringBuffer();  
                    String line = bufferedReader.readLine();  
                    while (line != null) {  
                        HttpResponserer.contentCollection.add(line);  
                        temp.append(line).append("\r\n");  
                        line = bufferedReader.readLine();  
                    }  
                    bufferedReader.close();  
                    String ecod = urlConnection.getContentEncoding();  
                    if (ecod == null)  
                        ecod = this.defaultContentEncoding;  
                    HttpResponserer.urlString = urlString;  
                    HttpResponserer.defaultPort = urlConnection.getURL().getDefaultPort();  
                    HttpResponserer.file = urlConnection.getURL().getFile();  
                    HttpResponserer.host = urlConnection.getURL().getHost();  
                    HttpResponserer.path = urlConnection.getURL().getPath();  
                    HttpResponserer.port = urlConnection.getURL().getPort();  
                    HttpResponserer.protocol = urlConnection.getURL().getProtocol();  
                    HttpResponserer.query = urlConnection.getURL().getQuery();  
                    HttpResponserer.ref = urlConnection.getURL().getRef();  
                    HttpResponserer.userInfo = urlConnection.getURL().getUserInfo();  
                    HttpResponserer.content = new String(temp.toString().getBytes(), ecod);  
                    HttpResponserer.contentEncoding = ecod;  
                    HttpResponserer.code = urlConnection.getResponseCode();  
                    HttpResponserer.message = urlConnection.getResponseMessage();  
                    HttpResponserer.contentType = urlConnection.getContentType();  
                    HttpResponserer.method = urlConnection.getRequestMethod();  
                    HttpResponserer.connectTimeout = urlConnection.getConnectTimeout();  
                    HttpResponserer.readTimeout = urlConnection.getReadTimeout();  
                    return HttpResponserer;  
                } catch (IOException e) {  
                    throw e;  
                } finally {  
                    if (urlConnection != null)  
                        urlConnection.disconnect();  
                }  
            }  
          
            /** 
             * 默认的响应字符集 
             */  
            public String getDefaultContentEncoding() {  
                return this.defaultContentEncoding;  
            }  
          
              
            /** 
             * 发送GET请求 
             * @param url 
             * @param params 
             * @param headers 
             * @return 
             * @throws Exception 
             */  
            public static URLConnection sendGetRequest(String url,  
                    Map<String, String> params, Map<String, String> headers)  
                    throws Exception {  
                StringBuilder buf = new StringBuilder(url);  
                Set<Entry<String, String>> entrys = null;  
                // 如果是GET请求,则请求参数在URL中  
                if (params != null && !params.isEmpty()) {  
                    buf.append("?");  
                    entrys = params.entrySet();  
                    for (Map.Entry<String, String> entry : entrys) {  
                        buf.append(entry.getKey()).append("=")  
                                .append(URLEncoder.encode(entry.getValue(), "UTF-8"))  
                                .append("&");  
                    }  
                    buf.deleteCharAt(buf.length() - 1);  
                }  
                URL url1 = new URL(buf.toString());  
                HttpURLConnection conn = (HttpURLConnection) url1.openConnection();  
                conn.setRequestMethod("GET");  
                // 设置请求头  
                if (headers != null && !headers.isEmpty()) {  
                    entrys = headers.entrySet();  
                    for (Map.Entry<String, String> entry : entrys) {  
                        conn.setRequestProperty(entry.getKey(), entry.getValue());  
                    }  
                }  
                conn.getResponseCode();  
                return conn;  
            }  
            /** 
             * 发送POST请求 
             * @param url    
             * @param params 
             * @param headers 
             * @return  
             * @throws Exception 
             */  
            public static URLConnection sendPostRequest(String url,  
                    Map<String, String> params, Map<String, String> headers)  
                    throws Exception {  
                StringBuilder buf = new StringBuilder();  
                Set<Entry<String, String>> entrys = null;  
                // 如果存在参数,则放在HTTP请求体,形如name=aaa&age=10  
                if (params != null && !params.isEmpty()) {  
                    entrys = params.entrySet();  
                    for (Map.Entry<String, String> entry : entrys) {  
                        buf.append(entry.getKey()).append("=")  
                                .append(URLEncoder.encode(entry.getValue(), "UTF-8"))  
                                .append("&");  
                    }  
                    buf.deleteCharAt(buf.length() - 1);  
                }  
                URL url1 = new URL(url);  
                HttpURLConnection conn = (HttpURLConnection) url1.openConnection();  
                conn.setRequestMethod("POST");  
                conn.setDoOutput(true);  
                OutputStream out = conn.getOutputStream();  
                out.write(buf.toString().getBytes("UTF-8"));  
                if (headers != null && !headers.isEmpty()) {  
                    entrys = headers.entrySet();  
                    for (Map.Entry<String, String> entry : entrys) {  
                        conn.setRequestProperty(entry.getKey(), entry.getValue());  
                    }  
                }  
                conn.getResponseCode(); // 为了发送成功  
                return conn;  
            }  
            /** 
             * 直接通过HTTP协议提交数据到服务器,实现如下面表单提交功能: 
             *   <FORM METHOD=POST ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data"> 
                    <INPUT TYPE="text" NAME="name"> 
                    <INPUT TYPE="text" NAME="id"> 
                    <input type="file" name="imagefile"/> 
                    <input type="file" name="zip"/> 
                 </FORM> 
             * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试) 
             * @param params 请求参数 key为参数名,value为参数值 
             * @param file 上传文件 
             */  
            public static boolean uploadFiles(String path, Map<String, String> params, FormFile[] files) throws Exception{       
                final String BOUNDARY = "---------------------------7da2137580612"; //数据分隔线  
                final String endline = "--" + BOUNDARY + "--\r\n";//数据结束标志  
                  
                int fileDataLength = 0;  
                if(files!=null&&files.length!=0){  
                    for(FormFile uploadFile : files){//得到文件类型数据的总长度  
                        StringBuilder fileExplain = new StringBuilder();  
                        fileExplain.append("--");  
                        fileExplain.append(BOUNDARY);  
                        fileExplain.append("\r\n");  
                        fileExplain.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");  
                        fileExplain.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");  
                        fileExplain.append("\r\n");  
                        fileDataLength += fileExplain.length();  
                        if(uploadFile.getInStream()!=null){  
                            fileDataLength += uploadFile.getFile().length();  
                        }else{  
                            fileDataLength += uploadFile.getData().length;  
                        }  
                    }  
                }  
                StringBuilder textEntity = new StringBuilder();  
                if(params!=null&&!params.isEmpty()){  
                    for (Map.Entry<String, String> entry : params.entrySet()) {//构造文本类型参数的实体数据  
                        textEntity.append("--");  
                        textEntity.append(BOUNDARY);  
                        textEntity.append("\r\n");  
                        textEntity.append("Content-Disposition: form-data; name=\""+ entry.getKey() + "\"\r\n\r\n");  
                        textEntity.append(entry.getValue());  
                        textEntity.append("\r\n");  
                    }  
                }  
                //计算传输给服务器的实体数据总长度  
                int dataLength = textEntity.toString().getBytes().length + fileDataLength +  endline.getBytes().length;  
                  
                URL url = new URL(path);  
                int port = url.getPort()==-1 ? 80 : url.getPort();  
                Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);          
                OutputStream outStream = socket.getOutputStream();  
                //下面完成HTTP请求头的发送  
                String requestmethod = "POST "+ url.getPath()+" HTTP/1.1\r\n";  
                outStream.write(requestmethod.getBytes());  
                String accept = "Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*\r\n";  
                outStream.write(accept.getBytes());  
                String language = "Accept-Language: zh-CN\r\n";  
                outStream.write(language.getBytes());  
                String contenttype = "Content-Type: multipart/form-data; boundary="+ BOUNDARY+ "\r\n";  
                outStream.write(contenttype.getBytes());  
                String contentlength = "Content-Length: "+ dataLength + "\r\n";  
                outStream.write(contentlength.getBytes());  
                String alive = "Connection: Keep-Alive\r\n";  
                outStream.write(alive.getBytes());  
                String host = "Host: "+ url.getHost() +":"+ port +"\r\n";  
                outStream.write(host.getBytes());  
                //写完HTTP请求头后根据HTTP协议再写一个回车换行  
                outStream.write("\r\n".getBytes());  
                //把所有文本类型的实体数据发送出来  
                outStream.write(textEntity.toString().getBytes());           
                //把所有文件类型的实体数据发送出来  
                if(files!=null&&files.length!=0){  
                    for(FormFile uploadFile : files){  
                        StringBuilder fileEntity = new StringBuilder();  
                        fileEntity.append("--");  
                        fileEntity.append(BOUNDARY);  
                        fileEntity.append("\r\n");  
                        fileEntity.append("Content-Disposition: form-data;name=\""+ uploadFile.getParameterName()+"\";filename=\""+ uploadFile.getFilname() + "\"\r\n");  
                        fileEntity.append("Content-Type: "+ uploadFile.getContentType()+"\r\n\r\n");  
                        outStream.write(fileEntity.toString().getBytes());  
                        if(uploadFile.getInStream()!=null){  
                            byte[] buffer = new byte[1024];  
                            int len = 0;  
                            while((len = uploadFile.getInStream().read(buffer, 0, 1024))!=-1){  
                                outStream.write(buffer, 0, len);  
                            }  
                            uploadFile.getInStream().close();  
                        }else{  
                            outStream.write(uploadFile.getData(), 0, uploadFile.getData().length);  
                        }  
                        outStream.write("\r\n".getBytes());  
                    }  
                }  
                //下面发送数据结束标志,表示数据已经结束  
                outStream.write(endline.getBytes());  
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));  
                if(reader.readLine().indexOf("200")==-1){//读取web服务器返回的数据,判断请求码是否为200,如果不是200,代表请求失败  
                    return false;  
                }  
                outStream.flush();  
                outStream.close();  
                reader.close();  
                socket.close();  
                return true;  
            }  
            /**  
             * 提交数据到服务器  
             * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.itcast.cn或http://192.168.1.10:8080这样的路径测试)  
             * @param params 请求参数 key为参数名,value为参数值  
             * @param file 上传文件  
             */  
            public static boolean uploadFile(String path, Map<String, String> params, FormFile file) throws Exception{  
               return uploadFiles(path, params, new FormFile[]{file});  
            }  
            /** 
             * 将输入流转为字节数组 
             * @param inStream 
             * @return 
             * @throws Exception 
             */  
            public static byte[] read2Byte(InputStream inStream)throws Exception{  
                ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  
                byte[] buffer = new byte[1024];  
                int len = 0;  
                while( (len = inStream.read(buffer)) !=-1 ){  
                    outSteam.write(buffer, 0, len);  
                }  
                outSteam.close();  
                inStream.close();  
                return outSteam.toByteArray();  
            }  
            /** 
             * 将输入流转为字符串 
             * @param inStream 
             * @return 
             * @throws Exception 
             */  
            public static String read2String(InputStream inStream)throws Exception{  
                ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  
                byte[] buffer = new byte[1024];  
                int len = 0;  
                while( (len = inStream.read(buffer)) !=-1 ){  
                    outSteam.write(buffer, 0, len);  
                }  
                outSteam.close();  
                inStream.close();  
                return new String(outSteam.toByteArray(),"UTF-8");  
            }  
            /** 
             * 发送xml数据 
             * @param path 请求地址 
             * @param xml xml数据 
             * @param encoding 编码 
             * @return 
             * @throws Exception 
             */  
            public static byte[] postXml(String path, String xml, String encoding) throws Exception{  
                byte[] data = xml.getBytes(encoding);  
                URL url = new URL(path);  
                HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
                conn.setRequestMethod("POST");  
                conn.setDoOutput(true);  
                conn.setRequestProperty("Content-Type", "text/xml; charset="+ encoding);  
                conn.setRequestProperty("Content-Length", String.valueOf(data.length));  
                conn.setConnectTimeout(5 * 1000);  
                OutputStream outStream = conn.getOutputStream();  
                outStream.write(data);  
                outStream.flush();  
                outStream.close();  
                if(conn.getResponseCode()==200){  
                    return read2Byte(conn.getInputStream());  
                }  
                return null;  
            }  
            //测试函数  
            public static void main(String args[]) throws Exception {  
                Map<String, String> params = new HashMap<String, String>();  
                params.put("name", "xiazdong");  
                params.put("age", "10");  
                HttpURLConnection conn = (HttpURLConnection)  
                        sendGetRequest(  
                                "http://192.168.0.103:8080/Server/PrintServlet",  
                                params, null);  
                int code = conn.getResponseCode();  
                InputStream in = conn.getInputStream();  
                byte[]data = read2Byte(in);  
            }  
              
            /** 
             * 设置默认的响应字符集 
             */  
            public void setDefaultContentEncoding(String defaultContentEncoding) {  
                this.defaultContentEncoding = defaultContentEncoding;  
            }  
        }  

    FormFile.java

    package com.cg.scoket.httpscodket;
    
    import java.io.File;  
    import java.io.FileInputStream;  
    import java.io.FileNotFoundException;  
    import java.io.InputStream;  
      
    /** 
     * 上传文件 
     */  
    public class FormFile {  
        /* 上传文件的数据 */  
        private byte[] data;  
        private InputStream inStream;  
        private File file;  
        /* 文件名称 */  
        private String filname;  
        /* 请求参数名称*/  
        private String parameterName;  
        /* 内容类型 */  
        private String contentType = "application/octet-stream";  
          
        /** 
         * 此函数用来传输小文件 
         * @param filname 
         * @param data 
         * @param parameterName 
         * @param contentType 
         */  
        public FormFile(String filname, byte[] data, String parameterName, String contentType) {  
            this.data = data;  
            this.filname = filname;  
            this.parameterName = parameterName;  
            if(contentType!=null) this.contentType = contentType;  
        }  
        /** 
         * 此函数用来传输大文件 
         * @param filname 
         * @param file 
         * @param parameterName 
         * @param contentType 
         */  
        public FormFile(String filname, File file, String parameterName, String contentType) {  
            this.filname = filname;  
            this.parameterName = parameterName;  
            this.file = file;  
            try {  
                this.inStream = new FileInputStream(file);  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            }  
            if(contentType!=null) this.contentType = contentType;  
        }  
          
        public File getFile() {  
            return file;  
        }  
      
        public InputStream getInStream() {  
            return inStream;  
        }  
      
        public byte[] getData() {  
            return data;  
        }  
      
        public String getFilname() {  
            return filname;  
        }  
      
        public void setFilname(String filname) {  
            this.filname = filname;  
        }  
      
        public String getParameterName() {  
            return parameterName;  
        }  
      
        public void setParameterName(String parameterName) {  
            this.parameterName = parameterName;  
        }  
      
        public String getContentType() {  
            return contentType;  
        }  
      
        public void setContentType(String contentType) {  
            this.contentType = contentType;  
        }  
          
    }  



    展开全文
  • SimpleHTTPServer SimpleHTTPServer是用于处理的HTTP Server实现。 它可以处理静态文件(html,css,js)... 这样,它还可以处理PUT请求或使用JSON进行回答。 可以将回调添加到简单的Filehandles中,以控制查询参数。
  • 便携式Java HTTP服务器,用于通过自定义网络限制进行文件共享,并支持同时处理多个请求。有时,您只希望小型服务器通过http共享文件,这类似于python的SimpleHttpServer,但支持多个请求。 怎么建呢? ./gradlew...
  • java socket通信自定义消息协议

    热门讨论 2010-05-26 16:26:34
    java socket通信自定义消息协议,socket以字节码的方式通信传递,客户端与服务器端分别进行转换与解析的过程实现简单的消息协议。
  • 可以执行 get 和 post 请求,从 Web 服务器接收文本和二进制答案,设置自定义标头等。 支持 Http 和 https 请求。 用法 Maven 添加到您的部分: <id>dunnololda's maven repo <url>...
  • SpringBoot发送Http请求-RestTemplate

    万次阅读 多人点赞 2020-05-14 12:05:41
    SpringBoot发送Http请求 [提前声明] 文章由作者:张耀峰 结合自己生产中的使用经验整理,最终形成简单易懂的文章 写作不易,转载请注明,谢谢! 大数据代码案例地址: https://github.com/Mydreamandreality/sparkResearch...

    SpringBoot发送Http请求

    [提前声明]
    文章由作者:张耀峰 结合自己生产中的使用经验整理,最终形成简单易懂的文章
    写作不易,转载请注明,谢谢!
    大数据代码案例地址: https://github.com/Mydreamandreality/sparkResearch


    前言

    之前我写过一篇关于SpringBoot发送Http请求的文章、当时使用的是Apache,Http.client
    文章地址:图解springboot后端发送HttpGet和HttpPost请求
    但是使用这个工具发送请求很繁琐、代码看起来也很复杂、而且大部分都是冗余的代码、而Spring给我们提供了一个发送Http请求的工具、所以我觉得有必要安利一下

    RestTemplate

    首先看下spring官方对RestTemplate的解释

    在这里插入图片描述

    RestTemplate是Spring用于同步client端的核心类,简化了与http服务的通信,并满足RestFul原则,程序代码可以给它提供URL,并提取结果。默认情况下,RestTemplate默认依赖jdk的HTTP连接工具。当然你也可以 通过setRequestFactory属性切换到不同的HTTP源,比如Apache HttpComponents、Netty和OkHttp

    如何使用

    经过简单了解后、我们不多bb、直接上代码、通过代码来说话

    • 1、pom配置

    先声明下我的SpringBoot版本:<version>2.1.13.RELEASE</version>
    org.springframework.web中已经默认集成了RestTemplate

    引用apache的httclient (不是用RestTemplate吗?为什么又引用了apache的client、别急 稍后解释

            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.5.6</version>
            </dependency>
    
    • 2、RestTemplate配置

    在Spring的官方文档中可以了解到、RestTemplate 采用同步方式执行 HTTP 请求的类,底层使用 JDK 原生 HttpURLConnection API ,或者 HttpComponents等其他 HTTP 客户端请求类库。还有一处强调的就是 RestTemplate 提供模板化的方法让开发者能更简单地发送 HTTP 请求

    既然如此、那么我们底层依然使用apache的client给我们提供的http请求服务能力、上层的应用开发使用RestTemplate的模板

    ClientHttpRequestFactory 接口有4个实现类,分别是:

    • AbstractClientHttpRequestFactoryWrapper 用来装配其他request factory的抽象类。
    • CommonsClientHttpRequestFactory 允许用户配置带有认证和http连接池的httpclient,已废弃,推荐用HttpComponentsClientHttpRequestFactory。
    • HttpComponentsClientHttpRequestFactory 同2.
    • SimpleClientHttpRequestFactory 接口的一个简单实现,可配置proxy,connectTimeout,readTimeout等参数。

    我们使用的是HttpComponentsClientHttpRequestFactory来配置

    • 配置application.yml

    首先我们自定义一些配置参数、后面会用到

    http_pool:
      max_total: 200
      default_max_per_route: 100
      connect_timeout: 5000
      connection_request_timeout: 1000
      socket_timeout: 65000
      validate_after_inactivity: 2000
    
    • 新建ApplicationValues.java

    这个是读取配置中的参数方法

    import lombok.Getter;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    /**
     * @author 孤
     * @version v1.0
     * @Developers 张耀烽
     * @serviceProvider 四叶草安全(SeClover)
     * @description 获取Application配置数据
     * @date
     */
    @Getter
    @Component
    public class ApplicationValues {
    
        @Value("${http_pool.max_total}")
        private int maxTotal;
    
        @Value("${http_pool.default_max_per_route}")
        private int maxPerRoute;
    
        @Value("${http_pool.connect_timeout}")
        private int connTimeOut;
    
        @Value("${http_pool.connection_request_timeout}")
        private int connReqTimeOut;
    
        @Value("${http_pool.socket_timeout}")
        private int socketTimeout;
    
        @Value("${http_pool.validate_after_inactivity}")
        private int inactivity;
    }
    
    • 新建RestTemplateConfig.java

    这个是配置我们的底层http客户端(这里我们使用apache的client

    如何配置:

    Spring提供了HttpComponentsClientHttpRequestFactory可以通过该方法来配置我们的http客户端

    import com.clover.api.consts.ApplicationValues;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.client.ClientHttpRequestFactory;
    import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * @author 孤
     * @version v1.0
     * @Developers 张耀烽
     * @serviceProvider 四叶草安全(SeClover)
     * @description http工厂配置
     * @date
     */
    @Configuration
    public class RestTemplateConfig {
    
        @Autowired
        private ApplicationValues appValues;
    
        @Bean
        public RestTemplate restTemplate() {
            return new RestTemplate(httpRequestFactory());
        }
    
        @Bean
        public ClientHttpRequestFactory httpRequestFactory() {
            return new HttpComponentsClientHttpRequestFactory(httpClient());
        }
    
        @Bean
        public HttpClient httpClient() {
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", SSLConnectionSocketFactory.getSocketFactory())
                    .build();
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
            connectionManager.setMaxTotal(appValues.getMaxTotal());
            connectionManager.setDefaultMaxPerRoute(appValues.getMaxPerRoute());
            connectionManager.setValidateAfterInactivity(appValues.getInactivity());
            RequestConfig requestConfig = RequestConfig.custom()
                    //服务器返回数据(response)的时间,超过抛出read timeout
                    .setSocketTimeout(appValues.getSocketTimeout())
                    //连接上服务器(握手成功)的时间,超出抛出connect timeout
                    .setConnectTimeout(appValues.getConnTimeOut())
                    //从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                    .setConnectionRequestTimeout(appValues.getConnReqTimeOut())
                    .build();
            return HttpClientBuilder.create()
                    .setDefaultRequestConfig(requestConfig)
                    .setConnectionManager(connectionManager)
                    .build();
        }
    }
    
    • 发送请求

    RestTemplate对于不同的请求方式提供了不同的函数、我把官方的图贴一下、下面我会把常用的跟大家说一下

    在这里插入图片描述

    发送Post请求、请求参数为json

    一般的post请求都是从body中传递json参数、比如是这样的

    {
        "name":"张耀烽",
        "sex":"男"
    }
    
    • 首先我们构造我们的json请求参数
    • 其次发送请求

    请求发送成功后、会返回 ResponseEntity对象、spring把response的所有结果集都封装在了这个对象中、我们可以按需使用、此处我只获取了请求成功后返回的body

        /**
         * 生成post请求的JSON请求参数
         * 请求示例:
         * {
         * "id":1,
         * "name":"张耀烽"
         * }
         *
         * @return
         */
        public HttpEntity<Map<String, String>> generatePostJson(Map<String, String> jsonMap) {
    
            //如果需要其它的请求头信息、都可以在这里追加
            HttpHeaders httpHeaders = new HttpHeaders();
    
            MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8");
    
            httpHeaders.setContentType(type);
    
            HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(jsonMap, httpHeaders);
    
            return httpEntity;
        }
        
        
          /**
         * post请求、请求参数为json
         *
         * @return
         */
        public String sendPost() {
            String uri = "http://127.0.0.1:80";
    
            Map<String, String> jsonMap = new HashMap<>(6);
            jsonMap.put("name", "张耀烽");
            jsonMap.put("sex", "男");
    
            ResponseEntity<String> apiResponse = restTemplate.postForEntity
                    (
                            uri,
                            generatePostJson(jsonMap),
                            String.class
                    );
            return apiResponse.getBody();
        }
    

    发送get请求、请求参数为uri参数

    get的请求我们一般都是通过uri的方式来进行传参,比如:

    http://127.0.0.1:80/?name=张耀烽&sex=男

    • 首先构造我们的get请求参数
    • 发送get请求、获取结果
     /**
         * 生成get参数请求url
         * 示例:https://0.0.0.0:80/api?u=u&o=o
         * 示例:https://0.0.0.0:80/api
         *
         * @param protocol 请求协议 示例: http 或者 https
         * @param uri      请求的uri 示例: 0.0.0.0:80
         * @param params   请求参数
         * @return
         */
        public String generateRequestParameters(String protocol, String uri, Map<String, String> params) {
            StringBuilder sb = new StringBuilder(protocol).append("://").append(uri);
            if (ToolUtil.isNotEmpty(params)) {
                sb.append("?");
                for (Map.Entry map : params.entrySet()) {
                    sb.append(map.getKey())
                            .append("=")
                            .append(map.getValue())
                            .append("&");
                }
                uri = sb.substring(0, sb.length() - 1);
                return uri;
            }
            return sb.toString();
        }
    
        /**
         * get请求、请求参数为?拼接形式的
         * <p>
         * 最终请求的URI如下:
         * <p>
         * http://127.0.0.1:80/?name=张耀烽&sex=男
         *
         * @return
         */
        public String sendGet() {
            Map<String, String> uriMap = new HashMap<>(6);
            uriMap.put("name", "张耀烽");
            uriMap.put("sex", "男");
    
            ResponseEntity responseEntity = restTemplate.getForEntity
                    (
                            generateRequestParameters("http", "127.0.0.1:80", uriMap),
                            String.class
                    );
            return (String) responseEntity.getBody();
        }
    

    总结

    到此我们两种常用的请求就已经掌握了、其它的方法你们需要用的时候去看就可以了、都是一些重载的方法、大同小异。

    完整代码:

    import com.clover.api.utils.tools.ToolUtil;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpEntity;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Component;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @author 孤
     * @version v1.0
     * @Developers 张耀烽
     * @serviceProvider 四叶草安全(SeClover)
     * @description 请简易描述定义
     * @date 2020/5/14
     */
    @Component
    public class RestMock<k, v> {
    
        @Autowired
        private RestTemplate restTemplate;
    
        /**
         * 生成post请求的JSON请求参数
         * 请求示例:
         * {
         * "id":1,
         * "name":"张耀烽"
         * }
         *
         * @return
         */
        public HttpEntity<Map<String, String>> generatePostJson(Map<String, String> jsonMap) {
    
            //如果需要其它的请求头信息、都可以在这里追加
            HttpHeaders httpHeaders = new HttpHeaders();
    
            MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8");
    
            httpHeaders.setContentType(type);
    
            HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(jsonMap, httpHeaders);
    
            return httpEntity;
        }
    
    
        /**
         * 生成get参数请求url
         * 示例:https://0.0.0.0:80/api?u=u&o=o
         * 示例:https://0.0.0.0:80/api
         *
         * @param protocol 请求协议 示例: http 或者 https
         * @param uri      请求的uri 示例: 0.0.0.0:80
         * @param params   请求参数
         * @return
         */
        public String generateRequestParameters(String protocol, String uri, Map<String, String> params) {
            StringBuilder sb = new StringBuilder(protocol).append("://").append(uri);
            if (ToolUtil.isNotEmpty(params)) {
                sb.append("?");
                for (Map.Entry map : params.entrySet()) {
                    sb.append(map.getKey())
                            .append("=")
                            .append(map.getValue())
                            .append("&");
                }
                uri = sb.substring(0, sb.length() - 1);
                return uri;
            }
            return sb.toString();
        }
    
        /**
         * get请求、请求参数为?拼接形式的
         * <p>
         * 最终请求的URI如下:
         * <p>
         * http://127.0.0.1:80/?name=张耀烽&sex=男
         *
         * @return
         */
        public String sendGet() {
            Map<String, String> uriMap = new HashMap<>(6);
            uriMap.put("name", "张耀烽");
            uriMap.put("sex", "男");
    
            ResponseEntity responseEntity = restTemplate.getForEntity
                    (
                            generateRequestParameters("http", "127.0.0.1:80", uriMap),
                            String.class
                    );
            return (String) responseEntity.getBody();
        }
    
        /**
         * post请求、请求参数为json
         *
         * @return
         */
        public String sendPost() {
            String uri = "http://127.0.0.1:80";
    
            Map<String, String> jsonMap = new HashMap<>(6);
            jsonMap.put("name", "张耀烽");
            jsonMap.put("sex", "男");
    
            ResponseEntity<String> apiResponse = restTemplate.postForEntity
                    (
                            uri,
                            generatePostJson(jsonMap),
                            String.class
                    );
            return apiResponse.getBody();
        }
    
    }
    
    

    更多完整代码可以去参考我的个人开源项目easy_boot、项目地址easy_boot开源项目

    展开全文
  • 深入JAVA注解(Annotation):自定义注解

    万次阅读 多人点赞 2019-07-31 18:40:53
    要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法。 元注解:  元注解的作用就是负责注解其他注解。Java5.0定义了4...

    一、基础知识:元注解

     

    要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法。

    元注解:

      元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
        1.@Target,
        2.@Retention,
        3.@Documented,
        4.@Inherited
      这些类型和它们所支持的类在java.lang.annotation包中可以找到。下面我们看一下每个元注解的作用和相应分参数的使用说明。

      @Target:

       @Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。

      作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

      取值(ElementType)有:

        1.CONSTRUCTOR:用于描述构造器
        2.FIELD:用于描述域
        3.LOCAL_VARIABLE:用于描述局部变量
        4.METHOD:用于描述方法
        5.PACKAGE:用于描述包
        6.PARAMETER:用于描述参数
        7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

      使用实例:  

    复制代码

    @Target(ElementType.TYPE)
    public @interface Table {
        /**
         * 数据表名称注解,默认值为类名称
         * @return
         */
        public String tableName() default "className";
    }
    
    @Target(ElementType.FIELD)
    public @interface NoDBColumn {
    
    }

    复制代码

      注解Table 可以用于注解类、接口(包括注解类型) 或enum声明,而注解NoDBColumn仅可用于注解类的成员变量。

      @Retention:

      @Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。

      作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)

      取值(RetentionPoicy)有:

        1.SOURCE:在源文件中有效(即源文件保留)
        2.CLASS:在class文件中有效(即class保留)
        3.RUNTIME:在运行时有效(即运行时保留)

      Retention meta-annotation类型有唯一的value作为成员,它的取值来自java.lang.annotation.RetentionPolicy的枚举类型值。具体实例如下:

    复制代码

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Column {
        public String name() default "fieldName";
        public String setFuncName() default "setField";
        public String getFuncName() default "getField"; 
        public boolean defaultDBValue() default false;
    }

    复制代码

       Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理

      @Documented:

      @Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

    复制代码

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Column {
        public String name() default "fieldName";
        public String setFuncName() default "setField";
        public String getFuncName() default "getField"; 
        public boolean defaultDBValue() default false;
    }

    复制代码

      @Inherited:

      @Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

      注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。

      当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。

     

    实例代码:

    复制代码

    /**
     * 
     * @author peida
     *
     */
    @Inherited
    public @interface Greeting {
        public enum FontColor{ BULE,RED,GREEN};
        String name();
        FontColor fontColor() default FontColor.GREEN;
    }

    二、基础知识:自定义注解

     

    使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

      定义注解格式:
      public @interface 注解名 {定义体}

      注解参数的可支持数据类型:

        1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
        2.String类型
        3.Class类型
        4.enum类型
        5.Annotation类型
        6.以上所有类型的数组

      Annotation类型里面的参数该怎么设定: 
      第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;   
      第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;  
      第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。

      简单的自定义注解和使用注解实例:

    复制代码

    package annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 水果名称注解
     * @author peida
     *
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface FruitName {
        String value() default "";
    }

    复制代码

    复制代码

    package annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 水果颜色注解
     * @author peida
     *
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface FruitColor {
        /**
         * 颜色枚举
         * @author peida
         *
         */
        public enum Color{ BULE,RED,GREEN};
        
        /**
         * 颜色属性
         * @return
         */
        Color fruitColor() default Color.GREEN;
    
    }

    复制代码

    复制代码

    package annotation;
    
    import annotation.FruitColor.Color;
    
    public class Apple {
        
        @FruitName("Apple")
        private String appleName;
        
        @FruitColor(fruitColor=Color.RED)
        private String appleColor;
        
        
        
        
        public void setAppleColor(String appleColor) {
            this.appleColor = appleColor;
        }
        public String getAppleColor() {
            return appleColor;
        }
        
        
        public void setAppleName(String appleName) {
            this.appleName = appleName;
        }
        public String getAppleName() {
            return appleName;
        }
        
        public void displayName(){
            System.out.println("水果的名字是:苹果");
        }
    }

    复制代码


    注解元素的默认值:

      注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为每个注解的声明中,所有元素都存在,并且都具有相应的值,为了绕开这个约束,我们只能定义一些特殊的值,例如空字符串或者负数,一次表示某个元素不存在,在定义注解时,这已经成为一个习惯用法。

    三、自定义注解实例

         以上都是一些注解的基础知识,这里讲一下自定义注解的使用。一般,注解都是搭配反射的解析器共同工作的,然后利用反射机制查看类的注解内容。如下:

     

    复制代码

     1 package testAnnotation;
     2 
     3 import java.lang.annotation.Documented;
     4 import java.lang.annotation.Retention;
     5 import java.lang.annotation.RetentionPolicy;
     6 
     7 @Documented
     8 @Retention(RetentionPolicy.RUNTIME)
     9 public @interface Person{
    10     String name();
    11     int age();
    12 }

    复制代码

     

     package testAnnotation;
     2 
     3 @Person(name="xingoo",age=25)
     4 public class test3 {
     5     public static void print(Class c){
     6         System.out.println(c.getName());
     7         
     8         //java.lang.Class的getAnnotation方法,如果有注解,则返回注解。否则返回null
     9         Person person = (Person)c.getAnnotation(Person.class);
    10         
    11         if(person != null){
    12             System.out.println("name:"+person.name()+" age:"+person.age());
    13         }else{
    14             System.out.println("person unknown!");
    15         }
    16     }
    17     public static void main(String[] args){
    18         test3.print(test3.class);
    19     }
    20 }

     

    运行结果:

    testAnnotation.test3
    name:xingoo age:25

    接下来再讲一个工作中的例子就可以收篇啦!

    LoginVerify注解是用于对标注的方法在进行请求访问时进行登录判断。

     

    package com.newsee.annotation;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 是否已登录判断
     *
     */
    @Documented
    @Target(ElementType.METHOD)
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LoginVerify {
    
    }

     

    ScanningLoginVerifyAnnotation里的scanning()方法被@PostConstruct修饰,说明它在服务器加载Servlet的时候运行,并且只会被服务器执行一次。

     

    这里再科普一下:

     

    @PostConstruct和@PreDestroy。这两个注解被用来修饰一个非静态的void()方法 。写法有如下两种方式:

    @PostConstruct

    Public void someMethod() {}                                                                       
    或者

    public @PostConstruct void someMethod(){}

    被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct会在构造函数之后,init()方法之前执行。PreDestroy()方法在destroy()方法执行之后执行

     

    scanning方法是在servlet加载完毕后获取所有被加载类,遍历其中的方法,如果有被LoginVerify注解修饰,则该方法名放到一个static的map中存储起来。

     

     

    package com.newsee.annotation;
    
    import java.io.IOException;
    import java.lang.reflect.Method;
    import javax.annotation.PostConstruct;
    import org.springframework.core.io.Resource;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.core.io.support.ResourcePatternResolver;
    import org.springframework.stereotype.Component;
    import org.springframework.util.ClassUtils;
    import com.newsee.constant.LoginVerifyMapping;
    
    @Component
    public class ScanningLoginVerifyAnnotation {
    	private static final String PACKAGE_NAME = "com.newsee.face";
    
    	private static final String RESOURCE_PATTERN = "/**/*.class";
    
    	@PostConstruct
    	public void scanning() throws IOException, SecurityException,
    			ClassNotFoundException {
    		String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
    				+ ClassUtils.convertClassNameToResourcePath(PACKAGE_NAME)
    				+ RESOURCE_PATTERN;
    		ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    		Resource[] resources = resourcePatternResolver.getResources(pattern);
    		for (Resource resource : resources) {
    			if (resource.isReadable()) {
    				String className = getClassName(resource.getURL().toString());
    				Class cls = ScanningRequestCodeAnnotation.class.getClassLoader().loadClass((className));
    				for (Method method : cls.getMethods()) {
    					LoginVerify requestCode = method.getAnnotation(LoginVerify.class);
    					if (requestCode != null) {
    						</span>LoginVerifyMapping.add(className + "."+ method.getName());
    					}
    				}
    			}
    		}
    	}
    
    	private String getClassName(String resourceUrl) {
    		String url = resourceUrl.replace("/", ".");
    		url = url.replace("\\", ".");
    		url = url.split("com.newsee")[1];
    		url = url.replace(".class", "");
    		return "com.newsee" + url.trim();
    	}
    }
    

    LoginVerifyMapping就是存放被LoginVerify注解修饰的方法名的。

    public class LoginVerifyMapping {
    	private static Map<String, Boolean> faceFunctionIsNeedLoginVerify = new HashMap<String, Boolean>();
    
    	public static void add(String functionName) {
    		faceFunctionIsNeedLoginVerify.put(functionName, Boolean.TRUE);
    	}
    
    	public static Boolean getFaceFunctionIsNeedLoginVerify(String functionName) {
    		return faceFunctionIsNeedLoginVerify.get(functionName);
    	}
    }

    以下方法就是请求过来时判断请求的方法是不是在LoginVerifyMapping中,如果是,则需要进行登录校验。

    private ResponseContent handleRequests(RequestContent requestContent) throws ClassNotFoundException,
    			NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
    			InvocationTargetException {
    		String requestCode = requestContent.getRequest().getHead().getNWCode();
    		String className = RequestCodeMapping.getClassName(requestCode);
    		String beanName = RequestCodeMapping.getBeanName(requestCode);
    		String functionName = RequestCodeMapping.getFunctionName(requestCode);
    		Boolean loginVerify = LoginVerifyMapping.getFaceFunctionIsNeedLoginVerify(className + "." + functionName);
    		if (loginVerify != null && loginVerify) {//需要进行登录校验
    			boolean isAuthenticated = SecurityUtils.getSubject().isAuthenticated();
    			if (!isAuthenticated) {
    				String exId=requestContent.getRequest().getHead().getNWExID();
    				SystemMobileTokenKeyServiceInter systemMobileTokenKeyServiceInter = (SystemMobileTokenKeyServiceInter) SpringContextUtil
    					.getBean("systemMobileTokenKeyServiceInter");
    				SystemMobileTokenKey systemMobileTokenKey=systemMobileTokenKeyServiceInter.getByExId(exId);
    				if(systemMobileTokenKey==null)
    					throw new BaseException(ResponseCodeEnum.NO_LOGIN);
    				Date keyTime = systemMobileTokenKey.getKeyTime();
    				if (System.currentTimeMillis() - keyTime.getTime() > 1000 * 60 * 60 * 24 * 3)
    					throw new BaseException(ResponseCodeEnum.NO_LOGIN);
    			}
    		}
    		if (className == null || beanName == null || functionName == null)
    			throw new BaseException(ResponseCodeEnum.REQUEST_CODE_NOT_EXIST);
    		Object object = SpringContextUtil.getBean(beanName);
    		Class cls = Class.forName(className);
    		Method method = cls.getMethod(functionName, RequestContent.class);
    		Object response = method.invoke(object, requestContent);
    		return (ResponseContent) response;
    	}
    }

     

     

     

     

    展开全文
  • java自定义协议

    2020-02-26 18:02:03
    在设计 C-S 结构的应用时,我们一般需要使用一种客户端C与服务端S的通信协议。现在常用的协议有HTTP,XML-RPC,SOAP等,当然... 客户端与服务器之间通过信息(数据)交换来完成具体操作,举例来说,当客户端向服务器发送...

        在设计 C-S 结构的应用时,我们一般需要使用一种客户端C与服务端S的通信协议。现在常用的协议有HTTP,XML-RPC,SOAP等,当然,现在XML在很多场景下都用JSON替代了,这个不赘述,有些时候,我们需要设计一些自有协议,这里咱们就说一下设计自有协议时需要注意的几个点:

    1、C-S交互

        客户端与服务器之间通过信息(数据)交换来完成具体操作,举例来说,当客户端向服务器发送一个请求来执行某个操作,服务器在执行完成后向客户端回复一个处理结果,这是客户端与服务端的一次完整交互。

        当一台ComputerA向另一台ComputerB 通过网络发送信息,从A发出信息到B接收到信息需要花费一定的时间,这个网络传输时间称为时延。

    在定义协议时,完成某操作需要的交互次数越多,协议的效率就越低,如果时延很高,那效率低下就会更明显。HTTP协议完成一次操作时,只需要一次请求与一次响应,也就是只需要一次交互。而SMTP在完成一次邮件发送前会经过多次交互。

        我们只有在客户端需要向服务端发送大量的数据时,才考虑将协议操作拆分为多次交互。我们一般有两种选择:

    1、使用一次单独的交互来发送头信息

    2、将信息拆分为多个信息块

        如果服务器可以对头信息做一些初始化的预先校验,那在第一次交互时发送头信息是比较好的选择,如果头信息无效,即时数据被正常接收也是无效的。

        在传输大体量的数据时,如果中途网络连接断开,我们需要将所有数据从新发送,但如果我们将数据拆分为小的数据块,那么当网络连接失败时,我们只需要从新发送失败的数据块,然后就可以go on,已经发送成功的数据块就不需要重新发送。

    2、多请求与多响应的划分

        当通过相同连接发送多个请求时,我们需要划分出不同的请求,同时,客户端也需要划分开不同的响应。针对此问题,我们一般有两种选择:

    1、在请求信息的开始部分标明信息的字节长度

    2、在请求内容后添加结束标识

        HTTP使用的是第一种,在请求头中通过“Content-Length”标识请求数据的字节长度。它标识了请求头后有多少字节属于这个请求。这种方式相较第二种优点是减少结束符处理开销的同时,也不需要对原始信息中可能存在的与结束符相同的字符进行转义操作。缺点就是,我们在数据发送之前必须知道数据的长度,如果数据是动态生成的,我们需要缓存整个请求数据,在获取数据长度之后才能执行发送操作。

        使用结束符是,我们不必要知道我们发送的数据有多长,我们只需要在待发送数据的尾部加上结束符,但是我们需要对数据体中可能混淆结束符的字符进行转义。

    3、防火墙穿透

        大多数防火墙会阻止HTTP以外的协议通信,所以我们构建网络通信协议时基于HTTP组建新协议是一个比较好的办法。我们需要在HTTP请求及响应信息的内部来构建我们的协议。我们构建的协议形式可以是文本,可以是xml,也可以是二进制。但因为HTTP的特殊性,我们在组建某些协议时会有一定的额外开销。

    展开全文
  • 1.ajax发送请求,红色部分为自定义添加的请求头信息//上传视频文件  function uploadfile(el) {  &lt;@shiro.user&gt;  var userId = &lt;@shiro.principal property = "id"/&gt;  &...
  • java客户端数据发送服务器(POST请求)总结

    万次阅读 多人点赞 2015-01-08 16:33:21
    java客户端数据发送服务器(POST请求)总结 1.如果不设置Content-type,默认是:application/x-www-form-urlencoded。 2.GET请求的参数与对应的值位于请求行中,并附加在URL后面,通过“?”分隔开来。 POST请求的...
  • 如何在java中发起http和https请求

    万次阅读 多人点赞 2017-01-03 15:47:02
    一般调用外部接口会需要用到http和https请求。 一.发起http请求 1.写http请求方法 //处理http请求 requestUrl为请求地址 requestMethod请求方式,值为"GET"或"POST" public static String httpRequest(String ...
  • 终于是搞定了UEditor自定义上传... 上班的时间写这个,不知道会不会被骂死... 现在公司正在做的一个项目,需要用到HTML编辑器,在UEditor之前,使用的是Ckeditor+Ckfinder。 CK这个编辑器和UEditor一样,都是首次...
  • 前提:通过HttpClient实现. 方式一:以form表单形式提交数据 jar包: commons-logging-1.1.1.jar ...客户端(此时的后台)如何发送请求: 导入: import java.util.ArrayList; import java.util.HashMap; i...
  • 在正式给大家介绍自定义协议之前,我们先对网络传输和协议解析的相关知识点做一个基本的介绍,尽管这些知识点我们在学校里学过,但难免会有所遗忘,这里先做一个简单的介绍,以便对后文的内容理解更加顺畅。...
  • 404界面(可自定义模板) sws文件(简单的进行重定向) 学习前需要的知识 整理思路 项目目录结构 使用的 jar(shendi-kit-1.0.jar) 编写启动类 StartWebServer Server抽象类(所有服务器类的父类) 实现TCP服务器...
  • java实现调用http请求的几种常见方式

    万次阅读 多人点赞 2019-05-25 02:23:36
    一、概述 在实际开发过程中,我们经常需要调用对方提供的...在Java项目中调用第三方接口的方式有: 1、通过JDK网络类Java.net.HttpURLConnection; 2、通过common封装好的HttpClient; 3、通过Apache封装好的Clos...
  • 文章目录1.http请求过程1.1.准备工作1.2.http请求流程示意图1.3三/四次握手1.3.1.Seq序号/确认号Ack/标志位Flags1.3.2.三次握手流程1.3.3.四次挥手流程2.使用wireshark对http请求进行抓包分析2.1.准备工作2.2....
  • 使用自定义批注将浏览器请求路由到特定处理程序方法的小型Web服务器 描述 您的任务是创建一个微型网络服务器,该服务器使用批注将浏览器请求路由到特定的处理程序方法,这基本上是路由机制的一个简单版本。 使用...
  • Java实现拦截HTTP请求的几种方式

    千次阅读 2020-03-25 12:06:46
    Java的服务端开发当中,拦截器是很常见...一:实现javax.servlet.Filter接口(使用过滤器方式拦截请求) import org.springframework.stereotype.Component; import javax.servlet.*; import java.io.IOExceptio...
  • java 自定义状态码

    千次阅读 2018-08-13 12:28:03
    说明用中文而已,对应...org.springframework.http.HttpStatus 参考 https://blog.csdn.net/razeSpirit/article/details/78030947 的状态码定义 /** * PRODUCT_NAME: IntelliJ IDEA * PROJECT_NAME: z...
  • 前后端分离项目,后端为JAVA自定义请求头header MY_TOKEN做鉴权,开发环境前端请求接口,运行正常。 部署至服务器,使用nginx做了代理,进行转发。此时奇怪的事情发生了,服务端取不到 自定义headerMY_TOKEN 的...
  • JavaHttp请求(一)post

    万次阅读 2019-05-13 18:20:40
    导包: <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.6</version> ...
  • http://blog.csdn.net/qianlong2hao/article/details/50175939...1、写一个HttpRequestUtils工具类,包括post请求和get请求 ? 1 2 3 4 5 6 7 8 9 10
  • Java序列化之自定义序列化

    千次阅读 2016-06-06 09:05:48
    背景 进行序列化传输时,有时不仅需要对象本身的数据,还需要传输一些额外的辅助信息,以保证信息的安全、完整和正确。为了做到这点需求,Java提供了一套有效的机制,允许在序列化和反...两个接口 Java为程序员自定义
  • JAVA HTTPclient头中增加自定义的属性

    千次阅读 2016-07-10 14:45:27
    原文:http://blog.csdn.net/z69183787/article/details/25372971 场景是这样的,第三方页面访问...我试过用response.addHeader("Authorization","xxxxxxxxx")方法,但发送请求还是不带Authorization属性,还请大
  • 线上项目一旦报错,将报错信息通过http请求发送到自己部署开发环境服务器项目中 将处理一下http请求信息存起来,就是一个小型的异常数据库, 当然也实现了开发环境查库然后界面化,这个就是一个后台系统展现就不说了 ...
  • 当您的应用程序是无服务器的并且您想通过http post请求发送一些数据时,这很有用,并且在保存到数据库之前,您需要处理数据或使用它来获取其他结果然后保存。 AWS Lambda函数扮演着处理通过API网关接收的数据的角色...
  • 自我总结 初次尝试微信公众号开发,遇到各种问题。废话不多说,上码: 1、创建自定义菜单  根据微信接口文档,内容如下图:对应链接 要创建自定义菜单要获取ACCESS_TOKEN,根据微信接口...import java.io.IOExcep
  • id=mp1421141013中自定义菜单创建接口,和自己的功能需求对比,确定后方能下一步。第二步:确保自己的公众号已开通自定义菜单功能,第三步:创建自定义菜单:url:...
  • HTTP 服务器使用自定义端口(例如 8080)为客户端提供服务,当客户端请求服务器连接时,服务器则接受客户端的连接并等待 HTTP 请求头 我只针对客户端中的 GET 和 PUT 请求,因此该程序可以分别从服务器获取 html ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 178,473
精华内容 71,389
关键字:

java服务器发送自定义http请求

java 订阅