Sometimes we have to do access to URL resource or in particular invoke some servlet (via HTTP protocol). There is some different approaches to invocation via HTTP protocol: through GET or through POST. GET request is pretty simple to realize. Just put next code:
String url = http://localhost/AppWeb/myServlet?param1=val1¶m2=val2";
URLConnection uc = new URL(url).openConnection();
uc.setDoOutput(true);
uc.setDoInput(true);
//TO DO #1 some code put here to sign request as POST
InputStream istr = uc.getInputStream();
//TO DO #2 something do with respond (istr)
Differences (rather similarities) between URLConnection and HttpURLConnection can be shown in next lines:
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
if (connection instanceof HttpURLConnection) {
HttpURLConnection httpConnection = (HttpURLConnection)connection;
}
Servlet (myServlet) will accept request from first source as GET method. In "TO DO #2" just do something with servlet's respond. In case of HttpURLConnection it is possible to retrieve response code and message: httpConnection.getResponseCode(); or httpConnection.getResponseMessage() .
It is possible to put next code instead "TO DO #1" to convert that request into POST request:
BufferedWriter wr = new BufferedWriter(new PrintWriter(uc.getOutputStream()));
wr.write("param3=val3&"); //PAY ATTENTION. SYMBOL > & < param4="val4">
Just we fulfil some writing into body of our connection, connection become POST request. There are some difficulties with file adding to POST request from java application and treatment those files in servlets. Firstly, for simple html form posting with file fild, form has to be multipart/form-data (enctype) and there is method setRequestProperty(key, value) in our URLConnection to set these property in java code like by html tags:
<form enctype="multipart/form-data" action="DownWithAPI" method="POST">
<input type="file" name="filetoupload" />
<input type="submit" value="Go" />
</form>
Secondly we need not write some parameters manualy. Instead we can use some simple API (one java file): ClientHttpRequest 1.4 or ClientHttpRequest 1.0. Using is pretty simple too:
String url = http://localhost/AppWeb/myServlet?param1=val1¶m2=val2";
ClientHttpRequest client = new ClientHttpRequest(url);
client.setParameter("file", new File("d:/dome.txt"));
client.setParameter("param5", "value5");
client.post().read();
Now look into more difficult part of work - treatment our request on server side (in servlet). Pay attention that servlet deals with post request in doPost method. Transmitted parameters in both case can be retrieved via HttpServletRequest parameter (in doGet or doPost) in manner:
String dataFromClient = request.getParameter("param1");
But in case of multipart/form-data that approach is not useful. Instead we need to parse request.getInputStream() as multipart container. To do this I suggest to use API again: form-data Reader in manner:
Map map = MultipartFormReader.read(request);
String value1= map.get("SomeParamName1").toString();
byte[] file =((DataSource) map.get("fileParam1")).getBinaryContent();
String value2 = map.get("SomeParamName1").toString();
All keys can be retrieved via:
Map map = MultipartFormReader.read(request);
Iterator it = map.keySet().iterator();
while(it.hasNext()){
System.out.println(it.next().toString());
}
And also I will talk about downloading with servlet functionality. Method below can clarify this situation:
private void doDownload(HttpServletRequest req, HttpServletResponse resp, String original_filename, InputStream istr){
ServletOutputStream op = resp.getOutputStream();
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition", "attachment; filename=\"" + original_filename + "\"");
byte[] b = new byte[8164];
int len = 0;
int fullLen = 0;
while ((len = istr.read(b, 0, 8164)) != -1){
op.write(b, 0, len);
fullLen = fullLen + len;
}
resp.setContentLength(fullLen);
istr.close();
op.flush();
op.close();
}
Just put him some InputStream (from file for example or byte array stream). After and before invoking of that method do not invoke any response.getWriter().write(""); because it will be Exception throwing.
There are some interesting issue in working with java.net.URLConnection or
HttpURLConnection. For example it is posible to set some usefull properties:
String url = http://localhost:8080/MyJavaServer_web/Down;
HttpURLConnection hconn = (HttpURLConnection) new URL(url).openConnection();
hconn.setDoInput(true);
hconn.setDoOutput(true);
hconn.setRequestMethod("POST");
hconn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461)");
conn.setRequestProperty("Accept", "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
conn.setRequestProperty("Accept-Language","de-de,de;q=0.8,en-us;q=0.5,en;q=0.3");
conn.setRequestProperty( "Accept-Encoding","gzip,deflate");
conn.setRequestProperty( "Accept-Charset","ISO-8859-1,utf-8;q=0.7,*;q=0.7");
conn.setRequestProperty( "Keep-Alive","300");
conn.setRequestProperty( "Proxy-Connection","keep-alive");
conn.setRequestProperty( "Cache-Control","max-age=0");
conn.setConnectTimeout(5000);
wr.flush();
After flushing servlet Down will accept POST request from .. Mozilla.
There is also posibility to set up cookie in the reques:
String cookie = null;
hconn.setRequestProperty("Cookie", cookie);
As you can see "Cookie" in transmitted while web request as plain string. Those string can be retrieved after first request to the server in code:
cookie = hconn.getHeaderField("Set-Cookie");
Pay attention that if server accepts request with "Cookie" property it will not fulfil "Set-Cookie" in response and hconn.getHeaderField("Set-Cookie") will be null.
For using proxy put next code before invoking openConnection() for URL:
Properties systemProperties = System.getProperties();
systemProperties.setProperty("http.proxyHost",proxy);
systemProperties.setProperty("http.proxyPort",port); //And optionally:
System.setProperty("http.proxyUser", "");
System.setProperty("http.proxyPassword", "");
And finally for authentication create simple class:
public class SimpleAuthenticator extends Authenticator{
private String username;
private String password;
public SimpleAuthenticator(String username,String password) {
this.username = username;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication( username,password.toCharArray());
}
}
And before creating new URL (URL myUrl= new URL(url);) invoke:
Authenticator.setDefault(new SimpleAuthenticator(username, password));
The end.
String url = http://localhost/AppWeb/myServlet?param1=val1¶m2=val2";
URLConnection uc = new URL(url).openConnection();
uc.setDoOutput(true);
uc.setDoInput(true);
//TO DO #1 some code put here to sign request as POST
InputStream istr = uc.getInputStream();
//TO DO #2 something do with respond (istr)
Differences (rather similarities) between URLConnection and HttpURLConnection can be shown in next lines:
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
if (connection instanceof HttpURLConnection) {
HttpURLConnection httpConnection = (HttpURLConnection)connection;
}
Servlet (myServlet) will accept request from first source as GET method. In "TO DO #2" just do something with servlet's respond. In case of HttpURLConnection it is possible to retrieve response code and message: httpConnection.getResponseCode(); or httpConnection.getResponseMessage() .
It is possible to put next code instead "TO DO #1" to convert that request into POST request:
BufferedWriter wr = new BufferedWriter(new PrintWriter(uc.getOutputStream()));
wr.write("param3=val3&"); //PAY ATTENTION. SYMBOL > & < param4="val4">
Just we fulfil some writing into body of our connection, connection become POST request. There are some difficulties with file adding to POST request from java application and treatment those files in servlets. Firstly, for simple html form posting with file fild, form has to be multipart/form-data (enctype) and there is method setRequestProperty(key, value) in our URLConnection to set these property in java code like by html tags:
<form enctype="multipart/form-data" action="DownWithAPI" method="POST">
<input type="file" name="filetoupload" />
<input type="submit" value="Go" />
</form>
Secondly we need not write some parameters manualy. Instead we can use some simple API (one java file): ClientHttpRequest 1.4 or ClientHttpRequest 1.0. Using is pretty simple too:
String url = http://localhost/AppWeb/myServlet?param1=val1¶m2=val2";
ClientHttpRequest client = new ClientHttpRequest(url);
client.setParameter("file", new File("d:/dome.txt"));
client.setParameter("param5", "value5");
client.post().read();
Now look into more difficult part of work - treatment our request on server side (in servlet). Pay attention that servlet deals with post request in doPost method. Transmitted parameters in both case can be retrieved via HttpServletRequest parameter (in doGet or doPost) in manner:
String dataFromClient = request.getParameter("param1");
But in case of multipart/form-data that approach is not useful. Instead we need to parse request.getInputStream() as multipart container. To do this I suggest to use API again: form-data Reader in manner:
Map map = MultipartFormReader.read(request);
String value1= map.get("SomeParamName1").toString();
byte[] file =((DataSource) map.get("fileParam1")).getBinaryContent();
String value2 = map.get("SomeParamName1").toString();
All keys can be retrieved via:
Map map = MultipartFormReader.read(request);
Iterator it = map.keySet().iterator();
while(it.hasNext()){
System.out.println(it.next().toString());
}
And also I will talk about downloading with servlet functionality. Method below can clarify this situation:
private void doDownload(HttpServletRequest req, HttpServletResponse resp, String original_filename, InputStream istr){
ServletOutputStream op = resp.getOutputStream();
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition", "attachment; filename=\"" + original_filename + "\"");
byte[] b = new byte[8164];
int len = 0;
int fullLen = 0;
while ((len = istr.read(b, 0, 8164)) != -1){
op.write(b, 0, len);
fullLen = fullLen + len;
}
resp.setContentLength(fullLen);
istr.close();
op.flush();
op.close();
}
Just put him some InputStream (from file for example or byte array stream). After and before invoking of that method do not invoke any response.getWriter().write("
There are some interesting issue in working with java.net.URLConnection or
HttpURLConnection. For example it is posible to set some usefull properties:
String url = http://localhost:8080/MyJavaServer_web/Down;
HttpURLConnection hconn = (HttpURLConnection) new URL(url).openConnection();
hconn.setDoInput(true);
hconn.setDoOutput(true);
hconn.setRequestMethod("POST");
hconn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Q312461)");
conn.setRequestProperty("Accept", "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
conn.setRequestProperty("Accept-Language","de-de,de;q=0.8,en-us;q=0.5,en;q=0.3");
conn.setRequestProperty( "Accept-Encoding","gzip,deflate");
conn.setRequestProperty( "Accept-Charset","ISO-8859-1,utf-8;q=0.7,*;q=0.7");
conn.setRequestProperty( "Keep-Alive","300");
conn.setRequestProperty( "Proxy-Connection","keep-alive");
conn.setRequestProperty( "Cache-Control","max-age=0");
conn.setConnectTimeout(5000);
wr.flush();
After flushing servlet Down will accept POST request from .. Mozilla.
There is also posibility to set up cookie in the reques:
String cookie = null;
hconn.setRequestProperty("Cookie", cookie);
As you can see "Cookie" in transmitted while web request as plain string. Those string can be retrieved after first request to the server in code:
cookie = hconn.getHeaderField("Set-Cookie");
Pay attention that if server accepts request with "Cookie" property it will not fulfil "Set-Cookie" in response and hconn.getHeaderField("Set-Cookie") will be null.
For using proxy put next code before invoking openConnection() for URL:
Properties systemProperties = System.getProperties();
systemProperties.setProperty("http.proxyHost",proxy);
systemProperties.setProperty("http.proxyPort",port); //And optionally:
System.setProperty("http.proxyUser", "");
System.setProperty("http.proxyPassword", "");
And finally for authentication create simple class:
public class SimpleAuthenticator extends Authenticator{
private String username;
private String password;
public SimpleAuthenticator(String username,String password) {
this.username = username;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication( username,password.toCharArray());
}
}
And before creating new URL (URL myUrl= new URL(url);) invoke:
Authenticator.setDefault(new SimpleAuthenticator(username, password));
The end.
No comments:
Post a Comment