1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/dreampie-Resty

Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Resty — простой RESTful веб-фреймворк

Обновление


  • feature/20170203 Улучшение Stringer-инструмента и поддержка цветного вывода логов для удобства отладки @t-baby

Присоединиться к чату на https://gitter.im/Dreampie/Resty Статистика задач Статистика задач Руководство по разработке

Если вы ещё недостаточно знакомы с RESTful или считаете, что это просто стандарт без практического применения, рекомендую статью с сайта OSC, опубликованную два года назад: Лучшие практики проектирования RESTful API и очень теоретическую статью на сайте InfoQ: Понимание истинной природы архитектурного стиля REST. Несмотря на то, что они немного устарели и содержат простое описание, можно использовать их как базовое понимание. Больше преимуществ RESTful можно найти на Google.

Имеет такую же простую активную модель данных, как jfinal/activejdbc, использует более простой RESTful фреймворк.Проектирование RESTful API является лучшим выбором для серверной части RESTful сервиса (используется для разделения клиента и сервера, предоставляет API для статических HTML-клиентов (MVVM и т.д.), iOS, Android и других).Руководство по Java-разработке: Java стиль

Руководство по проектированию HTTP-API: HTTP API дизайн

Примеры Resty: resty-samples (только API) resty-demo (с интерфейсом)

Если вы рассматриваете вариант разделения front-end и back-end, рекомендую использовать resty + vuejs, https://github.com/Dreampie/vuejs2-demo

Группа разработчиков: Простой RESTful фреймворк - Resty

Полезные плагины от других разработчиков:

Если вас интересует участие в совместной работе над этим проектом, свяжитесь со мной.

Нормы работы:
Перед началом работы следует указать функционал. Создайте новую ветку с названием feature/дата для новых функций и fix/дата для исправлений. В разделе README добавьте список задач TODO. Пример:

  • feature/20161228 задача списка завершена @Dreampie
  • feature/20161229 задача списка ещё не выполнена @Dreampie

Обратите внимание на два пробела отступа при оформлении кода. После этого все участники должны проверить код друг за другом, а затем объединить его с основной веткой master.Инструкция по использованию Maven:

  1. Добавьте зависимость:

    <dependency>
        <groupId>cn.dreampie</groupId>
        <artifactId>resty-route</artifactId>
        <version>1.3.1.SNAPSHOT</version>
    </dependency>
  2. Если вы используете пакет с суффиксом SNAPSHOT, добавьте следующий репозиторий:

    <repositories>
        <repository>
            <id>oss-snapshots</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

Основные преимущества:

Главные обновления:* 1.3.0 версия: использование Jetty как встроенного механизма горячей перезагрузки (перезагружается после компиляции Java файла), функция resty-captcha для генерации CAPTCHA...

  • 1.2.0 версия: управление версией API через заголовки, чтение и запись данных с разделением источников, более простое управление таблицами. Подробнее здесь
  • 1.1.0 версия: быстрый доступ к Spring, кэшированию, шифрованию, заголовкам, XForwardedSupports и многому другому. Подробнее здесь

Запись (record)的时代已经到来,您可以完全使用它来处理数据而无需创建模型。

// Создание исполнителя записи для таблицы sec_user и включение кэширования
Record recordDAO = new Record("sec_user");
// Используя текущий источник данных и данные таблицы создаем объект для хранения данных
recordDAO.reNew().set("атрибут", "значение").save();
Record r1 = recordDAO.reNew().set("атрибут", "значение");
Record r2 = recordDAO.reNew().set("атрибут", "значение");
// Сохранение в батче
recordDAO.save(r1, r2);
// Обновление
r2.set("атрибут", "значение").update();
// Получение всех записей
List<Record> записи = recordDAO.findAll();
// Условный поиск
recordDAO.findBy(where, paras);
// Поиск с пагинацией
Page<Record> записи = recordDAO.paginateAll();
// Удаление по id
recordDAO.deleteById("1");

