Статьи

Объедините клиент JaxRS 2.0 Rest, Java FX 2, Spring MVC и Hibernate

Сегодня я хочу поделиться с вами примером приложения, которое работает в соответствии со стилями RESTful и включает технологии на стороне сервера и на стороне клиента. Перед тем, как показывать содержимое приложения, я хочу поговорить о серверных и клиентских технологиях в запущенном приложении.

Серверные

  • Spring MVC 3.1 (для серверного сервиса Restful)
  • Hibernate 4 (чтобы сделать данные постоянными с ORM)

Клиентские

  • Java FX 2 (для визуального интерфейса пользователя)
  • JaxRS 2 — Rest Client (для управления http-запросами к серверу Restful)

После внедрения технологий давайте приступим к работе на стороне сервера на первом этапе. Поскольку приложение на стороне сервера является приложением Maven, его можно запустить в любой желаемой среде IDE. Вы можете взглянуть на картинку ниже, чтобы познакомиться с компонентами внутри серверного приложения.

весна-MVC-отдых

1) Book.java

@Entity
@XmlRootElement
public class Book implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private Double price;

    public Book(){}

    public Book(String name, Double price) {
        this.name = name;
        this.price = price;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }


}

Объект сущности Book (определенный  @Entity ) — это классический объект Java, который будет сделан постоянным для базы данных, будет прочитан, отредактирован и удален. Согласно стандарту JAXB, если требуется преобразование из объекта Java в объект XML (противоположный также является допустимым Java  <>  XML), преобразованный класс должен быть обернут   аннотацией @XmlRootElement в ее самой простой форме.

2) BookWrapper.java

@XmlRootElement
public class BookWrapper implements Serializable {

    private List<Book> bookList;

    public List<Book> getBookList() {
        return bookList;
    }

    public void setBookList(List<Book> bookList) {
        this.bookList = bookList;
    }

    public BookWrapper(List<Book> bookList) {
        this.bookList = bookList;
    }

    public BookWrapper() {
    }
}

Класс BookWrapper действует как класс, охватывающий более одного объекта книги. Единственная цель этого — обеспечить легкое преобразование объектов типа интерфейса List в  формат XML  или  JSON  .

3) MvcInitializer.java

public class MvcInitializer implements WebApplicationInitializer {

    public void onStartup(ServletContext servletContext) throws ServletException {

        AnnotationConfigWebApplicationContext mvcContext= new AnnotationConfigWebApplicationContext();
        mvcContext.register(WebConfig.class);

        ServletRegistration.Dynamic register=
                servletContext.addServlet("distpatcher", new DispatcherServlet(mvcContext));
        register.addMapping("/*");
        register.setLoadOnStartup(1);

    }
}

Когда мы посмотрим на изображение, ориентированное на серверное приложение, вы увидите, что конфигуратор транспорта web.xml не включен в каталог проекта. Ну, как Spring MVC Context может работать без конфигуратора web.xml?

Ответ основан на стандарте Servlet 3.0. В стандарте Servlet 3.0 зависимость от транспортного конфигуратора web.xml полностью устранена.

Когда   контейнер Servlet 3.0 запускается впервые, если существует класс, реализующий интерфейс ServletContainerInitializer в CLASSPATH приложения, метод onStartup (..) этого класса запускается автоматически, и выполняются определения и аналогичные операции, такие как Servlet, Filter, Слушатель может быть выполнен с помощью этого метода, как это может быть сделано в web.xml.

Чтобы облегчить работу, выполненную в Spring Framework, интерфейс WebApplicationInitializer, который управляется классом SpringServletContainerInitializer, представлен нам с точки зрения конфигурации контейнера Spring.

Файлы конфигурации на основе XML, в которых объекты Spring определены, связаны друг с другом и настроены, больше не требуются в версии Spring Framework 3.1. Потому что теперь возможно сделать XML-конфигурацию Spring Context независимой от версии 3.1. На данный момент, я предпочитаю использовать этот метод, чтобы показать  независимую конфигурацию web.xml  и  spring-beans.xml (имя может отличаться).

Вкратце, вышеуказанная процедура включает в себя создание веб-контекста Spring и определение класса конфигурации контекста Spring, а именно WebConfig, и определение DispatcherServlet, который является неотъемлемой частью Spring MVC. Можно сказать, что этот класс является сопряженным с конфигуратором транспорта web.xml.

4) WebConfig.java

