1. Kiến trúc Dự án Truyền thống và Khung SSM
1.1. Lập trình Mạng
Chi tiết tại: https://www.cnblogs.com/szrs/p/12121032.html
1.2. Giới thiệu về Kiến trúc và Khung
- Kiến trúc tổng thể phát triển phần mềm B/S (Browser/Server) và C/S (Client/Server) là kiến trúc ứng dụng đơn lẻ.
- Kiến trúc hướng dịch vụ (SOA - Service-Oriented Architecture).
- Các quyết định về kiến trúc được thể hiện qua khung và chương trình phần mềm được phát triển. MVC là một mẫu phát triển, nhiều khung dựa trên tư tưởng lập trình này, tách biệt xử lý giao diện người dùng, gọi chức năng và triển khai chức năng.
1.3. Quy trình Giới thiệu Khung
- Cấu hình mybatis.xml.
- Tích hợp web.xml, applicationContext.xml và mybatis.xml.
- Tích hợp SpringMVC với mybatis.xml và applicationContext.xml: Ba tệp cấu hình chính là web.xml, springmvc.xml và applicationContext-mybatis.xml. Thông thường, hai tệp sau không được gộp chung.
- Dự án SOA: Tách springmvc.xml thành nhiều tệp cấu hình. Bao gồm AOP, Dubbo, đọc tài nguyên tĩnh.
1.3.1. Bước 1: Thảo luận về Khung: Dự án B/S, Khung SSM
Dự án B/S hoạt động dựa trên máy chủ và trình duyệt web, về cơ bản là một kiến trúc ứng dụng đơn lẻ. Với lượng truy cập nhỏ, điểm kỹ thuật chính là các framework giúp tăng hiệu quả truy cập cơ sở dữ liệu: các framework truy cập dữ liệu (ORM) giúp đơn giản hóa công việc CRUD (Create, Read, Update, Delete). Ánh xạ quan hệ đối tượng-quan hệ (Object-Relational Mapping - ORM) là yếu tố then chốt. Chỉ cần một ứng dụng duy nhất, triển khai tất cả các chức năng cùng nhau để giảm chi phí và số lượng nút triển khai. Điều này không yêu cầu phát triển phân tán. Phát triển phân tán liên quan đến các framework dịch vụ, ví dụ như Dubbo: nhà cung cấp dịch vụ, trung tâm đăng ký và người tiêu dùng dịch vụ. So với việc triển khai dự án trên nhiều máy chủ Linux, chi phí thấp hơn nhiều. Phần dưới đây sẽ giải thích chi tiết về việc xây dựng dự án B/S và dự án phân tán.
1.3.2. Bước 2: Thảo luận về Thiết lập Môi trường Phát triển
Quy trình thiết lập môi trường phát triển: Đầu tiên, sử dụng khung SSM. Chúng ta sẽ thiết lập khung phát triển trước. Trước khi thiết lập khung, chúng ta cần nhập các tệp jar cần thiết vào dự án.
- Jar cốt lõi.
- Log4j: Gói nhật ký.
- Asm: Gói xử lý tệp java, Spring và MyBatis phụ thuộc vào gói này để hoạt động.
- Cglib: Gói proxy động của MyBatis. Với gói này, có thể khởi tạo các lớp triển khai của giao diện và thực thi các phương thức.
- Commons: Gói ghi nhật ký của Spring.
- Javaassist: Gói hỗ trợ tệp mã byte, chịu trách nhiệm xử lý tệp mã byte.
- Log4j: Gói nhật ký cho chương trình java.
- Mybatis-3.2.7.jar: Gói cốt lõi thực thi framework MyBatis.
- Slf4j: Một định dạng gói nhật ký khác. Vì MyBatis hỗ trợ nhiều định dạng nhật ký, có thể lựa chọn khi chạy.
1.3.3. Bước 3: Thảo luận về Cấu trúc và Nguyên lý Tệp Cấu hình
1.3.3.1. Cấu hình Framework MyBatis
1. Tệp mybatis.xml trong thư mục src:
Đầu tiên, sửa đường dẫn trình xác thực tài liệu .dt thành cục bộ, trong xmlcatalog của xml trên Windows.
- Thẻ gốc:
configuration. Tất cả các thẻ khác được đặt bên trong thẻ này.settingsđể bật nhật ký log4j;typeAliasesđể đặt bí danh cho các gói. environments: Môi trường sử dụng của framework MyBatis. Thuộc tínhdefaultphải giống với thuộc tínhnamecủa thẻ conenvironmentbên trong nó.datasource: Nguồn dữ liệu để kết nối cơ sở dữ liệu. Các thẻ conpropertiesbao gồm: Driver, url, username, password. Chúng cũng có thể được cấu hình trongconfigurationhoặc được nhập từ bên ngoài. Sử dụng công nghệ connection pool.transactionManager:<transactionManager type="JDBC"></transactionManager> <transactionManager type="MANAGED"></transactionManager>mappers: Nhập và tải bất kỳ tệp tài nguyên nào vào tệp cấu hình hiện tại.<mappers> <mapper resource="com/bjsxt/mapper/FlowerMapper.xml"/> <mapper class="com.bjsxt.mapper.ClassroomMapper"/> <mapper class="com.bjsxt.mapper.StudentMapper"/> </mappers>Các lớp như POJO (Plain Old Java Object) là các lớp thực thể. Mapper là các giao diện, chỉ viết các phương thức. Đối với các câu lệnh SQL phức tạp, nên viết bằng XML, ví dụ như SQL động, phân trang, truy vấn mờ. Xem lại các câu lệnh SQL truy vấn trong MyBatis 8 về trang bị tự động, trang bị thủ công và truy vấn N+1. --> Tương ứng giữa tham số và thuộc tính của câu lệnh truy vấn SQL.
2. Tệp mapper.xml:
<mapper namespace="com.bjsxt.mapper.ClassroomMapper">
Kiểm thử: Bao gồm trường hợp chỉ có tệp mapper.xml và trường hợp có giao diện mapper. Đối với trường hợp đầu, sau khi lấy SqlSessionFactory từ đối tượng resources, sử dụng mẫu Builder SqlSessionFactoryBuilder() để nhanh chóng tạo một đối tượng khởi tạo. Sau đó, lấy đối tượng SqlSession được đóng gói với API cho tất cả các hoạt động CRUD (Create, Read, Update, Delete) trên cơ sở dữ liệu. Với đối tượng session, thực hiện các thao tác thêm, sửa, xóa, truy vấn. Khi có giao diện mapper, bạn cũng có thể lấy lớp proxy động của giao diện mapper để gọi các phương thức trong mapper.
// Tải tệp cấu hình mybatis.xml hiện tại
InputStream is = Resources.getResourceAsStream("mybatis.xml");
// Xây dựng đối tượng nhà máy SqlSessionFactory bằng trình xây dựng
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
// Lấy đối tượng SqlSession
SqlSession session = factory.openSession();
FlowerMapper fm = session.getMapper(FlowerMapper.class);
//int n = fm.insFlower("玫瑰", 12.23, "中国");
Flower f = new Flower();
f.setName("杜鹃");
f.setPrice(12.3);
f.setProduction("北京");
// Thêm giống hoa mới
int n = fm.insFlower2(f); // Hoặc:
int n = session.insert("com.bjsxt.mapper.FlowerMapper.insFlower", f);
System.out.println(n);
session.commit();
session.close();
Mở rộng bộ nhớ đệm của MyBatis: Sau khi kiểm thử xong, nhất định phải đóng session. Nếu là thao tác DML, cần phải commit giao dịch.
Bộ nhớ đệm MyBatis: Giảm thiểu tương tác với cơ sở dữ liệu, là một trung gian được thiết lập giữa cơ sở dữ liệu và ứng dụng.
- Bộ nhớ đệm cấp 1: Dựa trên đối tượng
sqlSession. Lưu trữ đối tượngPreparedStatement. Áp dụng cho các thẻ. - Bộ nhớ đệm cấp 2: Dựa trên
SqlSessionFactory. Mỗi lần tạo một đối tượngsqlSessionsẽ có bộ nhớ đệm. Hiệu quả cao hơn, nhưng có thể gây dư thừa dữ liệu, làm cho dữ liệu không chính xác. Để tránh việc tạo quá nhiều đối tượng POJO, thêm cấu hình sau vào tệp cấu hình mybatis.xml:<cache readOnly="true"></cache>
Định danh dữ liệu: Giá trị id của thẻ truy vấn trong tệp ánh xạ.
- Đối tượng ThreadLocal: Tương tự như một lớp chứa, lưu trữ một đối tượng (object), và có thể truy cập ở bất kỳ đâu trong cùng một luồng. Tạo một lớp tiện ích, sử dụng mẫu thiết kế Factory, để tất cả các
sessionlà một đối tượng duy nhất.
1.3.3.2. Cấu hình Spring
- Cấu hình Spring: Bước đầu tiên là nhập các gói cần thiết. Tạo tệp
applicationContext.xml:- Schema mạnh mẽ hơn DTD, cung cấp trình xác thực, gợi ý và có thể mở rộng chức năng mới thông qua các thành phần mở rộng xác thực, có thể liên tục thích ứng với các thay đổi về nội dung và chức năng của tài liệu XML.
- Chỉ tệp cấu hình Spring: Chỉ cần khởi tạo và cấu hình thẻ
beanvới các thuộc tínhidvàclass: hỗ trợ IOC (Inversion of Control - Điều khiển Ngược chiều) và DI (Dependency Injection - Tiêm Phụ thuộc). - IOC: Điều khiển Ngược chiều. Trước đây, đối tượng được khởi tạo bằng cách gọi
new. Bây giờ, chỉ cần cấu hìnhbeantrong tệp cấu hình cho đối tượng cần khởi tạo, và việc tạo đối tượng được giao cho Spring Container. Có ba cách:type,name,index. - DI: Tiêm Phụ thuộc. Ý nghĩa tương tự như IOC. Phụ thuộc là mối quan hệ giữa các lớp. Ở đây, sử dụng "liên kết" (association) sẽ phù hợp hơn, vì một lớp đóng vai trò là thuộc tính của lớp khác, và thuộc tính này được gán giá trị.
// Kiểm thử: // Classpath: Tìm kiếm tệp cấu hình xml từ thư mục classes, tạo Spring Container ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); // Lấy đối tượng People People people = ac.getBean("peo", People.class); - Về tiêm phụ thuộc: Có tiêm tự động:
autowire. Các tùy chọn bao gồmbyName,byType,constructor. Khi đặt làNO, giá trị của thuộc tínhdefault-autowiresẽ được sử dụng để xác định.typevànameở đây đề cập đến giá trịidcủa thẻbeancủa lớp làm thuộc tính.Sau khi giới thiệu chú thích, khi tệp cấu hình bao gồm:
<context:component-scan base-package="com.bjsxt.service.impl"></context:component-scan>Hỗ trợ quét chú thích cho lớpcom.bjsxt.service.impl(được cho là đã đóng gói thuộc tínhnamevàclasscủabean). Khi hỗ trợ chú thích,@Autowiredtiêm theobyName, chú thích@Resourcelần lượt tiêm theobyNamevàbyType. Ngoài ra, Spring còn có các thẻ con khác. Chúng tôi chỉ giới thiệu cấu hình của nó để khởi tạo đối tượng, tức là cấu hìnhbean(và hỗ trợ chú thích). - Tiếp theo là Spring tích hợp MyBatis và các thẻ con khác (aop, tx, context): Tất cả các thẻ này đều yêu cầu nhập tệp mở rộng trình xác thực tài liệu mới.
- Hai cách tích hợp:
- Cấu hình tệp
web.xml: Sử dụng listener và đường dẫn để tự động tải tệpapplication.xml. Sử dụng<context-param>và<listener>. - Tệp
applicationContext-mybatis.xml:- Cấu hình nguồn dữ liệu
dataSource.context:property-placeholdercho phép nạp từ tệp cấu hình bên ngoài. Lưu ý rằng tên thuộc tínhpropertykhông thể tùy ý đặt, phải tìm trong tệp nguồn. - Cấu hình đối tượng
SqlSessionFactory, tức là để Spring quản lý instance của lớp factory MyBatis. - Cấu hình Spring để quản lý các giao diện trong gói
mappercủa MyBatis. - Cấu hình
beanchoserviceImpl. Bước này thường có hỗ trợ chú thích, không cần thêmbeanvào tệp cấu hình mỗi khi tạo một giao diện và lớp triển khai của nó. Chỉ cần cấu hình thẻcontext:component-scanđể cho phép quét chú thích cho lớp triển khai này. Thẻ này yêu cầu thêm tệp mở rộng context của trình xác thực tài liệu. Khi không sử dụng chú thích, sử dụngWebApplicationContextđể lấy đối tượngbeanđã được khởi tạo. Khi không khởi tạo bằng chú thích, cần có phương thức getter và setter cho lớp được sử dụng làm thuộc tính. - Sau khi tích hợp SpringMVC, tệp quét chú thích cho tầng controller thường được cấu hình riêng biệt với tệp quét chú thích cho tầng nghiệp vụ.
- Cấu hình nguồn dữ liệu
tx(Giao dịch):- Giao dịch bằng mã: Mã phải liên quan trực tiếp đến giao dịch, ví dụ như
commit,rollback. - Giao dịch khai báo: Giao giao dịch cho Spring xử lý. Chỉ cần khai báo các phương thức cần thêm giao dịch. Liên quan đến AOP.
- Giao dịch bằng mã: Mã phải liên quan trực tiếp đến giao dịch, ví dụ như
- Thêm
beancho lớp đóng gói giao dịch.TransactionManagerđể Spring tải lớp xử lý giao dịch. - Các phương thức cần xử lý giao dịch: thẻ
tx.<tx:advice id="tran" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="register" read-only="false"/><!-- Giá trị mặc định là false, nghĩa là xử lý giao dịch. Nếu là true, nghĩa là không xử lý giao dịch, thường dùng cho các phương thức truy vấn. --> </tx:attributes> </tx:advice> - Thêm thông báo (advice): tức là AOP:
aop:config->aop:pointcut->aop:advisor. - Đọc bẩn (Dirty Read): Giữa hai giao dịch: Một giao dịch sửa đổi dữ liệu trong cơ sở dữ liệu nhưng chưa commit. Giao dịch khác tình cờ đọc được dữ liệu này, dữ liệu này không chính xác, tức là xảy ra đọc bẩn.
- Đọc không lặp lại (Non-repeatable Read): Hiện tượng xảy ra trong cùng một giao dịch: Tức là giữa lần đọc thứ nhất và lần đọc thứ hai một dữ liệu trong một giao dịch, có một giao dịch khác đã sửa đổi dữ liệu đó. Do đó, dữ liệu đọc được hai lần sẽ khác nhau, tức là xảy ra đọc không lặp lại.
- Đọc ảo (Phantom Read): Xảy ra khi các giao dịch không thực thi độc lập. Ví dụ, một lần đọc và một lần chèn dữ liệu. Khi xảy ra đồng thời (tức là thực thi đồng thời), có thể không đọc được toàn bộ dữ liệu (dữ liệu được nhập chưa kịp đọc).
- Định nghĩa: Thực thi trước khi trình điều khiển được truy cập bởi máy khách, và thực thi lại sau khi trình điều khiển và JSP đã thực thi. Thực hiện một số công việc trước khi truy cập trình điều khiển, và thực hiện một số công việc sau khi truy cập trình điều khiển.
- Dựa trên đặc điểm: Tương tự như
filter, tương tự nhưaop. - So sánh trình chặn và bộ lọc:
filter: Có thể lọc tất cả các tài nguyên truy cập.interceptor: Chỉ có hiệu lực đối với các phương thức của trình điều khiển.
- So sánh trình chặn và AOP:
aop: Liên kết thông báo (trước, sau) với tất cả các phương thức điểm cắt.interceptor: Chỉ có hiệu lực đối với các phương thức của trình điều khiển.
- Nguyên lý thực thi: Việc triển khai trình chặn trước tiên cần triển khai giao diện
HandlerInterceptorvà thực hiện các phương thức liên quan. - Thứ tự thực thi:
MyInterceptor.preHandle(): Thực thi trước trình điều khiển.DemoController.demo1(): Thực thi trình điều khiển.MyInterceptor.postHandle(): Sau trình điều khiển, trước JSP.MyInterceptor.afterCompletion(): Sau JSP.
- Tham số trong phương thức:
req: Đối tượng yêu cầu.resp: Đối tượng phản hồi.Object:handler(phương thức trình điều khiển bị chặn).
- Tạo chú thích mới
@interface, viết phương thức, giá trị mặc định là " ". - Thêm hỗ trợ trong tệp cấu hình
springmvc.xml.<!-- Kích hoạt hỗ trợ chú thích @AspectJ --> <aop:aspectj-autoproxy proxy-target-class="true" /> <!-- Khía cạnh --> <bean id="systemLogAspect" class="org.rentcar.annotation.SystemLogAspect"/>Phương thức khía cạnh này sẽ ghi lại những gì cần thiết vào cơ sở dữ liệu. - Tạo phương thức khía cạnh và sử dụng nguyên lý phản chiếu để lấy nội dung chú thích tùy chỉnh đã được chú thích ở tầng Controller.
- Kiểm tra xem đường dẫn có phải là phương thức đăng nhập trong trình điều khiển hay không: Nếu đúng, cho phép đi tiếp; nếu không, chuyển hướng đến trang đăng nhập.
- Kiểm tra xem người dùng có rỗng hay không. Nếu rỗng, chuyển hướng đến trang đăng nhập; nếu không, tiếp tục.
- Kiểm tra xem đối tượng
usercó chứa đường dẫn cần truy cập hay không. Nếu có, chuyển hướng; nếu không, chuyển hướng đến trang đăng nhập. (Ở đây, đối tượng thực thểuserđược đóng gói với một tập hợp các đường dẫn mà người dùng đó có quyền truy cập). - Thiết kế bảng cơ sở dữ liệu: Giới thiệu bảng
role.- Thiết kế
role-user: Phân bổ vai trò trực tiếp cho người dùng, đơn giản, dễ thao tác. - Thiết kế
role-url: Phân bổ đường dẫn cho vai trò. Để đảm bảo an toàn truy cập, kiểm tra trong trình chặn để ngăn chặn người dùng chưa đăng nhập truy cập trang của chương trình. - Thiết kế
role-menu: Chỉ định menu tương ứng cho từng vai trò.
- Thiết kế
- Câu lệnh SQL: Chủ yếu là truy vấn đệ quy của bảng
menu. Số hiệu cha của menu con chính là số hiệu cha của menu cha. - Cho phép người dùng khác nhau xem các menu khác nhau (sau khi đăng nhập).
- Hiệu ứng hiển thị trang web khác nhau cho người dùng khác nhau:
- Một số người có thể thấy nút chức năng thêm.
- Một số người chỉ có thể thấy nút chức năng hiển thị.
- Những người khác nhau thực hiện các chức năng khác nhau dưới cùng một dự án.
- Kiến trúc ứng dụng đơn lẻ: Tăng hiệu quả của framework ORM ở tầng truy cập dữ liệu. Quá trình lưu trữ dữ liệu.
- Kiến trúc ứng dụng theo chiều dọc: Khi lượng truy cập tăng dần, việc tăng máy cho một ứng dụng đơn lẻ mang lại hiệu quả ngày càng ít. Chia ứng dụng thành các ứng dụng độc lập không liên quan để tăng hiệu quả. Lúc này, framework Web (MVC) để tăng tốc phát triển trang front-end là yếu tố then chốt.
- Kiến trúc dịch vụ phân tán: Khi số lượng ứng dụng theo chiều dọc ngày càng tăng, tương tác giữa các ứng dụng là không thể tránh khỏi. Trích xuất các nghiệp vụ cốt lõi làm dịch vụ độc lập, dần dần hình thành một trung tâm dịch vụ ổn định, giúp ứng dụng front-end phản ứng nhanh hơn với nhu cầu thị trường thay đổi. Lúc này, framework dịch vụ phân tán (RPC) để tăng cường tái sử dụng và tích hợp nghiệp vụ là yếu tố then chốt.
- Kiến trúc điện toán lưu động: Khi số lượng dịch vụ ngày càng tăng, các vấn đề như đánh giá dung lượng và lãng phí tài nguyên dịch vụ nhỏ dần xuất hiện. Lúc này, cần thêm một trung tâm điều phối dựa trên áp lực truy cập để quản lý dung lượng của cụm theo thời gian thực, tăng hiệu quả sử dụng cụm. Lúc này, trung tâm quản lý và điều phối tài nguyên (SOA) để tăng hiệu quả sử dụng máy móc là yếu tố then chốt. Cân bằng tải Nginx, gọi máy chủ có áp lực thấp trong cụm.
- Thêm, xóa, sửa giỏ hàng.
application,sessionhoặccookie, nhưng rõ ràng là không hợp lý.- Quy trình thêm:
Chúng ta đều biết Redis là cơ sở dữ liệu phi quan hệ, lưu trữ dữ liệu theo cặp
key-value. Ở đây,keyđược sử dụng làidcủa người dùng. Đầu tiên, trong phần đăng nhập một lần, chúng ta đã lưu trữ thông tin người dùng vào Redis, vàidcủa nó làuser:UUID.UUIDnày được lưu trữ trongcookie(trong lớp tiện ích chungego-commons, đặt các công cụ cần thiết cho nhiều dịch vụ). Bằng cách này, chúng ta có thể lấykeycủa người dùng hiện tại được lưu trữ trong Redis, từ đó lấy thông tin người dùng. Thông qua thông tin người dùng, lấyidcủa người dùng, sau đó lấykeylưu trữ giỏ hàng. Sau đó, lấy thông tin sản phẩm thông quaitemIdđược truyền từ front-end (chúng ta đã lưu trữ thông tin sản phẩm vào Redis khi truy vấn chi tiết sản phẩm). Đóng gói thuộc tính cần thiết của giỏ hàng vào đối tượng thực thể giỏ hàng. Lưu ý ở đây là Redis có thể lưu trữ thông tin của nhiều sản phẩm, vì vậy phần đọc từ giỏ hàng ra là một tập hợp các sản phẩm trong giỏ hàng. - Hiển thị thông tin giỏ hàng: Sau khi thêm giỏ hàng, chúng ta xin nhắc lại rằng trên trang giỏ hàng, không có nút thanh toán. Lúc này, chỉ có thể nhấp vào "Đi thanh toán", sẽ nhảy đến một dịch vụ thanh toán? 666, viết đến đây đã mệt.
- AOF: Sao lưu thời gian thực, liên tục ghi nhật ký vào tệp nhật ký. Dẫn đến tệp quá lớn, thời gian phục hồi dài.
- RDB: Sao lưu sau một khoảng thời gian nhất định, dẫn đến mất dữ liệu nhiều. Phương thức mặc định.
- Cài đặt độc lập: Sao chép gói nén Redis vào thư mục root và giải nén --> Thêm phụ thuộc gcc-c++:
yum install gcc-c++ automake autoconf--> Tạo thư mục cài đặtmkdir -p /usr/local/redis, và biên dịch bằngmake. - Cài đặt:
make install PREFIX=/usr/local/redis - Sao chép tệp cấu hình
redis.confvào thư mục bin và sửa đổidaemonizetrong tệp cấu hìnhredis.confthànhyesđể khởi động ở chế độ nền. - Sau đó, chạy
./redis-server ./redis.confđể khởi động lại dịch vụ. - Kết nối máy khách với dịch vụ, cần cài đặt cổng tường lửa hoặc tắt tường lửa trực tiếp.
- Và đặt địa chỉ IP: Cấu hình
bindtrongredis.confthành:bind *. Số lượng cơ sở dữ liệudatabases 16nghĩa là có 16 cơ sở dữ liệu mặc định. redis-cli: nghĩa là client Redis.redis-server: nghĩa là server Redis.- Năm loại dữ liệu: String, Hash, List, Set, Sorted Set.
- Trong phát triển thực tế, thường sử dụng String và Hash { "key1": "value1", "key2": "value2" } theo cặp key-value.
- Trong Eclipse, để quản lý cơ sở dữ liệu Redis, trước tiên cần nhập gói jar, sử dụng
JedisPoolđể quản lý nguồn dữ liệu. - Sao chép script Ruby vào thư mục root, giải nén, và tạo thư mục cấu hình, nhật ký và dữ liệu Redis trong thư mục root.
- Sao chép sáu tệp cấu hình Redis và một tệp cấu hình chung (chỉ cần sửa đổi
bind(IP) và hỗ trợ cluster, do đó cần một tệp cấu hình chung) vào thư mục cấu hình đã tạo. Sau đó tạo./start.shđể khởi động, cấp quyền. Khởi động sáu dịch vụ. - Bước ba là sử dụng Ruby để quản lý dịch vụ Redis, thực hiện cluster, chạy lệnh tạo cluster. Tạo thành công. Sau đó có thể kiểm tra cluster bằng
./redis-cli -c -p 6379.-cđại diện cho cluster,-pđại diện cho cổng. - Slots: Có 16384 slot, được tính toán bằng thuật toán CRC16 để xác định slot đó thuộc về Redis nào trong cluster.
- Tệp cấu hình: Cấu hình địa chỉ IP và cổng của Redis cluster.
- Quản lý lớp
daovà lớp triển khaijedis, cấu hình hỗ trợ chú thích@Repository. - Lớp triển khai có thể có lớp
RedisClientsthực sự gọi các phương thứcsetvàgetcủa Redis. - Phân chia cơ sở dữ liệu (Sharding Database): Một cơ sở dữ liệu được chia thành nhiều cơ sở dữ liệu logic thông qua MyCAT. Các cơ sở dữ liệu này được gọi chung là thư viện logic (theo chiều dọc - theo nghiệp vụ).
- Phân chia bảng (Sharding Table): (Theo chiều ngang - theo thao tác).
schema.xml: Cấu hình máy chủ đọc/ghi, tức là cơ sở dữ liệu Master/Slave của MySQL; định nghĩa thư viện logic, bảng logic.server.xml: Định nghĩa thư viện logic, tên người dùng và mật khẩu để kết nối cơ sở dữ liệu.rule.xml: Định nghĩa quy tắc phân chia của MyCAT, ví dụ: thuật toáncrc32. Xem dữ liệu được chia thành thư viện logic nào.- Nạp lại: Trước tiên, cấu hình Tomcat trên Linux:
vim tomcat-users.xml:<role rolename="manager-gui"/> <role rolename="manager-script"/> <user username="tomcat" password="tomcat" roles="manager-gui,manager-script"/> Khởi động lại Tomcat. - Trong tệp
pom.xmlcủa dự ánwarcần triển khai:<port>8082</port>
<path>/</path>Thêm cấu hình bên dưới.
<username>tomcat</username>
<password>tomcat</password>
<url>http://192.168.26.150:8080/manager/text</url> --> manager/text là cố định, phần trước là IP và cổng của máy chủ nơi dự án sẽ được triển khai.Tiếp theo là triển khai tomcat7:redeploysử dụngmaven build... - Kiểm tra xem đã triển khai thành công hay chưa: Tìm trong thư mục Tomcat, thư mục
webapps, thư mụcROOT:cd /WEB-INF/lib, kiểm tra xem có tệp jar của dự án hay không. - Truy cập: Có thể truy cập trực tiếp trên trình duyệt
http://192.168.26.150:8080/ - Sửa đổi ánh xạ: Cấu hình ánh xạ ảo
C:\Windows\System32\drivers\etc\hosts192.168.26.150 www.ego.com - Nếu không ghi rõ cổng, mặc định là cổng 80. Sửa đổi cổng Tomcat trên máy chủ Linux thành 80.
- Cần khởi động lại Tomcat. Truy cập qua tên miền.
- Trong tệp
server.xml, sửa đổi cổng Tomcat. - Thư mục gốc của Tomcat:
Catalinacatalina.policycatalina.propertiescontext.xmllogging.propertiesserver.xmltomcat-users.xmlweb.xml
- Theo tình hình, có thể sử dụng Nginx để proxy các dịch vụ có áp lực lớn (cân bằng tải).
Spring không làm lại những thứ đã có. Sự ra đời của nó chủ yếu phục vụ lớp Service (tầng nghiệp vụ), không cần phải tự khởi tạo đối tượng.
3.1. Spring tích hợp MyBatis
Hiện tại đã hoàn tất cơ bản việc tích hợp Spring và MyBatis.
Tất nhiên, Spring còn hỗ trợ các khía cạnh lập trình giao dịch tx và lập trình đối tượng khía cạnh aop. Chúng ta sẽ thảo luận chi tiết hơn khi triển khai chức năng dự án.
3.2. AOP và TX
Trong dự án SSM, giao dịch được thêm vào tầng nghiệp vụ, tức là tầng service. Các phương thức của tầng service được coi là điểm cắt (pointcut). Nếu có lỗi xảy ra, thông báo sẽ không nhận được giao dịch nếu xử lý lỗi ở tầng nghiệp vụ. Thêm cấu hình giao dịch vào tệp cấu hình:
Trong applicationContext.xml:
Spring sử dụng proxy động của JDK ở tầng dưới. Theo mặc định, nó không tạo ra đối tượng thực thể thực sự của giao diện. Vấn đề phát sinh là: nếu muốn thực thi một phương thức của giao diện, nhất định phải tạo một đối tượng proxy động. Lúc này, nếu muốn chuyển đổi proxy động thành thực thể thực sự, chắc chắn sẽ ném ra lỗi chuyển đổi proxy động $proxy.
Cách giải quyết:
Trong tệp cấu hình Spring, thêm thẻ:
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
Ý nghĩa của thẻ này là chuyển đổi proxy động ở tầng dưới từ JDK sang CGLIB. Sau khi chuyển đổi, bất kể có chuyển đổi kiểu hay không, sẽ không còn lỗi nữa. Lưu ý: ngay cả khi sử dụng proxy động của JDK, nếu không xảy ra chuyển đổi, cũng sẽ không có lỗi.
Giá trị của proxy-target-class: false là giá trị mặc định, nghĩa là không chuyển đổi thành thực thể. true thì ngược lại.
Tính lan truyền giao dịch (Transaction Propagation): Hiểu biết: Trong các yêu cầu đặc biệt, một số phương thức có thể gọi lẫn nhau trong quá trình thực thi, liên quan đến nhiều giao dịch. Kiểm soát cách thức thực thi giao dịch chính là tính lan truyền giao dịch. Ít gặp.
Mức cách ly giao dịch:
3.3. Tích hợp Ba thành phần của Khung SSM:
3.3.1. web.xml
Sau khi cấu hình context-param và listener của Spring để tìm kiếm application.xml, cấu hình servlet và servlet-mapping của SpringMVC. Thông qua mapping của URL, chặn tất cả các truy cập vào bộ điều phối (DispatcherServlet), tìm name, sau đó tìm servlet có tên tương ứng, rồi tìm class tương ứng của nó, tức là bộ điều phối. Cần cấu hình thuộc tính load-on-startup là 1 để khởi tạo chủ động bộ điều phối. Đồng thời, cấu hình thẻ init-param để chỉ định tệp SpringMVC.xml nằm trong thư mục src.
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>ContextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
3.3.2. applicationContext-mybatis.xml
Tại đây, cấu hình quét chú thích, nguồn dữ liệu, factory SqlSessionFactory, và quản lý MyBatis. Thêm khía cạnh AOP và giao dịch TX theo nhu cầu.
Sau khi cấu hình url-pattern từ *.do thành /*, việc viết RequestMapping trở nên đơn giản hơn. Tuy nhiên, nó cũng chặn các tài nguyên tĩnh của yêu cầu. Khi trả về máy khách và yêu cầu lại, đường dẫn đã thay đổi. Lúc này, cần cấu hình tài nguyên tĩnh trong SpringMVC.xml.
(1)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Lưu ý: Trong tệp cấu hình Spring, chỉ quét tầng service, không quét tầng controller -->
<context:component-scan base-package="com.bjsxt.service.impl"/>
<context:property-placeholder location="classpath:db.properties"/>
<!-- Cấu hình nguồn dữ liệu -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- Cấu hình factory SqlSessionFactory -->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- Cấu hình mapperLocations để chỉ định vị trí các tệp Mapper XML -->
<property name="mapperLocations" value="classpath:com/bjsxt/mapper/*.xml"/>
</bean>
<!-- Spring quản lý MyBatis -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.bjsxt.mapper"/>
<property name="sqlSessionFactoryBeanName" value="factory"/>
</bean>
<bean id="addRoleMenuAdvice" class="com.bjsxt.advice.AddRoleMenuAdvice"/>
<bean id="delRoleMenuAdvice" class="com.bjsxt.advice.DelRoleMenuAdvice"/>
<aop:config>
<aop:pointcut expression="execution(* com.bjsxt.service.impl.RolesServiceImpl.addRoles(..))" id="pointcutAddRoleMenu"/>
<aop:pointcut expression="execution(* com.bjsxt.service.impl.RolesServiceImpl.delRole(..))" id="pointcutDelRoleMenu"/>
<aop:advisor advice-ref="addRoleMenuAdvice" pointcut-ref="pointcutAddRoleMenu"/>
<aop:advisor advice-ref="delRoleMenuAdvice" pointcut-ref="pointcutDelRoleMenu"/>
</aop:config>
<bean id="logsAdvice" class="com.bjsxt.advice.LogsAdvice"/>
<bean id="loginLogsAdvice" class="com.bjsxt.advice.LoginLogsAdvice"/>
<bean id="addCustomerAdvice" class="com.bjsxt.advice.AddCustomerAdvice"/>
<bean id="delCustomerAdvice" class="com.bjsxt.advice.DelCustomerAdvice"/>
<!-- <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> -->
<aop:config>
<aop:pointcut expression="execution(* com.bjsxt.service.impl.CustomersServiceImpl.selectById(..))"id="pointcut2"/>
<aop:pointcut expression="execution(* com.bjsxt.service.impl.CustomersServiceImpl.addCustomer(..))"id="pointcut3"/>
<aop:pointcut expression="execution(* com.bjsxt.service.impl.CustomersServiceImpl.deleteCustomer(..))" id="pointcut4"/>
<aop:advisor advice-ref="loginLogsAdvice" pointcut-ref="pointcut2"/>
<aop:advisor advice-ref="addCustomerAdvice" pointcut-ref="pointcut3"/>
<aop:advisor advice-ref="delCustomerAdvice" pointcut-ref="pointcut4"/>
</aop:config>
</beans>
(2)
<!-- Cấu hình lập trình đối tượng khía cạnh, thông báo sau -->
<bean id="addRoleMenuAdvice" class="com.bjsxt.advice.AddRoleMenuAdvice"/>
<bean id="delRoleMenuAdvice" class="com.bjsxt.advice.DelRoleMenuAdvice"/>
<aop:config>
<aop:pointcut expression="execution(* com.bjsxt.service.impl.RolesServiceImpl.addRoles(..))" id="mypoint"/>
<aop:pointcut expression="execution(* com.bjsxt.service.impl.RolesServiceImpl.delRole(..))" id="mypointDelRM"/>
<aop:advisor advice-ref="addRoleMenuAdvice" pointcut-ref="mypoint"/>
<aop:advisor advice-ref="delRoleMenuAdvice" pointcut-ref="mypointDelRM"/>
</aop:config>
<bean id="logsAdvice" class="com.bjsxt.advice.LogsAdvice"/>
<bean id="loginlogsAdvice" class="com.bjsxt.advice.LoginlogsAdvice"/>
<bean id="addCusAdvice" class="com.bjsxt.advice.AddCusAdvice"/>
<bean id="delCusAdvice" class="com.bjsxt.advice.DelCusAdvice"/>
<aop:config>
<aop:pointcut expression="execution(* com.bjsxt.service.impl.CustomersServiceImpl.selById(..))"id="mypoint2"/>
<aop:pointcut expression="execution(* com.bjsxt.service.impl.CustomersServiceImpl.addCus(..))"id="mypoint3"/>
<aop:pointcut expression="execution(*com.bjsxt.service.impl.CustomersServiceImpl.delCus(..))" id="mypoint4"/>
<aop:advisor advice-ref="loginlogsAdvice" pointcut-ref="mypoint2"/>
<aop:advisor advice-ref="addCusAdvice" pointcut-ref="mypoint3"/>
<aop:advisor advice-ref="delCusAdvice" pointcut-ref="mypoint4"/>
</aop:config>
3.3.3. springmvc.xml
Cấu hình thẻ quét chú thích cho controller và mvc driver để hỗ trợ quét chú thích.
Khi truy cập tài nguyên tĩnh của trang web, cần cấu hình mvc:resources.
Về cơ bản, cấu hình cơ bản bao gồm quét chú thích, driver hỗ trợ quét chú thích và cấu hình truy cập tài nguyên tĩnh.
<!-- Cấu hình truy cập tài nguyên tĩnh -->
<mvc:resources location="/" mapping="/**"/>
Ba cấu hình còn lại được cấu hình theo nhu cầu.
Trình phân giải tùy chỉnh:
<!-- Cấu hình trình phân giải tùy chỉnh -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean><br><br>
Bộ lọc (Filter):
Ví dụ: Xử lý lỗi mã hóa tiếng Trung. SpringMVC đã đóng gói sẵn lớp bộ lọc. Chỉ cần cấu hình trong web.xml.
Giá trị của param-name không thể tùy ý đặt.
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
Trình chặn (Interceptor):
<!-- Cấu hình trình chặn -->
<!-- Cách 1: Áp dụng cho tất cả các phương thức -->
<mvc:interceptors>
<bean id="myInterceptor" class="com.bjsxt.interceptor.MyInterceptor"/>
<bean id="myInterceptor2" class="com.bjsxt.interceptor.MyInterceptor2"/>
</mvc:interceptors>
<context:component-scan base-package="com.bjsxt.controller"/>
<mvc:annotation-driven/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:resources location="/" mapping="/**"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/demo1"/>
<bean id="myInterceptor" class="com.bjsxt.interceptor.MyInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/demo2"/>
<bean id="myInterceptor2" class="com.bjsxt.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
1.3.4. Bước 4: Logic Nghiệp vụ và Triển khai
1.3.4.1. Ghi nhật ký AOP
Các công nghệ được sử dụng trong triển khai, cài đặt, cấu hình và sử dụng: ghi nhật ký nghiệp vụ: ghi nhật ký tùy chỉnh, triển khai bằng chú thích.
Định nghĩa điểm cắt ở đây:
@Pointcut("execution (* org.rentcar.controller.*.*(..))")
public void controllerAspect() {
}
/**
* Thông báo sau khi thực thi, dùng để chặn tầng Controller ghi lại thao tác của người dùng
* @param joinPoint Điểm cắt
* joinPoint có thể lấy danh sách tham số của điểm kết nối, đối tượng phương thức, đối tượng mục tiêu, bản thân đối tượng proxy.
*/
@After("controllerAspect()")
public void doAfter(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
// Đọc người dùng từ session // Sẽ triển khai sau
User user = (User) session.getAttribute("user");
// IP yêu cầu
String ip = request.getRemoteAddr();
// Lấy mô tả phương thức của tầng controller
public static String getServiceMethodDescription(JoinPoint joinPoint) throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == arguments.length) {
description = method.getAnnotation(SystemLog.class).description();
break;
}
}
}
return description;
}
}
1.3.4.2. Quyền truy cập RBAC (Role-Based Access Control)
Ý tưởng: Liên quan đến trình chặn. Khi truy cập, trước tiên đi vào trình chặn. Ba bước kiểm tra:
String uri = req.getRequestURI(); // Ví dụ: /sxt/login
Hai điểm khó hiểu nhất của RBAC: RBAC đơn giản nhất dựa trên URL cũng cần sáu bảng, ngoài ra còn có user, role, url, menu.
Truy vấn đệ quy của menu menu: Sử dụng đệ quy trong mã. Tạo lớp thực thể userMenu với bốn thuộc tính: id, name, pid (id của nút cha), List<userMenu> children.
List<UserMenu> list = menuMapper.showMenu(rid, pid);
// System.out.println(list.get(0));
for (UserMenu userMenu : list) {
List<UserMenu> menu = menuMapper.showMenu(rid, userMenu.getId());
userMenu.setChildren(menu);
}
return list;
Trong đó, rid là id của vai trò, pid là id của nút cha trong menu.
select * from menu where id in (select mid from role_menu where rid=#{0}) and pid=#{1}
Mối quan hệ nhiều-nhiều giữa bảng vai trò và bảng menu: Khi truy vấn, trước tiên theo id vai trò để lấy ra id menu tương ứng của vai trò đó, sau đó theo id menu và pid để lấy ra tất cả các menu cha hiện tại, sau đó sử dụng vòng lặp để lấy ra các menu con của mỗi menu cha (là một tập hợp), sau đó sử dụng đệ quy để truy vấn các menu con của mỗi menu con.
Thông thường có hai cấp độ thư mục.
Vai trò thực tế của RBAC trong dự án:
2. Dự án Phân tán và Các Công nghệ Liên quan
2.1. Quy trình Giải thích Dự án Thương mại Điện tử
2.1.1. Xây dựng Dự án
Kiến trúc hướng dịch vụ (SOA - Service-Oriented Architecture). Có quá nhiều dịch vụ, chia các dịch vụ cụ thể thành nhiều dự án. Các dự án dịch vụ được chia này được triển khai trên nhiều máy chủ, tổng thể chia thành hai module lớn là front-end và back-end.
Quản lý dự án bằng Maven. Framework front-end là Easy-UI.
Tạo ego-parent.
Số lượng bảng trong thiết kế cơ sở dữ liệu không phải do tôi tham gia thiết kế.
Tạo ego-pojo bằng kỹ thuật tạo mã ngược (reverse engineering).
Trong quá trình viết, tạo module ego-commons để đặt các lớp chung.
Chúng tôi sử dụng phát triển phân tán Dubbo. Tạo ego-service để viết giao diện dịch vụ. Tạo ego-dubbo để viết lớp triển khai dịch vụ và xuất bản dịch vụ lên trung tâm đăng ký.
Các module còn lại như ego-manager, ego-portal, v.v. đều là người tiêu dùng dịch vụ.
Phát triển phân tán của dự án ego:
Ở đâu thể hiện phát triển phân tán? Ở đâu thể hiện tư tưởng SOA?
Trả lời: SOA chia toàn bộ dự án thành nhiều module theo yêu cầu chức năng cụ thể, xuất bản dịch vụ trên một máy chủ riêng biệt, thể hiện tư tưởng kiến trúc hướng dịch vụ của SOA. Còn việc triển khai dự án, tức là người tiêu dùng dịch vụ, trên các máy chủ khác nhau, rõ ràng là Dubbo đang quản lý dịch vụ, thể hiện tư tưởng phát triển phân tán. Dự án có thể được triển khai trên nhiều máy chủ, nhưng các dự án này yêu cầu giống hệt nhau. Lúc này, cần sử dụng Nginx để proxy máy chủ, cân bằng tải, để tăng hiệu quả truy cập và giảm áp lực cho máy chủ. Điều này thể hiện cụm.
Cân bằng tải Nginx: Mở cổng 80. Trong thư mục cài đặt Nginx /conf/nginx.conf, cấu hình ba phần liên tiếp:
| upstream trong thẻ server{} | server { listen 80; server_name test.ego.com; location / { proxy_pass http://test.ego.com; } } |
|---|---|
| upstream test.ego.com { server 192.168.26.10 weight=2; server 192.168.26.128 weight=3; server 192.168.26.138 weight=2; ... } |
server_name phải giống với tên trong upstream. proxy_pass là đường dẫn truy cập, upstream là đường dẫn proxy.
Trong C:\Windows\System32\drivers\etc\hosts, cấu hình ánh xạ IP và tên miền.
Lần đầu tiên thực hiện cân bằng tải, cần thay đổi biến môi trường của Windows.
192.168.26.148 test.ego.com: Phần trước là IP của Nginx, phần sau là đường dẫn truy cập.
Xây dựng dự án bằng Maven: Thêm phụ thuộc vào pom.xml.
| Nhà cung cấp dịch vụ: | Người tiêu dùng dịch vụ: |
|---|---|
| ego-parent ego-service ego-dubbo ego-pojo ego-commons |
ego-manager --> Quản lý back-end ---- 8080 pom.xml ego-item --> Lưu trữ thông tin sản phẩm ---- 8081 -- Lưu trữ thông tin chi tiết sản phẩm vào Redis ego-portal --> Trang front-end ---- 8082 ego-search --> Tìm kiếm sản phẩm - Solr --- 8083 -- Xây dựng Solr, lưu trữ thông tin sản phẩm vào Solr ego-passport -- Đăng nhập một lần ------ 8084 ego-cart ---- Giỏ hàng --- 8085 -- Lưu trữ thông tin giỏ hàng vào Redis ego-order --- Đơn hàng ---- 8086 ego-pay --> Trực tiếp viết vào ego-order |
2.1.2. Chức năng Cụ thể - Triển khai Module Giỏ hàng
Tôi chủ yếu phụ trách module giỏ hàng, đồng thời cũng có hiểu biết nhất định về các module khác.
Triển khai giỏ hàng:
Cách triển khai:
2.1.3. Đăng nhập một lần (Single Sign-On - SSO)
Trong dự án phân tán, vì có các máy chủ khác nhau, cần có SSO. Thông tin người dùng được lưu trữ trong Redis. Thêm trình chặn. Khi truy cập mà chưa đăng nhập, sẽ trực tiếp chuyển hướng đến trang đăng nhập. Ý tưởng triển khai: key = user:UUID, UUID được lưu trữ trong cookie và truyền về back-end để kiểm tra. Thêm: so sánh người dùng được truyền từ front-end với cơ sở dữ liệu. Nếu tồn tại, tạo UUID, lưu trữ thông tin người dùng vào Redis, đồng thời chuyển hướng đến trang trước đó.
Tại sao cần làm vậy? Nhiều dịch vụ, truy cập khác domain. Thông tin người dùng được lưu trữ trong Redis. Trên các trang dịch vụ khác, thêm trình chặn. Nếu người dùng chưa đăng nhập, sẽ chuyển hướng đến trang đăng nhập.
Lưu ý: Việc lưu trữ trong Redis yêu cầu sử dụng JedisPool và lớp triển khai của nó để thực hiện các thao tác set, get, exist trên Redis. Đồng thời, thêm các lớp tiện ích cookie và json vào ego-common.
2.1.4. Ôn tập Cài đặt Các Thành phần Trung gian Phổ biến
2.1.4.1. vsftp - Proxy Nginx
Giao thức FTP: Giao thức truyền tệp văn bản. An toàn hơn, hiệu quả tải lên tệp nhanh hơn, tải lên nhiều tệp cùng lúc, chỉ định người dùng, chỉ có thể thấy nội dung của đường dẫn được chỉ định. Sử dụng giao thức TCP/IP. Nhược điểm là cần cài đặt máy chủ FTP, tệp trên máy chủ FTP cần được tải xuống mới có thể sử dụng. So với giao thức truyền siêu văn bản HTTP, giao thức HTTP là giao thức mạng được sử dụng phổ biến nhất trên Internet. Vsftp có thể coi là một thành phần nhỏ của Linux.
Tại sao sử dụng máy chủ FTP làm máy chủ hình ảnh?
Quản lý thống nhất tài nguyên tệp trong dự án phân tán. Đảm bảo đường dẫn là duy nhất!
Sử dụng kỹ thuật Java FTPClient để tải ảnh lên máy chủ vsftp. Cần thêm phụ thuộc vào pom.xml.
Vsftpd được truy cập qua giao thức FTP! Cổng của giao thức FTP là 21. FileZilla: sftp: cổng mặc định là 22.
Cài đặt: Đồng thời sử dụng Nginx để proxy truy cập Vsftp, sử dụng HTTP để truy cập.
Cài đặt dễ dàng:
[root@bogon ~]# yum -y install vsftpd
-y: nghĩa là yes
Sau khi cài đặt, có tệp /etc/vsftpd/vsftpd.conf là tệp cấu hình của vsftpd.
/etc/vsftpd/vsftpd.conf: tắt truy cập ẩn danh.
Khởi động lại dịch vụ ftp: service vsftpd restart
Truy cập: ftp://192.168.26.30/gaoyy.jpg
Proxy bằng Nginx: Proxy tiến (Forward Proxy): Proxy một đường dẫn, truy cập một máy chủ, do máy khách quyết định. Ví dụ: Nginx proxy máy chủ ảnh vsftp.
Proxy ngược (Reverse Proxy): Proxy một máy chủ khác, và máy chủ này không do máy khách quyết định. Ví dụ: Cảnh sát mạng, cân bằng tải trong dự án thương mại điện tử.
Được viết bằng C: Cần cài đặt môi trường gcc: yum install gcc-c++ -y
Cấu hình trong tệp cấu hình nginx.conf. Khi proxy vsftp: đặt người dùng quyền truy cập, sửa đổi đường dẫn location.
Sau khi sửa đổi tệp cấu hình, cần phải khởi động lại.
2.1.4.2. redis Cluster, Quản lý Cluster bằng Ruby
Cơ sở dữ liệu phi quan hệ, viết bằng C, lưu trữ dữ liệu theo cặp key-value, không cần định nghĩa trước từ điển lưu trữ dữ liệu, lưu trữ trong bộ nhớ, truy cập nhanh. Bộ nhớ đệm --> Có cơ chế lưu trữ bền vững: AOF và RDB.
RedisDesktopManager để quản lý cơ sở dữ liệu Redis.
Cài đặt:
Triển khai và quản lý Cluster:
Trong thực tế, thường sử dụng Redis cluster để lưu trữ dữ liệu. Cài đặt Redis cluster và quản lý Redis cluster bằng Ruby.
Cluster độc lập:
Tích hợp vào Spring: Tích hợp Redis vào dự án nghĩa là để Spring quản lý Redis.
2.1.4.3. Truy vấn Solr
Giới thiệu: Là một máy chủ ứng dụng tìm kiếm độc lập cấp doanh nghiệp, một máy chủ tìm kiếm mã nguồn mở của Apache, thực tế là một dự án Java, được triển khai trong Tomcat!
Chủ yếu dựa trên HTTP và Apache Lucene. Hỗ trợ các giao diện chuẩn, hỗ trợ truy vấn HTTP, XML, JSON. Có thể phân trang, làm nổi bật, quản lý giao diện trực quan.
Tìm kiếm toàn văn dựa trên chỉ mục. Cần xây dựng kho chỉ mục trước. Hiệu quả hơn LIKE, LIKE là truy vấn theo thứ tự và không có chỉ mục. Cải thiện trải nghiệm người dùng.
Nguyên lý:
Kho chỉ mục lưu trữ các trường chỉ mục: Solr có thể hiểu như một cơ sở dữ liệu --> đối tượng document có thể hiểu như một hàng dữ liệu trong bảng --> thuộc tính field có thể hiểu như một trường.
Trong tệp cấu hình schema.xml, cấu hình fieldType làm bộ phân tích từ tiếng Trung và cấu hình fieldName làm trường truy vấn.
Trong dự án ego, để truy vấn chi tiết sản phẩm, cần cấu hình các trường của sản phẩm. Có thể truy vấn theo từng trường, đồng thời có thể cấu hình thuộc tính copyField source để thực hiện truy vấn từ trên nhiều trường.
Solr sẽ phân tách từ khóa tìm kiếm và tìm kiếm nội dung trong chỉ mục đã được xây dựng.
Cài đặt Solr đơn lẻ:
Cần có Tomcat và JDK. Sao chép và giải nén gói Solr, triển khai tệp war đã giải nén lên Tomcat.
Sửa đổi tệp ./start.sh và ./shutdown.sh của Tomcat để chỉ định Tomcat cụ thể. Và sửa đổi đường dẫn kho chỉ mục trong tệp web.xml của Solr.
Khởi động Tomcat, truy cập giao diện quản lý Solr nếu cài đặt thành công.
Đây là nguyên lý cài đặt Solr, cấu hình kho chỉ mục và truy vấn.
Solr cluster cần sự hỗ trợ của ZooKeeper. Vì Tomcat và Solr không có chức năng cluster.
Một leader, hai slave. Mỗi slave quản lý hai Tomcat.
Sao chép Tomcat và sửa đổi cổng --> Sửa đổi tệp ./start.sh và ./shutdown.sh của Tomcat --> Sửa đổi catalina.sh --> Sao chép và sửa đổi web.xml --> Sửa đổi cổng trong solr.xml và tương ứng với Tomcat. Khi kiểm thử, nhất định phải tắt tường lửa và bật ZooKeeper.
Trong dự án ego-search, cần thêm phụ thuộc solr.jar vào pom.xml. Trong tệp cấu hình, cấu hình IP của ZooKeeper cluster.
Quá trình triển khai truy vấn: Nhập từ khóa "điện thoại" vào ô tìm kiếm, nhấp vào tìm kiếm, "điện thoại" sẽ là từ khóa truy vấn trong Solr cluster. Ngoài ra, còn cần lấy page từ front-end, làm cơ sở cho việc phân trang của Solr.
Tạo lớp thực thể để lưu trữ thông tin sản phẩm cần cho trang. Trong lớp triển khai nghiệp vụ, tạo tập hợp này, gán điều kiện truy vấn cho trường truy vấn, truy vấn tất cả các tập hợp sản phẩm phù hợp và lấy dữ liệu nổi bật. Sau đó, lặp qua tập hợp này, so sánh trường nổi bật, lấy tập hợp nổi bật, đưa tất cả các thuộc tính cần cho trang vào lớp thực thể, sau đó đưa vào tập hợp, gán cho bộ chứa cần thiết cho trang và trả về.
2.1.5. MyCAT
MySQL thông qua MyCAT cluster.
MyCAT là một middleware cơ sở dữ liệu được viết bằng ngôn ngữ Java. Nó kết nối ứng dụng và cơ sở dữ liệu để tương tác dữ liệu.
Vai trò của MyCAT: Khi lượng dữ liệu lớn, chia một cơ sở dữ liệu thành nhiều thư viện logic, tương đương với cluster cơ sở dữ liệu.
Cấu hình chính:
Cơ sở dữ liệu Master/Slave:
Master để ghi dữ liệu, Slave để đọc dữ liệu.
Cơ sở dữ liệu Master/Slave. Sửa đổi tệp cấu hình my.cnf, bật chức năng nhật ký và chỉ định server_id. Bởi vì Slave sao chép và đọc nhật ký thông qua các luồng IO và SQL để sao lưu. Sau đó, cần tạo người dùng và đồng thời chỉ định IP của Slave, để Slave có quyền sao lưu và truy cập cơ sở dữ liệu Master.
2.1.6. Cuối cùng về Triển khai Dự án: Đóng gói Dubbo
Sử dụng plugin Assembly của Maven: (1) Thêm phụ thuộc vào pom.xml: thông tin plugin đóng gói và tệp mô tả đóng gói assembly; (2) Tạo thư mục assembly trong thư mục gốc của dự án, và tạo tệp assembly.xml, sao chép thông tin cấu hình; quy định thư mục lib trong tệp tar.gz và quyền truy cập thư mục; (3) Chạy Run as --> Maven Install, sau đó tệp .tar.gz sẽ được tạo trong thư mục target. (4) Tải lên Linux và chạy ./start để khởi động dịch vụ.
2.1.7. Nạp lại (Hot Deployment) (Triển khai Từ xa)
2.2. Số Cổng Các Thành phần Phổ biến
| Tên thành phần | Cổng mặc định |
|---|---|
| mysql | 3306 |
| oracle | 1521 |
| SqlServer | 1433 |
| redis | 6379 (Mặc định có 16384 slot) |
| zookeeper | 2181 (Cổng giao thức truyền thông: 20880) |
| tomcat | 8080 |
| nginx | 80 |
| ftp | 21 |
| sftp | 22 |
| nexus (kho cục bộ) | 8081 |
| svn | 3690 |
| mycat | 8066 |