// В данном запросе отключаем использование кэша recordDAO.unCache().findBy(where, paras); // Устанавливаем источник данных record в dsmName recordDAO.useDS(dsmName).findBy(where, paras);


```java
// Поддержка динамического переключения источников данных и отключения кэширования для текущего запроса
User dao = new User();
// Отключение использования кэша для данного запроса
dao.unCache().findBy(where, paras);
// Установка источника данных model в dsmName
dao.useDS(dsmName).findBy(where, paras);

// Настройки базы данных и глобальные параметры перемещены в application.properties, подробнее см. resty-example

# Автоматическая загрузка не обязательна
app.encoding=UTF-8
app.devEnable=true
app.showRoute=false
app.cacheEnabled=true
# По умолчанию используется ehcacheProvider
# app.cacheProvider=cn.dreampie.cache.redis.RedisProvider

## Конфигурация плагина druid для автоматической загрузки
db.default.url=jdbc:mysql://127.0.0.1/example?useUnicode=true&characterEncoding=UTF-8
db.default.user=dev
db.default.password=dev1010
db.default.dialect=mysql

#c3p0 конфигурация
c3p0.default.minPoolSize=3
c3p0.default.maxPoolSize=20

# Конфигурация druid
# druid.default.initialSize=10
# druid.default.maxPoolPreparedStatementPerConnectionSize=20
# druid.default.timeBetweenConnectErrorMillis=1000
# druid.default.filters=slf4j,stat,wall

# Конфигурация flyway для автоматической миграции базы данных
flyway.default.validClean=true
flyway.default.migrationAuto=true
flyway.default.migrationInitOnMigrate=true

db.demo.url=jdbc:mysql://127.0.0.1/demo?useUnicode=true&characterEncoding=UTF-8
db.demo.user=dev
db.demo.password=dev1010
db.demo.dialect=mysql
# Конфигурация druid
druid.demo.initialSize=10
druid.demo.maxPoolPreparedStatementPerConnectionSize=20
druid.demo.timeBetweenConnectErrorMillis=1000
druid.demo.filters=slf4j,stat,wall
# Конфигурация flyway
flyway.demo.validClean=true
flyway.demo.migrationAuto=true
flyway.demo.migrationInitOnMigrate=true
``````java
// Минимальная конфигурация базы данных, автоматически читающая параметры из файла, требуется только указание директории сканирования моделей и имени источника данных
public void configPlugin(PluginLoader pluginLoader) {
    // Первый источник данных
    ActiveRecordPlugin activeRecordPlugin = new ActiveRecordPlugin(new DruidDataSourceProvider("default"), true);
    activeRecordPlugin.addIncludePaths("cn.dreampie.resource");
    pluginLoader.add(activeRecordPlugin);
}
  1. Минималистичный дизайн маршрутов, полностью интегрированный с обычными методами, где параметры метода являются параметрами запроса, а возвращаемое значение — ответом.```java @GET("/пользователи/:имя") //Параметры в пути можно указывать как /пользователи/:имя, так и /пользователи/{имя}. //Имя параметра совпадает с именем метода. Дополнительные параметры также могут передаваться через метод, например user={json_string}. public Map найти(String имя, User user) { // return Lister.of(имя); return Maper.of("k1", "v1,имя:" + имя, "k2", "v2"); //Чтобы вернуть данные, просто используйте return }

2. Минимальный дизайн активной записи данных, операции с данными требуют всего одной строки кода, поддерживаются массовые сохранения объектов.

```java
  //Массовое сохранение
  User u1 = new User().set("username", "тест").set("providername", "тест").set("password", "123456");
  User u2 = new User().set("username", "тест").set("providername", "тест").set("password", "123456");
  User.dao.save(u1, u2);

  //Обычное сохранение
  User u = new User().set("username", "тест").set("providername", "тест").set("password", "123456");
  u.save();
```  // Обновление
  u.update();
  // Условное обновление
  User.dao.updateBy(columns, where, paras);
  User.dao.updateAll(columns, paras);

  // Удаление
  u.deleted();
  // Условное удаление
  User.dao.deleteBy(where, paras);
  User.dao.deleteAll();

  // Поиск
  User.dao.findById(id);
  User.dao.findBy(where, paras);
  User.dao.findAll();

  // Пагинация
  User.dao.paginateBy(pageNumber, pageSize, where, paras);
  User.dao.paginateAll(pageNumber, pageSize);