@Configuration // This is a Spring config class
@EnableTransactionManagement // As <tx:annotation-config />
@EnableWebMvc  // As <mvc:component-scan .. />
@ComponentScan(basePackages = "com.kodcu") // As <context:component-scan ../>
public class WebConfig extends WebMvcConfigurerAdapter {

    @Bean
    // Injectible Transaction Manager Bean
    public HibernateTransactionManager createTransactionManager(){

       HibernateTransactionManager transactionManager=new HibernateTransactionManager();
       transactionManager
        .setSessionFactory(createSessionFactoryBean().getObject());

        return transactionManager;

    }

    @Bean
    // Injectible Hibernate SessionFactory Bean
    public LocalSessionFactoryBean createSessionFactoryBean(){
        LocalSessionFactoryBean localSessionFactoryBean=new LocalSessionFactoryBean();
        Properties properties=new Properties();
        properties.setProperty("hibernate.dialect"
              ,"org.hibernate.dialect.MySQL5InnoDBDialect");
        properties.setProperty("hibernate.hbm2ddl.auto","create");
        properties.setProperty("hibernate.show_sql","true");
        localSessionFactoryBean.setHibernateProperties(properties);
        localSessionFactoryBean.setAnnotatedClasses(new Class<?>[]{Book.class});
        localSessionFactoryBean.setDataSource(createDataSource());
        return localSessionFactoryBean;
    }

    @Bean
    // Injectible DataSource Bean
    public BasicDataSource createDataSource(){
        BasicDataSource dataSource=new BasicDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/fxdb");
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        return dataSource;
    }
       
}

Сегодня существует тенденция к аннотационным операциям конфигурации, а не к XML-конфигураторам. На самом деле, нет ответа о том, какой метод лучше. Выбор зависит от оценки разработчика.

Если вы посмотрите на приведенный выше класс конфигурации WebConfig.java, то увидите, что этот класс является сопряженным с файлами конфигурации Spring на основе XML.

Проиллюстрировать:

Определение метода, который возвращает объект типа BasicDataSource вместо <bean id = ”..” class = ”com. Определение apache… .BasicDataSource ”>… </ bean> и применение аннотации @Bean к этому методу имеют ту же функцию.

5) PublisherController.java

@Transactional(readOnly = true)
@Repository  // Spring DAO
@Controller  // Spring MVC Controller
@RequestMapping(value = "/publisher/*")
public class PublisherController {

    @Autowired
    // SessionFactory injection
    private SessionFactory sessionFactory;

    // Gets current Session object
    public Session  getSession(){
        return sessionFactory.getCurrentSession();
    }

    @RequestMapping(value = "/book",
            method = RequestMethod.POST,
            produces = {MediaType.APPLICATION_JSON_VALUE,MediaType.APPLICATION_XML_VALUE },
            consumes = {MediaType.APPLICATION_JSON_VALUE,MediaType.APPLICATION_XML_VALUE })
    @Transactional(readOnly = false)
    public @ResponseBody Long saveBook(@RequestBody Book book) {

     return (Long)getSession().save(book);

    }

    @RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE)
    @Transactional(readOnly = false)
    public void removeBook(@PathVariable Long id) {

      getSession().delete(getSession().get(Book.class,id));

    }

    @RequestMapping(value = "/books",produces = {MediaType.APPLICATION_XML_VALUE},method = RequestMethod.GET)
    @ResponseStatus( HttpStatus.OK )
    public @ResponseBody
    BookWrapper allBooks() {

        List<Book> bookList= (List<Book>)getSession().createQuery("SELECT b FROM Book b").list();

      return new BookWrapper(bookList) ;

    }

    @RequestMapping(value = "/book",
            method = RequestMethod.PUT,
            consumes = {MediaType.APPLICATION_JSON_VALUE,MediaType.APPLICATION_XML_VALUE })
    @Transactional(readOnly = false)
    public void updateBook(@RequestBody Book book) {
        getSession().saveOrUpdate(book);
    }
}

Класс PublisherController — это DAO (объект доступа к данным), который назначается как класс @Controllerclass, в котором каждый метод поддерживает транзакции (посредством @Transactional), а также принадлежит Spring MVC.

 Аннотация @RequestMapping — это полезная аннотация Spring MVC, которая берет на себя сборку некоторых аннотаций, таких как @Path, @GET, @POST, @PUT, @ Produces, @ Consumes, расположенных в стандарте JAX-RS, а также эта аннотация направляет URL-адрес. -> Доступ к ресурсам.

