Mô tả kiến ​​trúc bạn sử dụng cho các ứng dụng web Java? [đóng cửa]


146

Hãy chia sẻ kiến ​​trúc ứng dụng web dựa trên Java!

Có rất nhiều kiến ​​trúc khác nhau cho các ứng dụng web sẽ được triển khai bằng Java. Các câu trả lời cho câu hỏi này có thể phục vụ như một thư viện của các thiết kế ứng dụng web khác nhau với những ưu và nhược điểm của chúng. Trong khi tôi nhận ra rằng các câu trả lời sẽ mang tính chủ quan, chúng ta hãy cố gắng khách quan nhất có thể và thúc đẩy những ưu và nhược điểm chúng ta liệt kê.

Sử dụng mức độ chi tiết bạn thích để mô tả kiến ​​trúc của bạn. Để câu trả lời của bạn có giá trị, ít nhất bạn sẽ phải mô tả các công nghệ và ý tưởng chính được sử dụng trong kiến ​​trúc mà bạn mô tả. Và cuối cùng nhưng không kém phần quan trọng, khi nào chúng ta nên sử dụng kiến ​​trúc của bạn?

Tôi sẽ bắt đầu...


Tổng quan về kiến ​​trúc

Chúng tôi sử dụng kiến ​​trúc 3 tầng dựa trên các tiêu chuẩn mở từ Sun như Java EE, Java Persistence API, Servlet và Java Server Pages.

  • Kiên trì
  • Kinh doanh
  • Trình bày

Các luồng giao tiếp có thể có giữa các lớp được thể hiện bởi:

Persistence <-> Business <-> Presentation

Ví dụ, điều đó có nghĩa là lớp trình bày không bao giờ gọi hoặc thực hiện các hoạt động bền bỉ, nó luôn thực hiện nó thông qua lớp nghiệp vụ. Kiến trúc này có nghĩa là để đáp ứng nhu cầu của một ứng dụng web có tính sẵn sàng cao.

Kiên trì

Thực hiện các thao tác tạo, đọc, cập nhật và xóa ( CRUD ). Trong trường hợp của chúng tôi, chúng tôi đang sử dụng ( API liên tục Java ) JPA và chúng tôi hiện đang sử dụng Hibernate làm nhà cung cấp kiên trì của chúng tôi và sử dụng EntityManager của nó .

Lớp này được chia thành nhiều lớp, trong đó mỗi lớp liên quan đến một loại thực thể nhất định (nghĩa là các thực thể liên quan đến giỏ hàng có thể được xử lý bởi một lớp duy trì duy nhất) và được sử dụng bởi một và chỉ một người quản lý .

Ngoài ra, lớp này cũng lưu trữ các thực thể JPA giống như Account, ShoppingCartv.v.

Kinh doanh

Tất cả logic được gắn với chức năng ứng dụng web được đặt trong lớp này. Chức năng này có thể là bắt đầu chuyển tiền cho một khách hàng muốn trả tiền cho một sản phẩm trực tuyến bằng thẻ tín dụng của họ. Nó cũng có thể tạo ra một người dùng mới, xóa một người dùng hoặc tính toán kết quả của một trận chiến trong một trò chơi dựa trên web.

Lớp này được chia thành nhiều lớp và mỗi lớp này được chú thích @Statelessđể trở thành Bean phiên phi trạng thái (SLSB). Mỗi SLSB được gọi là người quản lý và ví dụ, người quản lý có thể là một lớp được chú thích như đã đề cập AccountManager.

Khi AccountManagercần thực hiện các thao tác CRUD, nó thực hiện các cuộc gọi thích hợp đến một thể hiện của AccountManagerPersistence, đó là một lớp trong lớp kiên trì. Một bản phác thảo sơ bộ của hai phương pháp AccountManagercó thể là:

...
public void makeExpiredAccountsInactive() {
    AccountManagerPersistence amp = new AccountManagerPersistence(...)
    // Calls persistence layer
    List<Account> expiredAccounts = amp.getAllExpiredAccounts();
    for(Account account : expiredAccounts) {
        this.makeAccountInactive(account)
    }
}
public void makeAccountInactive(Account account) {
    AccountManagerPersistence amp = new AccountManagerPersistence(...)
    account.deactivate();
    amp.storeUpdatedAccount(account); // Calls persistence layer
}

