Я прочитал в «Эффективной Java», что вы не должны использовать ограниченные подстановочные знаки в качестве возвращаемых типов, но я не знаю, как это сделать тогда. Единственный способ компиляции кода - использовать RequestCloner<? extends HttpUriRequest>
в качестве возвращаемого типа в статической фабрике. Я что-то делаю неправильно или есть обходной путь?Ограниченный шаблон в обратном типе статического заводского шаблона
Примечание: Одна вещь, которую следует отметить, что HttpUriRequest
имеет метод setHeader
, но только HttpPost
имеет метод setEntity
.
abstract class RequestCloner<T extends HttpUriRequest> {
protected T clonedRequest;
private enum RequestType {
GET, POST, DELETE
}
static RequestCloner<? extends HttpUriRequest> newInstance(
String type, String url) {
RequestType requestType = RequestType.valueOf(type);
switch (requestType) {
case GET:
return new GetRequestCloner(url);
case POST:
return new PostRequestCloner(url);
case DELETE:
return new DeleteRequestCloner(url);
default:
throw new IllegalArgumentException(String.format(
"Method '%s' not supported",
type));
}
}
public abstract HttpUriRequest clone(HttpServletRequest servletRequest) throws IOException;
protected void cloneHeaders(HttpServletRequest servletRequest) {
@SuppressWarnings("unchecked")
Enumeration<String> e = servletRequest.getHeaderNames();
while (e.hasMoreElements()) {
String header = e.nextElement();
if (!header.equalsIgnoreCase("Content-Length")
&& !header.equalsIgnoreCase("Authorization")
&& !header.equalsIgnoreCase("Host")) {
clonedRequest.setHeader(new BasicHeader(header, servletRequest.getHeader(header)));
}
}
}
}
...
class GetRequestCloner extends RequestCloner<HttpGet> {
GetRequestCloner(String url) {
this.clonedRequest = new HttpGet(url);
}
@Override
public HttpUriRequest clone(HttpServletRequest servletRequest) {
cloneHeaders(servletRequest);
return clonedRequest;
}
}
...
class PostRequestCloner extends RequestCloner<HttpPost> {
private static final int MAX_STR_LEN = 1024;
PostRequestCloner(String url) {
this.clonedRequest = new HttpPost(url);
}
@Override
public HttpUriRequest clone(HttpServletRequest servletRequest) throws IOException {
cloneHeaders(servletRequest);
cloneBody(servletRequest);
return clonedRequest;
}
private void cloneBody(HttpServletRequest servletRequest) throws IOException {
StringBuilder sb = new StringBuilder("");
BufferedReader br = new BufferedReader(new InputStreamReader(
servletRequest.getInputStream(),
"UTF-8"));
String line = "";
while ((line = br.readLine()) != null && sb.length() < MAX_STR_LEN) {
sb.append(line);
}
br.close();
clonedRequest.setEntity(new StringEntity(sb.toString(), "UTF-8"));
}
}
...
class DeleteRequestCloner extends RequestCloner<HttpDelete> {
DeleteRequestCloner(String url) {
this.clonedRequest = new HttpDelete(url);
}
@Override
public HttpUriRequest clone(HttpServletRequest servletRequest) {
cloneHeaders(servletRequest);
return clonedRequest;
}
}
Как 'clonedRequest' используется в' RequestCloner'? Из кода не ясно, почему 'RequestCloner' должен быть общим – NamshubWriter
@NamshubWriter. Я добавил остальную часть кода. Я клонирую «HttpServletRequest» в Apache httpclient library, и каждый тип запроса имеет свой собственный класс. – carcaret