```java
  Client httpClient = null; // Создание объекта клиента
  // Запустите проект resty-example, чтобы протестировать клиента
  String apiUrl = "http://localhost:8081/api/v1.0";
  // Если учетная запись не требуется, то ее можно пропустить
  // httpClient = new Client(apiUrl);
  // Если есть ограничения по правам доступа, то потребуется авторизация
  httpClient = new Client(apiUrl, "/tests/login", "u", "123");

  // Этот запрос должен быть выполнен после авторизации, иначе будет возвращён код ошибки 401 (неавторизован)
  ClientRequest authRequest = new ClientRequest("/пользователи");
  ClientResult authResult = httpClient.build(authRequest).get();
  System.out.println(authResult.getResult());

  // GET
  ClientRequest getRequest = new ClientRequest("/tests");
  ClientResult getResult = httpClient.build(getRequest).get();
  System.out.println(getResult.getResult());

  // POST
  ClientRequest postRequest = new ClientRequest("/tests");
  postRequest.addParam("test", Jsoner.toJSONString(Maper.of("a", "谔谔")));
  ClientResult postResult = httpClient.build(postRequest).post();
  System.out.println(postResult.getResult());

  // PUT
  ClientRequest putRequest = new ClientRequest("/тесты/х");
  ClientResult putResult = httpClient.build(putRequest).put();
  System.out.println(putResult.getResult());
``````markdown
//удаление
ClientRequest deleteRequest = new ClientRequest("/тесты/а");
ClientResult deleteResult = httpClient.build(deleteRequest).delete();
System.out.println(deleteResult.getResult());

//загрузка
ClientRequest uploadRequest = new ClientRequest("/тесты/resty");
uploadRequest.addUploadFiles("resty", ClientTest.class.getResource("/resty.jar").getFile());
uploadRequest.addParam("описание", "тестовый файл параметры  测试笔");
ClientResult uploadResult = httpClient.build(uploadRequest).post();
System.out.println(uploadResult.getResult());

//скачивание Поддерживает прерывистую загрузку
ClientRequest downloadRequest = new ClientRequest("/тесты/файл");
downloadRequest.setDownloadFile(ClientTest.class.getResource("/resty.jar").getFile().replace(".jar", "x.jar"));
ClientResult downloadResult = httpClient.build(downloadRequest).get();
System.out.println(downloadResult.getResult());


4.Поддержка нескольких источников данных и вложенных транзакций (в случае использования: при необходимости доступа к нескольким базам данных, или как внутренний компонент данных компании для предоставления клиентам API доступа к данным)
   // В ресурсе используется транзакция, то есть в контроллере, в мире REST все запросы считаются ресурсами, поэтому здесь это называется ресурсом
   @GET("/пользователи")
   @Transaction(name = {"по умолчанию", "демо"}) // Транзакция с несколькими источниками данных, если у вас всего один источник данных, используйте просто @Transaction без параметров
   public User transaction() {
     // TODO Используйте модель для выполнения операций с базой данных, любое возникшее исключение приведёт к откату обоих источников данных, хотя это не распределённая транзакция, она обеспечивает безопасность выполнения блока кода
   }

<! -- Если вам требуется реализовать транзакцию в сервисе с помощью динамического прокси Java (обязательно использовать интерфейсы, так проектировалось JDK) -->

public interface UserService {
    @Transaction(name = {"demo"}) // Чтобы добавить транзакцию с несколькими источниками данных в сервисе, если используется только один базовый источник данных, используйте просто @Transaction без параметров
    public User save(User u);
}

<! -- В ресурсах используйте транзакцию уровня сервиса --> <! -- Аннотация @Transaction(name = {"demo"}) должна быть указана на интерфейсе сервиса --> <! -- Обратите внимание, что автоматическое проксирование Java требует наличия интерфейса --> <! -- TransactionAspect — это аспект транзакции, вы также можете реализовать свои аспекты, такие как аспект логирования, реализуя интерфейс Aspect --> <! -->-- Например, private UserService userService = AspectFactory.newInstance(new UserServiceImpl(), new TransactionAspect(), new LogAspect()); -->

private UserService userService = AspectFactory.newInstance(new UserServiceImpl(), new TransactionAspect(), new LogAspect());
  1. Минимальная реализация прав доступа позволяет использовать кэш для поддержки распределённых сессий. Вам нужно реализовать простой интерфейс и добавить один перехватчик, чтобы обеспечить управление правами доступа на основе URL.```java public void configInterceptor(InterceptorLoader interceptorLoader) { // Interceptor for access rights that should come first to immediately check access rights and avoid executing unnecessary code interceptorLoader.add(new SecurityInterceptor(new MyAuthenticateService())); }

// Implementation of the interface public class MyAuthenticateService implements AuthenticateService { // Upon entering the system via a username, we retrieve their password and access rights information public Principal findByName(String name) { DefaultPasswordService defaultPasswordService = new DefaultPasswordService();

    Principal principal = new Principal(name, defaultPasswordService.hash("123"), new HashSet<String>() {{
        add("api");
    }});
    return principal;
}