Chúng tôi sử dụng các giao dịch của người quản lý container để chúng tôi không phải thực hiện phân định giao dịch. Điều cơ bản xảy ra dưới mui xe là chúng tôi bắt đầu một giao dịch khi nhập phương thức SLSB và cam kết nó (hoặc khôi phục lại nó) ngay trước khi thoát khỏi phương thức. Đó là một ví dụ về quy ước về cấu hình, nhưng chúng tôi chưa có nhu cầu gì ngoài mặc định, Bắt buộc.

Dưới đây là cách Hướng dẫn Java EE 5 từ Sun giải thích thuộc tính Giao dịch bắt buộc cho Enterprise JavaBeans (EJB's):

Nếu khách hàng đang chạy trong một giao dịch và gọi phương thức của bean doanh nghiệp, phương thức đó sẽ thực thi trong giao dịch của khách hàng. Nếu khách hàng không được liên kết với một giao dịch, container sẽ bắt đầu một giao dịch mới trước khi chạy phương thức.

Thuộc tính Bắt buộc là thuộc tính giao dịch ngầm cho tất cả các phương thức bean doanh nghiệp đang chạy với phân định giao dịch được quản lý vùng chứa. Bạn thường không đặt thuộc tính Bắt buộc trừ khi bạn cần ghi đè thuộc tính giao dịch khác. Vì các thuộc tính giao dịch là khai báo, bạn có thể dễ dàng thay đổi chúng sau này.

Trình bày

Lớp trình bày của chúng tôi phụ trách ... trình bày! Nó chịu trách nhiệm về giao diện người dùng và hiển thị thông tin cho người dùng bằng cách xây dựng các trang HTML và nhận thông tin nhập của người dùng thông qua các yêu cầu GET và POST. Chúng tôi hiện đang sử dụng kết hợp Trang + Java Server Pages ( JSP ) cũ của Servlet .

Lớp gọi các phương thức trong các trình quản lý của lớp nghiệp vụ để thực hiện các hoạt động do người dùng yêu cầu và nhận thông tin để hiển thị trên trang web. Đôi khi, thông tin nhận được từ lớp doanh nghiệp là các loại ít phức tạp hơn như Stringcác intví dụ và ví dụ, và tại các thời điểm khác, các thực thể JPA .

Ưu và nhược điểm với kiến ​​trúc

Ưu

  • Có tất cả mọi thứ liên quan đến một cách cụ thể để thực hiện kiên trì trong lớp này chỉ có nghĩa là chúng ta có thể trao đổi từ việc sử dụng JPA sang một thứ khác, mà không phải viết lại bất cứ điều gì trong lớp kinh doanh.
  • Thật dễ dàng để chúng ta hoán đổi lớp trình bày của mình thành một thứ khác, và có khả năng là chúng ta sẽ làm được nếu chúng ta tìm thấy thứ gì đó tốt hơn.
  • Để cho EJB container quản lý ranh giới giao dịch là tốt.
  • Sử dụng + JPA của Servlet rất dễ dàng (để bắt đầu) và các công nghệ được sử dụng và triển khai rộng rãi trong nhiều máy chủ.
  • Sử dụng Java EE được cho là giúp chúng tôi dễ dàng tạo ra một hệ thống có tính sẵn sàng cao với việc cân bằng tảithất bại . Cả hai chúng tôi cảm thấy rằng chúng tôi phải có.

Nhược điểm

  • Sử dụng JPA, bạn có thể lưu trữ các truy vấn thường được sử dụng như các truy vấn được đặt tên bằng cách sử dụng @NamedQuerychú thích trên lớp thực thể JPA. Nếu bạn có càng nhiều càng tốt liên quan đến sự kiên trì trong các lớp kiên trì, như trong kiến ​​trúc của chúng tôi, điều này sẽ trải rộng các vị trí mà bạn có thể tìm thấy các truy vấn để bao gồm cả các thực thể JPA. Sẽ khó hơn để tổng quan các hoạt động kiên trì và do đó khó duy trì hơn.
  • Chúng tôi có các thực thể JPA như là một phần của lớp kiên trì của chúng tôi. Nhưng AccountShoppingCart, không phải là họ thực sự đối tượng kinh doanh? Nó được thực hiện theo cách này khi bạn phải chạm vào các lớp này và biến chúng thành các thực thể mà JPA biết cách xử lý.
  • Các thực thể JPA, cũng là các đối tượng kinh doanh của chúng tôi, được tạo như Đối tượng truyền dữ liệu ( DTO ), còn được gọi là Đối tượng giá trị (VO). Điều này dẫn đến một mô hình miền thiếu máu vì các đối tượng kinh doanh không có logic của riêng họ ngoại trừ các phương thức truy cập. Tất cả logic được thực hiện bởi các nhà quản lý của chúng tôi trong lớp kinh doanh, dẫn đến phong cách lập trình thủ tục hơn. Đó không phải là thiết kế hướng đối tượng tốt, nhưng có lẽ đó không phải là vấn đề? (Sau tất cả các hướng đối tượng không phải là mô hình lập trình duy nhất mang lại kết quả.)
  • Sử dụng EJB và Java EE giới thiệu một chút phức tạp. Và chúng ta không thể sử dụng Tomcat hoàn toàn (thêm một thùng chứa vi mô EJB không hoàn toàn là Tomcat).
  • Có rất nhiều vấn đề khi sử dụng + JPA của Servlet. Sử dụng Google để biết thêm thông tin về những vấn đề này.
  • Vì các giao dịch được đóng khi thoát khỏi lớp nghiệp vụ, chúng tôi không thể tải bất kỳ thông tin nào từ các thực thể JPA được cấu hình để được tải từ cơ sở dữ liệu khi cần (sử dụng fetch=FetchType.LAZY) từ bên trong lớp trình bày. Nó sẽ kích hoạt một ngoại lệ. Trước khi trả lại một thực thể có chứa các loại trường này, chúng ta phải chắc chắn gọi các getter có liên quan. Một tùy chọn khác là sử dụng Ngôn ngữ truy vấn bền vững Java ( JPQL ) và thực hiện a FETCH JOIN. Tuy nhiên cả hai tùy chọn này đều hơi cồng kềnh.

1
Có vẻ như bạn đặt thanh quá cao với câu trả lời của riêng bạn - nó có thể khiến người khác nản lòng :)
Jonik