Аннотации @RequestBody  и  @ResponseBody  позволяют выводить потоки данных, отправляемые в метод и выводить из метода, Spring MVC в качестве значимых данных, и эти аннотации также позволяют преобразовывать типы (такие как Java  <>  XML или Java  <>  JSON и т. Д. ) в фоновом режиме, если это необходимо.

 Аннотация @PathVariable сортирует переменные из компонентов URL, а затем передает это значение в переменную в параметре метода.

Такие операции, как создание базы данных постоянной, обновление, удаление и чтение, могут выполняться различными методами (например, saveOrUpdate, delete и т. Д.) Объекта Hibernate Session.

После объяснения общей архитектуры серверного приложения мы можем углубиться в детали компонентов на стороне клиента.

Доступ к веб-сервисам RESTful можно получить с помощью любого инструмента, управляющего запросами HTTP, языка программирования или программного обеспечения. Стандарт JAX-RS 1.1 позволяет писать веб-сервисы RESTful на языке программирования Java. Но в версии JAX-RS 1.1 нет никакого клиентского инструмента, который бы легко управлял HTTP-запросами. По этой причине в стандарте JAX-RS 2, который будет иметь место в Java EE 7, будет добавлена ​​новая библиотека, а именно клиент RESTful. Эта клиентская библиотека REST доступна и может использоваться с помощью текущих исследований.

Вы можете получить доступ к   справочной библиотеке реализации JAX-RS 2.0 с этого  http://repo1.maven.org/maven2/org/glassfish/jersey/bundles/jax-rs-ri/  адреса, а затем использовать ее.

Чтобы создать клиент RESTful с JAX-RS 2.0, клиентский объект можно получить с помощью Clientclient = ClientFactory.newClient (); вызов. Посредством этого объекта могут быть выполнены HTTP-запросы в соответствии со стилем RESTful, данные ( REST Entity ) могут быть отправлены по HTTP-запросу, информация, такая как заголовок HTTP, тело может быть получено из возвращенного ответа. Использование этой библиотеки действительно удобно и легко благодаря шаблону проектирования Builder.

Теперь, если вы хотите, мы можем проверить, как осуществлять доступ к методам к сервисам Spring MVC RESTful, который находится на стороне сервера, с помощью библиотеки реализатора стандарта JAX-RS 2.0.

1) УДАЛЕНИЕ HTTP —  http: // localhost: 8080 / rest / publisher / book / {ID}

Response response = client
        .target("http://localhost:8080/rest/") // ROOT_URL
        .path("publisher") // publisher resource
        .path("book") // book resource
        .path(String.valueOf(fxBook.getId())) // ID parameter
        .request() // HTTP request
        .delete();  // HTTP DELETE method

2) HTTP POST — http: // localhost: 8080 / rest / publisher / book

Book book = new Book();
book.setName(nameField.getText());
book.setPrice(Double.parseDouble(priceField.getText()));

// REST Entity object that will be converted to XML type 
Entity<Book> kitapEntity = Entity.entity(book, MediaType.APPLICATION_XML);
Response response = client
        .target(REST_ROOT_URL) // ROOT_URL
        .path("publisher") // Publisher resource
        .path("book")  // book resource
        .request() // HTTP request
        .post(kitapEntity); // REST Entity object is being sent to the server

3) HTTP GET — http: // localhost: 8080 / rest / publisher / book

Response response = client
        .target("http://localhost:8080/rest/")
        .path("publisher")
        .path("books")
        .request(MediaType.APPLICATION_XML) // Request the data as JSON
        .get(); // HTTP GET request is being made

// REST entity object that comes from the server is being obtained.
BookWrapper bookWrapper = response.readEntity(BookWrapper.class);

4) HTTP PUT — http: // localhost: 8080 / rest / publisher / book

Entity<Book> kitapEntity = Entity.entity(book, MediaType.APPLICATION_XML);

Response response = client
        .target(REST_ROOT_URL)
        .path("publisher")
        .path("book")
        .request()
        .put(kitapEntity); // REST Entity object is being sent to the server.

Вы можете получить доступ к сервису Spring MVC RESTful и использовать его с помощью простого приложения командной строки, а также приведенных выше примеров. Но визуальные приложения имеют больше смысла в человеческом уме. Я хочу поделиться с вами простым приложением Java FX в кодах проекта, чтобы поддержать эту идею. Визуальные компоненты  приложения JavaFX  были созданы с помощью   инструмента JavaFX Scene Builder в стандарте FXML. Вы также можете ясно увидеть детали, открыв файл компонента FXML в Project вместе с инструментом Scene Builder.

JavaFX-отдых

Вы можете получить доступ к исходным кодам в следующем сообщении в блоге. 

Надеюсь увидеть вас снова..