ПРИМЕЧАНИЕ. Пожалуйста, игнорируйте мое использование <i>MultivaluedMap</i>
вместо нескольких vargs String ... args .
Есть ли в Java стандартный способ сделать это?
То, что у меня есть, это ресурс, который возвращается с удаленного сервера. Но перед каждым запросом удаленное соединение должно быть открыто, а после возврата возвращено - оно должно быть закрыто.
Итак, естественный способ сделать это что-то вроде:
Connection c = config.configureConnection();
c.open(); //open
List<Car> cars;
try{
cars = c.getCars();
}finally{
c.close(); //close
}
Теперь я хочу реализовать что-то, что работает на уровне самих ресурсов, не беспокоясь о соединении, например:
List<Car> cars = new CarResource().all(); //opens and closes connection
То, как я сейчас это делаю, - это использование одного абстрактного класса AbstractQueriable вызов абстрактных методов query (String ... args) и query (int id) , который должен реализовывать любой класс, расширяющий его.
AbstractQuerieable реализует интерфейс Queriable , благодаря которому он предоставляет три открытых метода filter (String ... args) , all () и get (int id) - это общедоступные методы.
Вот интерфейс Queriable:
public interface Queriable <T>{
public T get(String id);
/** Simply returns all resources */
public Collection<T> all();
public Collection<T> filter(MultivaluedMap<String, String> args);
}
вот класс AbstractQueriable, который его реализует:
public abstract class AbstractQueriable<T> implements Queriable<T> {
@Override
public final T get(String id) {
setup();
try {
return query(id);
} finally {
cleanup();
}
}
@Override
public final Collection<T> filter(MultivaluedMap<String, String> args) {
setup();
try {
return query(args);
} finally {
cleanup();
}
}
/**
* Returns all resources.
*
* This is a convenience method that is equivalent to passing an empty
* arguments list to the filter function.
*
* @return The collection of all resources if possible
*/
@Override
public final Collection<T> all() {
return filter(null);
}
/**
* Queries for a resource by id.
*
* @param id
* id of the resource to return
* @return
*/
protected abstract T query(String id);
/**
* Queries for a resource by given arguments.
*
* @param args
* Map of arguments, where each key is the argument name, and the
* corresponing values are the values
* @return The collection of resources found
*/
protected abstract Collection<T> query(MultivaluedMap<String, String> args);
private void cleanup() {
Repository.close();
}
private void setup() {
Repository.open();
}
и, наконец, мой ресурс, который я хочу использовать в коде, должен, например, расширить класс AbstractQueriable (обратите внимание, что детали этих методов не важны):
public class CarRepositoryResource extends AbstractQueriable<Car> {
@Override
protected Car query(String id) {
MultivaluedMap<String, String> params = new MultivaluedMapImpl();
params.add("CarID", id);
// Delegate the query to the parametarized version
Collection<cars> cars = query(params);
if (cars == null || cars.size() == 0) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
if (cars.size() > 1) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return cars.iterator().next();
}
@Override
protected Collection<Car> query(MultivaluedMap<String, String> params) {
Collection<Car> cars = new ArrayList<Car>();
Response response = Repository.getConnection().doQuery("Car");
while (response.next()) {
Returned returned = response.getResult();
if (returned != null) {
cars.add(returned);
}
}
return cars;
}
}
который, наконец, я могу использовать в своем коде:
Collection<Car> cars = new CarRepositoryResource().all();
//... display cars to the client etc...
Есть несколько вещей, которые мне не нравятся в такой настройке:
- Я должен создавать новый экземпляр моего "CarRepositoryResource" каждый раз, когда я делаю запрос.
- Имена методов "query", хотя и внутренние и частные, все еще сбивают с толку и неуклюжи.
- Я не уверен, есть ли лучший образец или структура там.
Используемое мной соединение не поддерживает / не реализует API JDBC и не основано на sql.