5
Ngoài ra, có lẽ câu hỏi của bạn nên là một câu trả lời bình thường, không phải là một phần của câu hỏi, để nó có thể được bình chọn cùng với các câu trả lời khác?
Jonik

Câu hỏi này đã được tham khảo trên meta.
D4V1D

Câu trả lời:


20

Ok tôi sẽ làm một (ngắn hơn):

  • Frontend: Tapestry (3 cho các dự án cũ hơn, 5 cho các dự án mới hơn)
  • Lớp kinh doanh: Mùa xuân
  • DAO: Ibatis
  • Cơ sở dữ liệu: Oracle

Chúng tôi sử dụng hỗ trợ giao dịch Sping và bắt đầu giao dịch khi vào lớp dịch vụ, truyền xuống cuộc gọi DAO. Lớp Dịch vụ có kiến ​​thức mô hình kinh doanh nhất và DAO làm công việc CRUD tương đối đơn giản.

Một số công cụ truy vấn phức tạp hơn được xử lý bởi các truy vấn phức tạp hơn trong phần phụ trợ vì lý do hiệu suất.

Ưu điểm của việc sử dụng Spring trong trường hợp của chúng tôi là chúng tôi có thể có các trường hợp phụ thuộc quốc gia / ngôn ngữ, đứng sau lớp Spring Proxy. Dựa trên người dùng trong phiên, việc triển khai quốc gia / ngôn ngữ chính xác được sử dụng khi thực hiện cuộc gọi.

Quản lý giao dịch gần như minh bạch, khôi phục các ngoại lệ thời gian chạy. Chúng tôi sử dụng các ngoại lệ không được kiểm soát càng nhiều càng tốt. Chúng tôi đã từng thực hiện các ngoại lệ được kiểm tra, nhưng với việc giới thiệu Spring tôi thấy lợi ích của các ngoại lệ không được kiểm tra, chỉ xử lý các ngoại lệ khi bạn có thể. Nó tránh được rất nhiều công cụ "bắt / rút lại" hoặc "ném" nồi hơi.