// Main list of all access rights where all URL permissions are stored. You can configure these permissions through a configuration file, database or directly in the code.
public Set<Credential> loadAllCredentials() {
    Set<Credential> credentials = new HashSet<Credential>();
    credentials.add(new Credential("GET", "/api/v1.0/users**", "users"));
    return credentials;
}

}


6. Minimal caching implementation that easily scales and automatically activates model caching.

```java
// Activate caching and apply it to the model you want to cache
//@Table(name = "sec_user", cached = true)
@Table(name = "sec_user", cached = true)
public class User extends Model<User> {
    public static User dao = new User();
}
  1. To download a file, simply return an object of type File.
@GET("/files")
public File file() {
    return new File(path);
}
```8. Для загрузки файла используется аннотация для указания директории назначения.

```java
@POST("/files")
@FILE(dir = "/upload/") // Настройка информации о загружаемых файлах
public UploadedFile file(UploadedFile file) {
    return file;
}
  1. Поддерживается также традиционное веб-развитие, которое позволяет самостоятельно реализовывать парсеры данных и добавлять свои шаблоны отображения в конфигурацию.
public void configConstant(ConstantLoader constantLoader) {
    // Возврат различных типов данных на основе расширения файла. Можно добавить свои собственные Render, такие как FreemarkerRender.
    // По умолчанию уже добавлены json и text. Добавьте свои собственные Render для использования.
    // constantLoader.addRender("json", new JsonRender());
}

Запуск примера example:


  1. Создайте базы данных demo и example в локальной базе данных MySQL, соответствующие конфигурациям базы данных в application.properties.

  2. Запустите pom.xml в папке resty-example -> flyway-maven-plugin:migrate, чтобы автоматически создать структуру таблиц на основе файлов базы данных в директории resources/db.

  3. Запустите pom.xml в папке resty-example -> tomcat6-maven-plugin:run, чтобы запустить программу example.

Примечание: рекомендуется использовать IntelliJ IDEA как среду разработки для модульной разработки с несколькими модулями.

Лицензия: Apache License V2

Донат: Али-pay

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

сэмпл рестфул фреймворк Развернуть Свернуть
Apache-2.0
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/dreampie-Resty.git
git@api.gitlife.ru:oschina-mirror/dreampie-Resty.git
oschina-mirror
dreampie-Resty
dreampie-Resty
master