Xin lỗi, nó ngắn hơn bài viết của bạn, hy vọng bạn thấy điều này thú vị ...


Câu trả lời tốt đẹp! Chủ đề này dường như thu hút một số lưu lượng truy cập, đáng tiếc người khác không cảm thấy họ có thời gian để mô tả kiến ​​trúc của họ hoặc có lý do khác để không tham gia.

19

Công nghệ phát triển web dựa trên Java lý tưởng ngày nay.

Lớp web:

HTML + CSS + Ajax + JQuery

Trình điều khiển / hành động / yêu cầu xử lý web RESTFul:

Chơi khung

Lớp dịch vụ / logic nghiệp vụ:

Sử dụng Mã Java thuần túy càng lâu càng tốt. Người ta có thể hợp nhất các dịch vụ web ở đây.

Lớp chuyển đổi dữ liệu XML / JSon:

XMLTool (Tìm kiếm trên Google Code), JSoup, Google GSon, XStream, JOOX (Tìm kiếm trên Google Code)

Lớp bền bỉ:

CRUD: JPA hoặc SienaProject hoặc QueryDSL / Truy vấn phức tạp: JOOQ, QueryDSL


9

Đây là 5 xu của tôi

Trình bày

Android, Angular.JS WebClient, OAUTHv2

API

REST, Jersey (JAX-RS), Jackson (khử / tuần tự hóa JSON), các đối tượng DTO (khác với các mô hình logic nghiệp vụ)

Logic kinh doanh

Mùa xuân cho DI và xử lý sự kiện. Cách tiếp cận DDD-ish của các đối tượng mô hình. Các công việc đang chạy lâu hơn được giảm tải với SQS trong các mô-đun worker.

ĐAO

Mô hình lưu trữ với các mẫu JDBC của Spring để lưu trữ các Thực thể. Redis (JEDIS) cho Bảng xếp hạng, sử dụng Danh sách được sắp xếp. Memcache cho cửa hàng mã thông báo.

Cơ sở dữ liệu

MySQL, Memcached, Redis


Đây là một cái gì đó tương tự như những gì chúng tôi làm trong các dự án của chúng tôi quá! Ngoài JBPM cho quy trình làm việc kinh doanh. Tại sao không có mùa xuân tôi tự hỏi?
ininprsr

Tôi nên thực hiện cập nhật với vòm hiện tại của chúng tôi: Hiện tại chúng tôi sử dụng các mẫu Spring DI và JDBC cho lớp truy cập dữ liệu.
Pepster

6

Những gì chúng tôi đã theo dõi trong dự án của chúng tôi là:

Công nghệ kết thúc

  • AngularJS
  • HTML5
  • css3
  • Javascript
  • Bootstrap 3

API

  1. NGHỈ NGƠI
  2. JERSEY (JAX-RS)
  3. REST đảm bảo
  4. MÙA XUÂN
  5. Jackson
  6. an ninh mùa xuân

Logic kinh doanh

  • XUÂN DỮ LIỆU

  • Dữ liệu XUÂN MongoDB

Cơ sở dữ liệu

  • MongoDB

Máy chủ (Để lưu trữ)

  • làm lại

4

Chúng tôi vẫn đang sử dụng ngăn xếp Struts-Spring-Hibernate thông thường.

Đối với các ứng dụng trong tương lai, chúng tôi đang xem xét Spring Web Flow + Spring MVC + Hibernate hoặc Spring + Hibernate + Web Services với mặt trước Flex.

Một đặc điểm khác biệt của kiến ​​trúc của chúng tôi là mô đun hóa. Chúng tôi có một số mô-đun, một số bắt đầu với 3 đến tối đa 30 bảng trong cơ sở dữ liệu. Hầu hết các mô-đun bao gồm kinh doanh và dự án web. Dự án kinh doanh giữ logic kinh doanh và kiên trì trong khi web giữ logic trình bày.
Ở cấp độ logic, có ba lớp: Kinh doanh, Kiên trì và Trình bày.
Phụ thuộc:
Trình bày phụ thuộc vào Kinh doanh và Kiên trì.
Sự kiên trì phụ thuộc vào Kinh doanh.
Kinh doanh không phụ thuộc vào các lớp khác.

Hầu hết các dự án kinh doanh có ba loại giao diện (lưu ý: không phải GUI, nó là lớp giao diện java có lập trình).

  1. Giao diện mà bản trình bày đang sử dụng như một ứng dụng khách
  2. Giao diện mà các mô-đun khác đang sử dụng khi chúng là máy khách của mô-đun.
  3. Giao diện có thể được sử dụng cho mục đích quản trị của mô-đun.

Thông thường, 1 mở rộng 2. Bằng cách này, thật dễ dàng để thay thế một triển khai mô-đun bằng một mô-đun khác. Điều này giúp chúng tôi áp dụng cho các khách hàng khác nhau và tích hợp dễ dàng hơn. Một số khách hàng sẽ chỉ mua một số mô-đun nhất định và chúng tôi cần tích hợp chức năng họ đã có. Vì giao diện và lớp triển khai được tách riêng, nên có thể dễ dàng triển khai triển khai mô-đun quảng cáo cho khách hàng cụ thể đó mà không ảnh hưởng đến các mô-đun phụ thuộc. Và Spring Framework giúp dễ dàng thực hiện các cách thực hiện khác nhau.

Lớp kinh doanh của chúng tôi dựa trên POJO. Một xu hướng tôi đang quan sát là các POJO này giống với các DTO. Chúng tôi bị mô hình miền thiếu máu . Tôi không chắc tại sao điều này xảy ra nhưng có thể là do sự đơn giản của miền vấn đề của nhiều mô-đun của chúng tôi, hầu hết công việc là CRUD hoặc do các nhà phát triển thích đặt logic ở nơi khác.


3

Đây là một kiến ​​trúc web nữa mà tôi đã làm việc:

Một yêu cầu chính là ứng dụng phải hỗ trợ điện thoại di động / các thiết bị khác. Ứng dụng cũng nên được mở rộng hoặc linh hoạt với những thay đổi trong lựa chọn công nghệ.

Cấp trình bày:

  • JSP / JQuery (MVC phía máy khách)
  • Android gốc
  • IPhone bản địa
  • Web di động (HTML5 / CSS3 / Thiết kế đáp ứng)

  • Bộ điều khiển Spring REST (Có thể thay đổi thành JAX-RS)

Cấp dịch vụ kinh doanh:

Spring @Service (Có thể thay đổi thành EJB không quốc tịch)

Cấp truy cập dữ liệu:

Spring @Rep repository (Có thể thay đổi thành EJB không quốc tịch)

Cấp tài nguyên:

Các thực thể Hibernate (JPA) (Có thể thay đổi thành bất kỳ ORM nào)

Bạn có thể tìm thêm thông tin về cuốn sách theo kiến ​​trúc này ở đây .


2

IMHO, hầu hết chúng ta đều có mẫu số chung. Cuối cùng, chúng ta có một số dạng IOC / DI container và khung bền vững. Cá nhân tôi sử dụng Guice và Mybatis cho việc này. Sự khác biệt là cách chúng tôi triển khai lớp xem / UI / trình bày. Có 2 tùy chọn chính ở đây (có thể nhiều hơn) .. Dựa trên hành động (URL được ánh xạ tới bộ điều khiển) và dựa trên thành phần. Hiện đang sử dụng lớp trình bày dựa trên thành phần (sử dụng wicket). Nó bắt chước hoàn hảo một môi trường máy tính để bàn nơi tôi sử dụng các thành phần và sự kiện trái ngược với URL và bộ điều khiển. Hiện đang tìm kiếm một lý do tại sao tôi nên chuyển sang loại kiến ​​trúc của trình điều khiển URL này (đó là cách tôi kết thúc trên trang này). Tại sao sự cường điệu về kiến ​​trúc RESTful và Statless.

Để trả lời câu hỏi này một cách ngắn gọn: Tôi viết các ứng dụng web có trạng thái bằng cách sử dụng khung định hướng thành phần trên thùng chứa Guice IOC và đưa dữ liệu vào cơ sở dữ liệu quan hệ bằng Mybatis.


1

Một chút khác biệt, và tôi sẽ yêu cầu kiến ​​trúc java mô-đun nhiều hơn ở đây. Chúng ta có:

  1. Kết thúc mùa xuân WS / Rest / JSP
  2. Spring MVC cho logic dịch vụ doanh nghiệp, chứa logic lớp trình bày cũng như các giao dịch Spring
  3. Giao diện dịch vụ thành phần, tìm kiếm thông qua EJB bởi các dịch vụ kinh doanh. Các EJB đặt ranh giới giao dịch của riêng họ có thể tham gia các giao dịch Mùa xuân.
  4. Thành phần dịch vụ triển khai, một lần nữa thành phần mùa xuân
  5. Lớp tích hợp, MyBatis cho tích hợp cơ sở dữ liệu, Spring WS cho tích hợp dịch vụ web, các công nghệ tích hợp khác cho các dịch vụ khác
  6. Máy tính lớn, cơ sở dữ liệu, dịch vụ khác tại các máy chủ khác ...

Ngoài các mục trên, chúng tôi có các mô-đun thư viện dùng chung, là nhà cung cấp chức năng chung cho tất cả các srevice.

Sử dụng các lớp khác nhau cho phép chúng tôi tách rời hoàn toàn và mô-đun chúng tôi cần. Chúng tôi cũng có thể sử dụng đầy đủ sức mạnh của Java EE cũng như Spring. Không có gì ngăn cản chúng tôi sử dụng JSF, ví dụ, cho giao diện người dùng nếu cần.

So với kiến ​​trúc ví dụ của OP, tôi nghĩ rằng điều này có thể được mô tả là có bốn lớp chính thay vì ba lớp, mặc dù có một vòng xoắn.


0

Tôi đã làm việc trên các dự án sử dụng mô hình quản lý cứng nhắc đó. Trong lịch sử, tôi là một người ủng hộ rất lớn cho hệ thống phân cấp cứng nhắc, nơi mọi thứ phù hợp với một hộp gọn gàng. Khi tôi tiến bộ trong sự nghiệp, tôi thấy nó bị ép buộc trong rất nhiều trường hợp. Tôi tin rằng việc áp dụng một tư duy nhanh nhẹn hơn vào thiết kế ứng dụng sẽ dẫn đến một sản phẩm tốt hơn. Ý tôi là gì khi tạo ra một tập hợp các lớp giải quyết vấn đề trong tay. Thay vì nói "Bạn đã xây dựng một người quản lý cho cái này và cái kia chưa?"

Dự án hiện tại tôi đang làm việc là một ứng dụng web với sự kết hợp của các lệnh gọi JSON / Ajax của Spring MVC và RestPal. Về phía máy chủ được nhúng trong bộ điều khiển của chúng tôi là tầng dữ liệu dựa trên mặt tiền hợp lý với JPA / Hibernate để truy cập Cơ sở dữ liệu trực tiếp, một số truy cập EJB và một số cuộc gọi dịch vụ web dựa trên SOAP. Liên kết tất cả những thứ này lại với nhau là một số mã trình điều khiển java tùy chỉnh để xác định những gì sẽ tuần tự hóa như JSON và trả về máy khách.

Chúng tôi gần như không dành thời gian để cố gắng tạo ra một số mẫu thống nhất thay vì chọn áp dụng ý tưởng "Tệ hơn là tốt hơn" của Triết lý thiết kế Unix. Làm cho nó tốt hơn nhiều để tô màu bên ngoài các dòng và xây dựng một cái gì đó hợp lý, nhanh hơn là để xây dựng một cái gì đó tuân thủ một loạt các nhiệm vụ thiết kế nghiêm ngặt.


0

Các thành phần trong Kiến trúc ứng dụng Web bao gồm:

1: Trình duyệt: Tương tác máy khách

        HTML
        JavaScript
        Stylesheet

2: Internet

3: Máy chủ web

        CSS
        Image
        Pages(Java render )

4: Máy chủ ứng dụng

        App Webapp (Java interaction)
        Others WebApps

5: Máy chủ cơ sở dữ liệu

        Oracle, SQL, MySQL

6: Dữ liệu

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.