Tải bản đầy đủ (.docx) (33 trang)

Fetching URLs in Java

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (236.66 KB, 33 trang )


Chương 9: Bộ nhớ cache (The Memory Cache)
Lưu trữ dữ liệu lâu bền đòi hỏi một phương tiện lưu trữ mà vẫn giữ được dữ liệu thông
qua tổn thất điện năng và hệ thống khởi động lại. Hôm nay vừa được lựa chọn là các ổ
đĩa cứng, một thiết bị lưu trữ bao gồm đĩa tròn phủ vật liệu từ tính mà trên đó các dữ liệu
được mã hóa. Các đĩa cứng quay với một tốc độ không đổi trong khi một bộ cảm biến
chuyển động dọc theo bán kính, đọc và viết bit trên đĩa cứng khi chúng đi qua. Đọc hoặc
viết một mảnh dữ liệu cụ thể đòi hỏi một đĩa tìm kiếm để xác định vị trí các cảm biến ở
bán kính thích hợp và chờ cho đĩa xoay cho đến khi dữ liệu mong muốn là bên dưới. Ổ
đĩa cứng nhanh cách đáng kinh ngạc, tất cả thứ được xem xét, nhưng đối với các ứng
dụng web, tìm kiếm đĩa có thể tốn kém. Lấy một thực thể từ các kho dữ liệu bằng cách
quan trọng có thể mất thời gian vào thứ tự của hàng chục mili giây.
Hầu hết các ứng dụng web hiệu suất cao sử dụng một bộ nhớ cache. Một bộ nhớ cache bộ
nhớ sử dụng một phương tiện lưu trữ ổn định, thường là bộ nhớ RAM của máy cho cache
rất nhanh chóng đọc và viết truy cập vào các giá trị. Một bộ nhớ cache phân phối cung
cấp khả năng mở rộng, lưu trữ tạm thời phù hợp cho các hệ thống phân phối, vì vậy nhiều
quá trình có thể truy cập cùng một dữ liệu. Vì bộ nhớ là dễ bay hơi, nó sẽ bị xóa trong
một utage, cache là không hữu ích để lưu trữ lâu dài, hoặc thậm chí lưu trữ chính ngắn
hạn cho các dữ liệu quan trọng. Nhưng đó là tuyệt vời như là một hệ thống thứ cấp cho
truy cập dữ liệu nhanh cũng giữ ở những nơi khác, chẳng hạn như kho dữ liệu. Nó cũng
đủ như là bộ nhớ tốc độ cao trên toàn cầu đối với một số mục đích sử dụng.
App Engine dịch vụ phân phối bộ nhớ cache, được biết đến như memcache trong danh dự
của các hệ thống memcached ban đầu mà nó giống, cửa hàng cặp khóa-giá trị. Bạn có thể
thiết lập một giá trị với một khóa, và nhận được các giá trị đã cho khóa. Một giá trị có thể
lên đến một megabyte trong kích thước. Một khóa lên đến 250 byte, và các API chấp
nhận các phím lớn hơn và sử dụng một thuật toán băm để chuyển chúng đến 250 byte.


Thiết lập một giá trị duy nhất trong bộ nhớ cache là nguyên tử: khóa hoặc được các giá trị
mới hoặc giữ lại một tuổi (hoặc vẫn bỏ thiết lập). Các memcache không hỗ trợ các giao
dịch như kho dữ liệu không. Nếu bạn nhận được một giá trị, sau đó cố gắng thiết lập một


giá trị dựa trên những gì bạn có, giá trị đầu tiên có thể đã thay đổi kể từ đó là cường điệu.
App Engine memcache bao gồm khả năng tăng và giảm giá trị giá trị số như là một hoạt
động nguyên tử.
Một cách phổ biến để sử dụng memcache với kho dữ liệu là để cache các tổ chức kho dữ
liệu bằng khoá của chúng. Khi bạn muốn lấy một thực thể theo khóa, đầu tiên bạn kiểm
tra memcache cho một giá trị với khóa đó, và sử dụng nó nếu tìm thấy (được biết đến như
một lần truy cập cache). Nếu nó không phải trong memcache (cache), bạn lấy nó từ kho
dữ liệu, sau đó đặt nó trong memcache thực hiện như vậy để truy cập sẽ tìm thấy chúng ở
đó. Với chi phí của một số lượng nhỏ của chi phí trong quá trình đầu tiên tìm nạp, lộ trình
kế tiếp trở nên nhanh hơn nhiều.
Nếu thực thể thay đổi trong các kho dữ liệu, bạn có thể cố gắng để cập nhật các
memcache khi thực thể được cập nhật trong kho dữ liệu, vì vậy yêu cầu tiếp theo có thể
tiếp tục đi vào bộ nhớ cache nhưng xem dữ liệu mới. Điều này chủ yếu là các công trình,
nhưng nó có hai vấn đề nhỏ. Đối với một, có thể là bản cập nhật memcache sẽ thất bại
ngay cả khi cập nhật kho dữ liệu thành công, để lại dữ liệu cũ trong bộ nhớ cache. Ngoài
ra, nếu hai quá trình cập nhật các thực thể kho dữ liệu tương tự, thì sau đó cập nhật các
memcache, kho dữ liệu sẽ có dữ liệu chính xác (nhờ các trao đổi kho dữ liệu), nhưng cập
nhật memcache sẽ có giá trị của bất cứ bản cập nhật sau cùng. Vì khả năng này, nó tốt
hơn là xóa các khóa memcache khi thay đổi kho dữ liệu, và để cho các lần tiếp đọc điền
bộ nhớ cache với một giá trị hiện tại. Đương nhiên, việc xóa cũng có thể thất bại.
Vì không có cách nào để cập nhật cả hai kho dữ liệu và memcache trong một duy nhất
trao đổi, không có cách nào để tránh khả năng rằng bộ nhớ cache có thể chứa dữ liệu cũ.
Để giảm thiểu tối đa thời gian mà các memcache sẽ có một giá trị cũ, bạn có thể cung cấp
cho các giá trị thời gian hết hạn khi bạn thiết lập nó. Khi thời gian hết hạn trôi qua, bộ


nhớ cache unsets khóa, và tiếp theo là một kết quả đọc trong một cache và gây ra một
tươi lấy từ kho dữ liệu.
Tất nhiên, mô hình bộ nhớ đệm này làm việc cho hơn thực thể chỉ kho dữ liệu. Bạn có thể
sử dụng nó cho các truy vấn kho dữ liệu, các cuộc gọi dịch vụ web được thực hiện với

URL Fetch, tính toán tốn kém, hoặc bất kỳ dữ liệu khác có thể được thay thế bằng một
hoạt động chậm, nơi mà lợi ích của việc truy cập nhanh vượt khả năng của staleness.
Điều này là rất thường xảy ra với các ứng dụng web mà cách tốt nhất là để cache linh
hoạt. Xem xét thông qua ứng dụng của bạn cho cơ hội để làm cho sự cân bằng này, và
thực hiện bộ nhớ đệm khi cùng giá trị là cần thiết một số tùy ý lần, đặc biệt là nếu số đó
tăng với giao thông. nội dung trang web như một bài viết trên một trang web tin tức
thường rơi vào thể loại này. Caching tăng tốc độ yêu cầu và tiết kiệm thời gian CPU, và
làm giảm khả năng của kho dữ liệu đọc thất bại ảnh hưởng đến ứng dụng của bạn.
Các API cho dịch vụ memcached là đơn giản. Chúng ta sẽ nhìn vào giao diện Python đầu
tiên, sau đó giao diện Java, với trọng tâm về bộ nhớ đệm đơn vị kho dữ liệu.
Các Java Memcached API (The Java Memcache API)
Cũng như các dịch vụ khác, App Engine bao gồm hai giao diện Java với dịch vụ
memcache. Một là một giao diện độc quyền cung cấp truy cập trực tiếp đến các tính năng
của dịch vụ. Mặt khác là một thực hiện JCache, một tiêu chuẩn giao diện của JSR 107 đề
xuất.
Theo bài viết này, JSR 107 không phải là một tiêu chuẩn được phê duyệt, và cách khuyến
khích để sử dụng nó trên App Engine là thay đổi liên tục. Vì vậy, bây giờ, chúng ta sẽ chỉ
xem xét các giao diện độc quyền. Để biết thêm thông tin về cách sử dụng giao diện
JCache với App Engine, tham khảo tài liệu App Engine.
Các dịch vụ Java memcache API cho phép sử dụng của bất kỳ đối tượng serializable như
là khóa hoặc giá trị của một cặp khóa-giá trị được lưu trữ trong bộ nhớ cache. Phím mà
tuần tự dạng là lớn hơn 250 byte được băm đến 250 byte. Các giá trị có thể lên đến một
megabyte trong kích thước.


Trong nhiều trường hợp, bạn có thể làm cho một lớp dữ liệu JPA serializable chỉ đơn giản
bằng cách khai báo rằng các lớp thực hiện Serializable, không có những thay đổi khác.
Nếu bạn đang sử dụng các API kho dữ liệu cấp thấp, các lớp thực thể và tất cả các lớp giá
trị thuộc tính thực thi giao diện Serializable
Với dịch vụ App Engine memcache Java API, bạn tương tác với các dịch vụ sử dụng một

đối

tượng

MemcacheService,



bạn

nhận

được

từ

MemcacheServiceFactory.getMemcacheService().Các thao tác cơ bản có sẵn như là
phương thức: MemcacheService: put(), get(), and delete().
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
// ...
List<String> headlines;
MemcacheService memcache = MemcacheServiceFactory.getMemcacheService();
memcache.put("headlines", headlines);
headlines = (List<String>) memcache.get("headlines");
memcache.delete("headlines");
Phương thức put () nhận khóa và giá trị, một trong đó có thể là đối tượng serializable.
Được gọi là chỉ với hai đối số này, giá trị mới được lưu trữ không có thời gian hết hạn, và
cả hai sẽ tạo ra một giá trị mới với các phím được hoặc thay thế sẵn có, nếu có.
Để thiết lập một giá trị với thời gian hết hạn, bạn put() một đối tượng Expiration như là

đối số thứ ba. Bạn tạo ra giá trị này với một phương thức tĩnh trong lớp Expiration.
import com.google.appengine.api.memcache.Expiration;
// ...
memcache.put("headlines", headlines,Expiration.byDeltaSeconds(300));


Bạn có thể sử dụng các phương pháp thức thay thức byDeltaMillis(int) cho thời gian hết
hạn trong milli-giây, hoặc onDate(java.util.Date) cho thời gian hết hạn vào một thời điểm
tuyệt đối trong tương lai.
Để thay đổi cách put () với giá trị hiện tại với các khóa, cung cấp một giá trị
MemcacheService.SetPolicy liệt kê như là đối số thứ tư. Bạn có thể sử dụng null cho đối
số thứ ba nếu bạn không muốn thiết lập thời hạn.
import com.google.appengine.api.memcache.MemcacheService.SetPolicy;
// ...
memcache.put("headlines", headlines, null,
SetPolicy.ADD_ONLY_IF_NOT_PRESENT);
Ba

lựa

chọn

thiết

lập

chính

sách




SET_ALWAYS

(mặc

định),

ADD_ONLY_IF_NOT_PRESENT (chỉ tạo ra, không ghi đè lên), và REPLACE CHỈ
NẾU HIỆN TẠI (chỉ ghi đè lên, không tạo ra).
Bạn có thể kiểm tra xem bộ nhớ cache contains một giá trị với một khóa đưa ra mà không
lấy giá trị bằng cách sử dụng Phương thức contains (). Phương thức này có một khóa như
là đối số của nó, và trả về đúng hay sai
boolean headlinesAreCached = memcache.contains("headlines");
Để xóa một giá trị cho một khóa nào đó, bạn gọi phương pháp delete () với khóa như là
đối số của nó. Bạn có thể chỉ định một số lượng thời gian mà các quá trình không được
phép readd khóa, như một số nguyên dài mili giây trong đối số thứ hai. Điều này rất hữu
ích cho việc đảm bảo rằng nhiều quy trình người làm việc đồng thời làm việc với cùng
một dữ liệu không vô tình lùi lại bộ nhớ cache xóa với một bản cập nhật
memcache.delete("tempnode91512", 5);
API cấp thấp bao gồm các phương thức để thiết lập, lấy, hoặc xóa nhiều mục trong
một lời gọi đợt duy nhất. Điều này là nhanh hơn so với làm một cuộc gọi dịch vụ cho mỗi


mục. Tuy nhiên, tổng kích thước của các lời gọi và phản hồi của nó được giới hạn trong
một megabyte.
Phương thức putAll () lưu nhiều giá trị trong một lô. Nó chấp nhận một Map Object> các khóa và giá trị như là đối số đầu tiên của nó. Nó thể chấp nhận Expiration và
giá trị SetPolicy, như đối tác của đơn hàng của mình.
import java.util.HashMap;

import java.util.Map;
// ...
Map<Object, Object> articleSummaries = new HashMap<Object, Object>();
articleSummaries.put("article00174", "...");
articleSummaries.put("article05234", "...");
articleSummaries.put("article15820", "...");
memcache.putAll(articleSummaries);
Phương thức GetAll () trả về nhiều mục trong một lô. Nó chấp nhận một Collection
<Object> các khóa như là đối số của nó, và trả về một Map <Object, Object> các khóa và
giá trị cho tất cả các khóa được cung cấp đã được tìm thấy trong bộ nhớ cache.
import java.util.List;
// ...
List<Object> articleSummaryKeys = Arrays.<Object>asList(
"article00174",
"article05234",
"article15820");
Map<Object, Object> articleSummaries = memcache.getAll(articleSummaryKeys);
Phương thức deleteAll () xóa nhiều mục trong một lô. Nó chấp nhận một Collection các
khóa như là đối số của nó. Nó cũng thể chấp nhận một thời gian khóa đọc trong mili giây
như là đối số thứ hai của mình.
memcache.deleteAll(articleSummaryKeys);


Bất kỳ giá trị memcached có thể được lưu trữ trong một không gian tên. Không gian tên
cho phép bạn phân đoạn không gian chính của các loại mà bạn đang lưu trữ, do đó bạn
không phải lo lắng về xung đột chính giữa sử dụng khác nhau của bộ nhớ cache. Để sử
dụng không gian tên trong cấp thấp Java API, bạn thiết lập các không gian tên trên
MemcacheService bằng cách gọi phương thức của nó setNamespace (). Tất cả các hoạt
động tiếp theo sử dụng không gian tên được đưa ra khi thao tác các giá trị.
memcache.setNamespace("News");

memcache.put("headlines", headlines);
memcache.setNamespace("User");
memcache.put("headlines", userHeadlines);
// Get User:"headlines".
userHeadlines = (List<String>) memcache.get("headlines");
/ Get News:"headlines".
memcache.setNamespace("News");
headlines = (List<String>) memcache.get("headlines");
Nếu một giá trị memcache là một số nguyên (int hay long), bạn có thể tăng hoặc giảm số
lượng các nguyên tử-có nghĩa là, không can thiệp với các quá trình khác làm điều tương
tự bằng cách sử dụng Phương thức increment (). Phương pháp này mất khóa và số tiền
thặng dư (mà có thể làm xấu đi). Nó trả về các giá trị mới (Long), hoặc null nếu không có
giá trị đã được lưu trữ với khóa.
memcache.put("work_done", 0);
// ...
Long workDone = memcache.increment("work_done", 1);
Các Java API cấp thấp cung cấp quyền truy cập vào giá trị hơn API JCache. Phương thức
getStatistics () trả về một đ ối tượng thống kê số liệu, với một phương thức cho từng giá
trị có sẵn.
import com.google.appengine.api.memcache.Stats;
// ...


Stats stats = memcache.getStatistics();
int ageOfOldestItemMillis = stats.getMaxTimeWithoutAccess();
Giá trị sẵn bao gồm:
getHitCount()
Đếm số lượng truy cập bộ nhớ cache.
getMissCount()
Đếm số lượng bộ nhớ cache.

getItemCount()
Số lượng các mục hiện có trong bộ nhớ cache.
getTotalItemBytes()
Tổng kích thước của mục hiện có trong bộ nhớ cache.
getBytesReturnedForHits()
Tổng số byte trả về để đáp ứng với số truy cập bộ nhớ cache, bao gồm các khóa và các
giá trị.
getMaxTimeWithoutAccess()
Thời gian của các mục gần đây nhất truy cập vào bộ nhớ cache, chỉ trong vài giây.
Không có cách nào để thiết lập một cách rõ ràng các giá trị memcache. Chúng được tích
lũy qua thời gian hoạt động của dịch vụ, và do đó chủ yếu là hữu ích cho các so sánh
tương đối trong thời gian ngắn ngủi của thời gian.
Theo mặc định, nếu dịch vụ memcache là không có hoặc có một lỗi khi truy cập các dịch
vụ, các cấp thấp API và API vận hành JCache như khóa không tồn tại. Cố gắng để đưa
các giá trị mới không âm thầm; các phương thức bốn đối số put () sẽ trả về false trong
trường hợp này, nếu như put thất bại do các chính sách đề ra. Những nỗ lực để có được
giá trị này sẽ hoạt động như bộ nhớ cache.
Ở cấp thấp Java API, bạn có thể thay đổi hoạt động này bằng cách cài đặt một trình xử lý
lỗi thay thế. Phương thức setErrorHandler () của MemcacheService mất một đối tượng
mà thực hiện các giao diện ErrorHandler. Hai triển khai như vậy được cung cấp:
LogAndContinueErrorHandler



StrictErrorHandler.

Mặc

định




LogAndContinueErrorHandler với mức độ ghi của nó thiết lập để FINE (các "gỡ rối" cấp


Administration Console). StrictErrorHandler ném MemcacheServiceException cho tất cả
các lỗi dịch vụ tạm thời.
import com.google.appengine.api.memcache.StrictErrorHandler;
// ...
memcache.setErrorHandler(new StrictErrorHandler());
Xử lý lỗi có thể có đáp lại tùy chỉnh cho các giá trị không hợp lệ và lỗi dịch vụ. Các loại
ngoại lệ ném ra bởi vận hành API như bình thường.

Chương 10: Tìm nạp URL và Tài nguyên Web (Fetching URLs in Java)
Một ứng dụng App Engine có thể kết nối đến các trang web khác trên Internet để lấy dữ
liệu và giao tiếp với các dịch vụ web. Nó làm điều này không phải bằng cách mở một kết
nối đến máy chủ từ xa từ máy chủ ứng dụng, nhưng thông qua một dịch vụ mở rộng được
gọi là dịch vụ URL Fetch. Nó có thể chịu đựng việc duy trì các kết nối từ các máy chủ
ứng dụng, và đảm bảo rằng tìm nạp tài nguyên thực hiện tốt bất kể như thế nào bất cứ xử
lý yêu cầu được Tìm kiếm nguồn cùng một lúc. Cũng như với các bộ phận khác của cơ sở
hạ tầng App Engine, URL Fetch dịch vụ được sử dụng bởi các ứng dụng khác của Google
để nạp các trang web.
Dịch vụ hỗ trợ Tìm kiếm URL bằng cách sử dụng giao thức HTTP, và sử dụng HTTP với
SSL (HTTPS). Các phương pháp khác đôi khi kết hợp với URL (như FTP) không được
hỗ trợ. Lưu ý rằng với các kết nối HTTPS, các dịch vụ không thể xác thực điểm đến của
các kết nối, vì không có chuỗi chứng chỉ tin tưởng. Dịch vụ chấp nhận tất cả các chứng
chỉ. Điều này có nghĩa các giao thức kết nối tự nó không thể bảo vệ chống lại "man-inthe-middle" tấn công, mặc dù giao thông vẫn được mã hóa.
Vì URL Fetch dịch vụ dựa trên cơ sở hạ tầng của Google, các dịch vụ thừa kế một vài
hạn chế đã được đưa ra trong các thiết kế ban đầu của các proxy HTTP cơ bản. Dịch vụ
hỗ trợ trong năm hành động HTTP thông thường nhất GET, POST, PUT, HEAD, và

DELETE) nhưng không cho phép người khác hoặc sử dụng một hành động không chuẩn.


Ngoài ra, nó chỉ có thể kết nối với các cổng TCP chuẩn cho từng phương pháp (80 cho
HTTP, và 443 cho HTTPS). Các proxy sử dụng HTTP 1.1 để kết nối với máy chủ từ xa.
Như một phương pháp an toàn chống lại yêu cầu ngẫu nhiên vòng lặp trong một ứng
dụng, dịch vụ URL Fetch không thể lấy URL mà ánh xạ để xử lý yêu cầu tìm nạp. ứng
dụng có thể thực hiện các kết nối với các URL khác của riêng nó, vì vậy yêu cầu các
vòng lặp có thể vẫn còn, nhưng hạn chế này mang một kiểm tra sự minh mẫn đơn giản.
Các yêu cầu đi có thể chứa các thông số URL, một nội dung yêu cầu, và các tiêu đề
HTTP. Một vài tiêu đề không thể được sửa đổi vì lý do an ninh, trong đó chủ yếu có
nghĩa là một ứng dụng không thể đưa ra một yêu cầu sai, chẳng hạn như một yêu cầu mà
header Content-Length không phản ánh chính xác chiều dài nội dung thực tế của nội
dung yêu cầu. Trong những trường hợp này, các dịch vụ sử dụng các giá trị chính xác,
hoặc không bao gồm tiêu đề.
Cả hai môi trường thời gian chạy Python và Java bao gồm giao diện đến các URL Fetch
dịch vụ cạnh tranh với các thường trình thư viện chuẩn. Môi trường Python thay thế các
mô-đun urllib và urllib2 với tương đương workalike sử dụng dịch vụ URL Fetch thay vì
làm cho các kết nối trực tiếp. Tương tự như vậy, môi trường Java thay thế
java.net.URLConnection với một thực hiện dựa trên dịch vụ. Các giao diện chuẩn cho
phép mã nguồn và các thành phần bên thứ ba hiện chức năng trong một ứng dụng App
Engine và vẫn đáp ứng yêu cầu mở rộng quy mô App Engine.
Các giao diện này (và các đối tác của chúng ở mức độ thấp) thực hiện đồng bộ tìm nạp
URL, nơi mà các ứng dụng sẽ đợi cho các máy chủ từ xa để đáp ứng trước khi ontinuing.
Các dịch vụ URL Fetch cũng hỗ trợ một giao diện đồng bộ cho phép các ứng dụng để
kích hoạt lấy yêu cầu, làm các công việc khác, sau đó lấy kết quả khi các yêu cầu đã sẵn
sàng. Điều này có thể làm giảm đáng kể lượng thời gian đồng hồ chi tiêu trong một yêu
cầu mà dựa trên một máy chủ từ xa, và cho phép ứng dụng thực hiện nhiều URL Fetch
kết nối cùng lúc.
Trong chương này, chúng tôi sẽ giới thiệu các giao diện tiêu chuẩn và cấp thấp cho việc

lấy URL đồng bộ Python và Java, cũng như giao diện đồng bộ cho các ứng dụng Python.


Tìm nạp URL trong Java (Fetching URLs in Java)
Thời gian chạy Java bao gồm một thực hiện tuỳ chỉnh của lớp URLConnection trong gói
java.net JRE tiêu chuẩn mà các lời gọi dịch vụ URL Fetch thay vì làm một kết nối socket
trực tiếp. Như với các giao diện tiêu chuẩn khác, bạn có thể sử dụng giao diện này và yên
tâm rằng bạn có thể chuyển ứng dụng của bạn vào nền tảng khác một cách dễ dàng.
Ví dụ 10-3 cho thấy một ví dụ đơn giản của việc sử dụng một phương thức tiện lợi ở lớp
URL, mà lần lượt sử dụng các lớp URLConnection, để lấy nội dung của một trang web.
Phương thức openStream () của đối tượng URL trả về một dòng đầu vào của byte. Như
đã trình bày, bạn có thể sử dụng một InputStreamReader (từ java.io) để xử lý các dòng
byte như là một dòng kí tự. Các lớp BufferedReader làm cho nó dễ dàng để đọc dòng văn
bản từ InputStreamReader.
import java.net.URL;
import java.net.MalformedURLException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
// ...
try {
URL url = new URL(" />InputStream inStream = url.openStream();
InputStreamReader inStreamReader = new InputStreamReader(inStream);
BufferedReader reader = new BufferedReader(inStreamReader);
// ... read characters or lines with reader ...
reader.close();
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {

// ...


}
Lưu ý rằng dịch vụ URL Fetch này đã đệm các phản ứng toàn bộ vào bộ nhớ của ứng
dụng cùng thời điểm bộ ứng dụng bắt đầu đọc. Các ứng dụng đọc dữ liệu phản hồi từ bộ
nhớ, không phải một dòng mạng từ socket hoặc dịch vụ.
Bạn có thể sử dụng các tính năng khác của giao diện URLConnection, miễn là họ hoạt
động trong phạm vi chức năng của dịch vụ API. Đáng chú ý, các URL Fetch dịch vụ
không duy trì một kết nối liên tục với máy chủ từ xa, do đó tính năng yêu cầu một kết nối
như vậy sẽ không làm việc.
Theo mặc định, các dịch vụ URL Fetch đợi đến năm giây cho một phản ứng từ các máy
chủ từ xa. Nếu các máy chủ không đáp ứng đúng hạn, các dịch vụ ném một IOException.
Bạn có thể điều chỉnh thời lượng để chờ đợi bằng cách sử dụng phương thức
setConnectTimeout () của URLConnection. (Phương thức setReadTimeout () có tác dụng
tương tự; các dịch vụ sử dụng lớn hơn trong hai giá trị.) Hạn chót một là từ 1 đến 10 giây.
Khi sử dụng các giao diện URLConnection, dịch vụ URL Fetch sau HTTP chuyển hướng
tự động, lên đến năm lần chuyển hướng liên tiếp.
API cấp thấp cho các dịch vụ URL Fetch cho phép bạn tùy chỉnh một số hành vi của dịch
vụ. Ví dụ 10-4 cho thấy làm thế nào để lấy một URL với API này với các tùy chọn định.
Như đã trình bày, các đối tượng FetchOptions nói với các dịch vụ không theo bất kỳ
chuyển hướng, và để ném một ResponseTooLargeException nếu đáp ứng vượt quá kích
thước tối đa của một megabyte thay vì cắt bỏ các dữ liệu.
import java.net.URL;
import java.net.MalformedURLException;
import com.google.appengine.api.urlfetch.FetchOptions;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.ResponseTooLargeException;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;

// ...
try {


URL url = new URL(" />FetchOptions options = FetchOptions.Builder
.doNotFollowRedirects()
.disallowTruncate();
HTTPRequest request = new HTTPRequest(url, HTTPMethod.GET, options);
URLFetchService service = URLFetchServiceFactory.getURLFetchService();
HTTPResponse response = service.fetch(request);
// ... process response.content ...
} catch (ResponseTooLargeException e) {
// ...
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
Các máy chủ phát triển Java mô phỏng các dịch vụ URL Fetch bằng cách làm cho các kết
nối HTTP trực tiếp từ máy tính của bạn. Bảo đảm để kiểm tra rằng ứng dụng của bạn có
thể truy cập vào ông URL cần thiết khi chạy trên App Engine.
Chương 11: Gửi, nhận thư và thông báo tức thì (Sending and Receiving Mail and
Instant Messages)
ứng dụng App Engine có thể kết nối với thế giới bên ngoài trong ba cách. Phương pháp
đầu tiên chúng tôi đề cập trong Chương 10: một ứng dụng có thể nhận và trả lời các yêu
cầu HTTP, và một ứng dụng có thể bắt đầu yêu cầu HTTP và nhận được phản hồi với
dịch vụ URL Fetch.
Phương pháp thứ hai của giao tiếp kết nối mạng có sẵn cho các ứng dụng là email. Ứng
dụng có thể gửi tin nhắn email bằng cách gọi các dịch vụ Mail với thông điệp dữ liệu và
danh sách người nhận. Ứng dụng cũng có thể nhận tin nhắn email tại bất kỳ đâu của một

số địa chỉ theo dõi bởi App Engine.


Phương pháp thứ ba là thông báo tức thời, đặc biệt là giao thức XMPP. Ứng dụng có thể
tham gia vào một hộp thoại trò chuyện với một người sử dụng của bất kỳ dịch vụ chat
tương thích XMPP, bao gồm Google Talk và bất kỳ máy chủ Jabber. Ứng dụng cũng có
thể sử dụng XMPP để giao tiếp với khách hàng tùy chỉnh thông qua các dịch vụ như vậy.
App Engine không thực hiện như một dịch vụ XMPP của chính nó; thay vào đó, nó kết
nối với cơ sở hạ tầng của Google Talk để tham gia như là một người sử dụng chat.
Một ứng dụng có thể gửi email thông báo cho người sử dụng các sự kiện hệ thống hoặc
các hành động của người sử dụng khác (chẳng hạn như gửi lời mời mạng xã hội), xác
nhận hành động người dùng (như để xác nhận một lệnh), tiếp nối hành động của người sử
dụng lâu dài (như gửi thông báo giao hàng cho một thứ tự), hoặc gửi thông báo hệ thống
để quản trị viên. Các ứng dụng có thể gửi email trên danh nghĩa của chính nó, các quản
trị viên của ứng dụng, hoặc người dùng hiện đã đăng nhập (trong xử lý yêu cầu đó là gửi
email).
Ứng dụng có thể nhận được email gửi đến các địa chỉ cụ thể, chẳng hạn như để cung cấp
một giao diện email để ứng dụng, hoặc đến trung bình hoặc theo dõi các cuộc thảo luận
email. Ứng dụng có thể trả lời email ngay lập tức, hoặc thiết lập công việc gây ra một trả
lời được gửi sau.
Các dịch vụ XMPP có giao diện hữu ích cho trò chyện, chẳng hạn như một công cụ dựa
trên truy vấn trò chuyện. Với một máy khách tùy chỉnh (như một máy khách điện thoại di
động, hoặc Flash trong trình duyệt) và một máy chủ XMPP hoặc chat dịch vụ (như
Google Talk), các ứng dụng có thể sử dụng XMPP để đẩy cập nhật theo thời gian thực
cho máy khách. App Engine không chạy máy chủ XMPP riêng của mình, vì vậy khách
hàng sẽ kết nối với các dịch vụ chat (sử dụng một tài khoản trên dịch vụ đó) để giao tiếp
với các ứng dụng.
Gửi tin nhắn email và trò chuyện cũng tương tự như khi bắt đầu yêu cầu HTTP: ứng dụng
gọi một dịch vụ sử dụng một API, và các dịch vụ hỗ trợ làm các kết nối từ xa và quản lý
các giao thức thích hợp. Không giống như các dịch vụ URL Fetch, Mail và các dịch vụ

XMPP không trả lại một phản hồi tức thì.


Nhận tin nhắn email và trò chuyện cũng tương tự như nhận được yêu cầu HTTP. Trong
thực tế, họ sử dụng các cơ chế tương tự: xử lý yêu cầu. Khi một dịch vụ nhận được một
tin nhắn email hoặc XMPP dành cho ứng dụng của bạn, các dịch vụ sẽ gửi một yêu cầu
HTTP để ứng dụng sử dụng một URL được chỉ định với các thông báo trong payload
HTTP. Các ứng dụng xử lý các thông điệp đến sử dụng xử lý yêu cầu ánh xạ tới các URL
cụ thể. Dịch vụ này bỏ qua các phản hồi cho yêu cầu; nếu ứng dụng cần phải trả lời cho
người sử dụng, nó có thể gửi tin nhắn bằng cách sử dụng API.
Hình 11-1 minh họa các luồng email gửi đến và nhắn XMPP.

Hình 11-1. Cấu trúc của thư đến và XMPP, gọi webhooks để đáp ứng với các sự kiện tin
nhắn gửi đến


Mỗi ứng dụng đã thiết lập riêng của nó các địa chỉ email và XMPP, dựa trên ID ứng dụng
của nó. App Engine hiện không hỗ trợ các địa chỉ email và XMPP với các lĩnh vực tùy
chỉnh.
Ứng dụng cũng có thể nhận tin nhắn tại địa chỉ tùy ý với một tên miền ứng dụng cụ thể.
Đối với email, các ứng dụng có thể nhận tin nhắn tại địa chỉ của các hình thức:


Đối với XMPP chat, ứng dụng này có thể nhận tin nhắn tại địa chỉ của những hình thức
(lưu ý sự khác biệt trong tên miền):


Trong chương này, chúng tôi sẽ thảo luận về các API cho việc gửi và nhận email và tin
nhắn XMPP, và các công cụ ngôn ngữ cụ thể cho việc tạo và xử lý những tin nhắn.
Kích hoạt dịch vụ trong nước (Enabling Inbound Services)

Các email gửi đến và XMPP tin nhắn được tắt theo mặc định. Nếu một ứng dụng có một
dịch vụ trong nước bị vô hiệu hóa, thì sau đó tin nhắn được gửi đến địa chỉ của một ứng
dụng sẽ được bỏ qua, và dịch vụ này sẽ không bao giờ tìm cách để truy cập vào các ứng
dụng ở URL hook web.
Trong Java, bạn thêm một phần tương tự với file appengine-web.xml, bất cứ đâu bên
trong phần tử gốc:
<inbound-services>
<service>mail</service>
<service>xmpp_message</service>
</inbound-services>
Những ví dụ này cho phép cả hai dịch vụ. Bạn có thể bỏ qua một dịch vụ để giữ nó vô
hiệu hóa trong khi cho phép khác.
Một khi ứng dụng của bạn được triển khai, bạn có thể xác nhận rằng các dịch vụ được
kích hoạt từ Administration Console dưới Cài đặt ứng dụng. Nếu ứng dụng của bạn


không xuất hiện để được nhận các yêu cầu HTTP cho các tin nhắn gửi đến, kiểm tra các
điều khiển và cập nhật các cấu hình nếu cần thiết.
Gửi thư điện tử (Sending Email Messages)
Để gửi một tin nhắn email, bạn gọi các API của dịch vụ Mail. Các tin nhắn gửi đi có một
địa chỉ người gửi ( "From"), một hoặc nhiều người nhận ("To", "Cc" hoặc Bcc "), một
chủ đề, một nội dung thư và file đính kèm tập tin tùy chọn.
Một thông điệp gửi đi có thể chỉ có các trường này, và không thể sử dụng tiêu đề email
khác. Các dịch vụ thư gắn thêm header vào tin nhắn cho mục đích theo dõi, chẳng hạn
như ngày và giờ của tin nhắn được gửi.
Bạn có thể chỉ định một cấu trúc nhắn nhiều phần, chẳng hạn như để bao gồm cả văn bản
và phiên bản HTML đơn giản của tin nhắn, và bao gồm các file đính kèm. Tổng kích
thước của tin nhắn, bao gồm tất cả các tiêu đề, không thể vượt quá một megabyte.
Các lời gọi đến các dịch vụ Mail là không đồng bộ. Khi ứng dụng của bạn gọi Mail
dịch vụ gửi tin nhắn, tin nhắn được hàng đợi để cung cấp, và các dịch vụ gửi trả lại. Nếu

có một vấn đề cung cấp tin nhắn, chẳng hạn như máy chủ mail từ xa không thể liên lạc
hoặc các máy chủ từ xa nói địa chỉ là không hợp lệ, một thông báo lỗi sẽ được gửi qua
email đến địa chỉ người gửi. Các ứng dụng không được thông báo về sự thất bại của các
dịch vụ trực tiếp. (Bạn có thể sử dụng một địa chỉ email gửi đến cho các ứng dụng như
địa chỉ người gửi. Các ứng dụng sẽ phải phân tích các tin nhắn được gửi bởi các máy chủ
từ xa cho một lỗi.).
Khi ứng dụng của bạn chạy trong các máy chủ phát triển, gửi một tin nhắn làm cho máy
chủ in thông tin về tin nhắn tới các bản ghi, và tin nhắn không được gửi.
Địa chỉ người gửi (Sender Addresses)
Người gửi ( "From") giải quyết trên một thông báo email gửi đi phải là một trong những
địa chỉ được phép:


Địa chỉ tài khoản Google của một trong những người quản trị ứng dụng.



Địa chỉ của người sử dụng hiện đang đăng nhập vào các ứng dụng với tài khoản
Google (trong xử lý yêu cầu đó là gửi tin nhắn).



Một địa chỉ email hợp lệ đến cho các ứng dụng.


Trả lời tin nhắn được gửi bởi các ứng dụng đi đến địa chỉ người gửi, cũng như các thông
báo lỗi được gửi bởi máy chủ thư đi (chẳng hạn như "Không thể kết nối với máy chủ từ
xa") hoặc máy chủ mail từ xa (chẳng hạn như "Người dùng không tìm thấy").
Bạn có thể sử dụng địa chỉ tài khoản Google của một nhà phát triển ứng dụng như địa chỉ
người gửi. Để thêm tài khoản như quản trị viên ứng dụng, chuyển đến mục phát triển của

giao diện chính. Nếu bạn không muốn sử dụng các tài khoản của một nhà phát triển cụ
thể như địa chỉ người gửi, bạn có thể tạo một tài khoản Google mới cho một địa chỉ mục
đích chung, sau đó thêm nó như là một nhà phát triển cho các ứng dụng. Hãy chắc chắn
rằng bạn bảo vệ mật khẩu tài khoản Google , vì bất cứ ai có thể đăng nhập vào tài khoản
đó có thể sửa đổi ứng dụng của bạn. Bạn có thể sử dụng Gmail để theo dõi các tài khoản
để trả lời, và bạn có thể thiết lập chuyển tiếp email tự động trong Gmail để chuyển tiếp
trả lời cho các quản trị cụ thể hoặc một danh sách gửi thư (hoặc Google Group) tự động.
Bạn có thể sử dụng địa chỉ email của người dùng như địa chỉ người gửi nếu và chỉ nếu
địa chỉ là của một tài khoản Google được đăng ký, và người dùng được đăng nhập và bắt
đầu yêu cầu mà xử lý là gửi email. Đó là, bạn có thể gửi email trên danh nghĩa của người
sử dụng "hiện tại". Điều này rất hữu ích nếu email được kích hoạt bởi hành động của
người dùng và nếu trả lời vào tin nhắn nên đi đến địa chỉ email của người dùng. Các tài
khoản Google API không tiếp xúc với tên con người có thể đọc được của người sử dụng,
do đó bạn sẽ không thể cung cấp, trừ khi bạn nhận được nó từ người sử dụng chính mình.
Như chúng ta đã đề cập trước đó, một ứng dụng có thể nhận tin nhắn email tại địa chỉ của
các hình thức hoặc , nơi
app-id là ID ứng dụng của bạn và bất cứ điều gì có thể là chuỗi bất kỳ đó là hợp lệ ở phía
bên trái của địa chỉ email (nó không thể chứa một biểu tượng @). Bạn có thể sử dụng một
địa chỉ email đến như người gửi một tin nhắn email đã trả lời chuyển đến một trình xử lý
yêu cầu.
Các "bất cứ điều gì" cho phép bạn tạo các địa chỉ người gửi tùy chỉnh một cách nhanh
chóng. Ví dụ, một ứng dụng hỗ trợ khách hàng có thể bắt đầu một cuộc trò chuyện email
với một ID duy nhất và bao gồm các ID trong địa chỉ email (support+ID@app-


id.appspotmail.com), và lưu trả lời cho chuyện đó trong kho dữ liệu nên toàn bộ chủ đề
có thể được xem bởi các nhân viên dịch vụ khách hàng.
Lưu ý rằng địa chỉ người gửi cũng sẽ nhận được lỗi ("trả lại") tin nhắn. Nếu bạn sử dụng
một địa chỉ thư đến như là người gửi, bạn có thể có những tin nhắn quá trình lỗi ứng dụng
để loại bỏ các địa chỉ email không hợp lệ tự động. Lưu ý rằng các máy chủ email khác

nhau từ xa có thể sử dụng định dạng khác nhau để thông báo lỗi.
Bất kỳ địa chỉ thư điện tử nào cũng có thể có một cái tên thân thiện với con người, chẳng
hạn như "The Example Nhóm <>". Làm thế nào bạn làm điều này
là cụ thể cho giao diện; chúng ta sẽ xem xét các giao diện trong một thời điểm.
Bạn có thể bao gồm một địa chỉ riêng biệt "Reply-to" địa chỉ ngoài người gửi ( "Từ").
Hầu hết độc giả mail và máy chủ sẽ sử dụng địa chỉ này thay vì địa chỉ người gửi để trả
lời và thông báo lỗi. "Reply-to" địa chỉ phải đáp ứng các yêu cầu tương tự như địa chỉ
người gửi.
Các máy chủ phát triển không kiểm tra xem địa chỉ người gửi đáp ứng các điều kiện bởi
vì nó không biết các nhà phát triển của ứng dụng là ai. Hãy chắc chắn để kiểm tra các
tính năng gửi email trong khi đang chạy trên App Engine.
Người nhận (Recipients)
Một thông báo email gửi đi có thể sử dụng bất kỳ địa chỉ cho một người nhận, và có thể
có nhiều người nhận.
Một người nhận có thể là một người nhận chính ("To"), một thứ hoặc "carbon-copy"
người nhận (các "Cc" trường), hoặc một "mù carbon-copy" người nhận ("Bcc"). "To" và
"Cc" người nhận được bao gồm trong nội dung của tin nhắn, do đó, một câu trả lời dành
cho tất cả những người nhận có thể được gửi đến các địa chỉ có thể nhìn thấy. Những
người nhận "Bcc" nhận được thông báo, nhưng địa chỉ của họ không nằm trong nội dung
của tin nhắn, và do đó không được bao gồm trong bài trả lời.
Các loại "Bcc" người nhận là đặc biệt hữu ích nếu bạn muốn có một tin nhắn duy nhất để
đi tới nhiều người, nhưng bạn không muốn mọi người nhận biết những người nhận được
tin nhắn. Bạn có thể sử dụng kỹ thuật này để gửi một bản tin email cho người dùng mà
không lộ địa chỉ email của người dùng. Một kỹ thuật phổ biến cho các bản tin là sử dụng


địa chỉ người gửi là duy nhất "To" người nhận, và làm cho người khác một "Bcc" người
nhận.
Số lượng người nhận được một email đếm hướng tới một hạn mức nhận email. hạn mức
này là ban đầu nhỏ để ngăn chặn các nhà quảng cáo email không mong muốn từ lạm

dụng hệ thống. Bạn có thể tăng hạn mức này bằng cách phân bổ phần ngân sách của bạn
đối với người nhận email.
Tập tin đính kèm (Attachments)
Một ứng dụng có thể đính kèm tập tin vào một tin nhắn email. Vì lý do an ninh (chủ yếu
là phải làm gì với các email máy khách không an toàn), chỉ có một số loại tập tin được
phép đính kèm. Tên tập tin phải kết thúc bằng một phần mở rộng phản ánh loại của tập
tin. Bảng 11-1 liệt kê các loại phép và tương ứng với các phần mở rộng tên tập tin cho
phép.
Bảng 11-1. Các loại tập tin cho phép các file đính kèm email, và phần mở rộng tên tập tin
cần thiết của họ

Những loại này thường đủ cho nội dung email phong phú, nhưng không nhất thiết phải
cho các tài liệu kinh doanh hoặc các ứng dụng máy tính để bàn. Nếu bạn muốn cung cấp
các loại file khác cho người sử dụng, một lựa chọn là gửi một liên kết đến một trình xử lý


yêu cầu đó cung cấp các tập tin thông qua trình duyệt. Các liên kết có thể được cá nhân
hoá tạm thời với một ID duy nhất, hoặc hạn chế sử dụng xác thực tài khoản Google.
Gửi email trong Java (Sending Email in Java)
Các giao diện Java với dịch vụ Mail là giao diện chuẩn JavaMail (javax.mail. *). Ngoài ra
còn có một giao diện cấp thấp, mặc dù bạn có thể truy cập tất cả các tính năng của dịch
vụ thông qua việc thực hiện JavaMail. (Như vậy, chúng tôi sẽ chỉ thảo luận về giao diện
JavaMail ở đây.)
Để sử dụng JavaMail, trước tiên bạn tạo một "session". JavaMail Các đối tượng Session
thường chứa các thông tin cần thiết để kết nối với một máy chủ mail, nhưng với App
Engine, không có cấu hình là cần thiết. Bạn chuẩn bị các thông điệp như một đối tượng
MimeMessage, sau đó gửi nó bằng cách sử dụng send() phương thức tĩnh của lớp
Transport. Các lớp Transport sử dụng phiên gần đây đã tạo nhất để gửi tin nhắn.
import java.util.Properties;
import javax.mail.Message;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;
// ...
User user = UserServiceFactory.getUserService().getCurrentUser();
String recipientAddress = user.getEmail();
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
String messageBody =
"Welcome to Example! Your account has been created." +


"You can edit your user profile by clicking the" +
"following link:\n\n" +
" +
"Let us know if you have any questions.\n\n" +
"The Example Team\n";
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("",
"The Example Team"));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(recipientAddress));
message.setSubject("Welcome to Example.com!");
message.setText(messageBody);

Transport.send(message);
} catch (AddressException e) {
// An email address was invalid.
// ...
} catch (MessagingException e) {
Sending Email Messages
|
261
// There was an error contacting the Mail service.
// ...
}
Như đã trình bày ở đây, bạn gọi phương thức trên MimeMessage để thiết lập các trường
và để thêm người nhận và nội dung. Thông điệp đơn giản nhất có một người gửi (setFrom
()), một trong "To" người nhận (addRecipient ()), một đối tượng (setSubject ()), và một
cơ quan nhắn văn bản đơn giản (setText ()).


Phương thức setFrom () nhận một InternetAddress. Bạn có thể tạo một InternetAddress
chỉ với địa chỉ email (String) hay địa chỉ và tên người đọc được làm tham số cho hàm tạo.
Các địa chỉ email của người gửi phải đáp ứng các yêu cầu mô tả trước đó. Bạn có thể sử
dụng bất kỳ chuỗi cho tên người hiểu.
Phương thức addRecipient () có một loại người nhận và một InternetAddress. Các loại
người nhận cho phép là Message.RecipientType.TO ("To", một người nhận cơ bản),
Message.RecipientType.CC ("Cc" hoặc "carbon copy", một người nhận phụ) và
Message.RecipientType.BCC ("Bcc "hoặc" carbon copy mù ", nơi người nhận gửi tin
nhắn nhưng địa chỉ không xuất hiện trong nội dung tin nhắn). Bạn có thể gọi
addRecipient () nhiều lần để thêm nhiều loại người nhận bất kỳ.
Phương thức setText () thiết lập khối văn bản đơn giản cho tin nhắn. Để bao gồm một
phiên bản HTML của khối thông báo cho bạn đọc mail hỗ trợ HTML, bạn tạo một đối
tượng MimeMultipart, sau đó tạo ra một MimeBodyPart cho khối văn bản đơn giản và

một cho khối HTML và thêm chúng vào MimeMultipart. Sau đó bạn làm cho nội dung
MimeMultipart của MimeMessage:
import javax.mail.Multipart;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
// ...
String textBody = "...text...";
String htmlBody = "...HTML...";
Multipart multipart = new MimeMultipart();
MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(textBody, "text/plain");
multipart.addBodyPart(htmlPart);
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(htmlBody, "text/html");
multipart.addBodyPart(htmlPart);
message.setContent(multipart);


Bạn đính kèm tập tin vào tin nhắn email trong một cách tương tự:
Multipart multipart = new MimeMultipart();
// ...
byte[] fileData = getBrochureData();
String fileName = "brochure.pdf";
String fileType = "application/pdf";
MimeBodyPart attachmentPart = new MimeBodyPart();
attachmentPart.setContent(fileData, fileType);
attachmentPart.setFileName(fileName);
multipart.addBodyPart(attachmentPart);
// ...
message.setContent(multipart);

Hãy nhớ rằng một tập tin đính kèm phải có một trong các loại đã được phê duyệt, và phải
có tên tập tin kết thúc bằng một phần mở rộng tên tập tin tương ứng, như được liệt kê
trong Bảng 11-1.
Bạn có thể thêm nhiều đối tượng MimeBodyPart một MimeMultipart duy nhất. Khôi đơn
giản văn bản, khối HTML, và các tập tin đính kèm là mỗi một phần của một tin nhắn
MIME nhiều phần.
Khi sử dụng một MimeMultipart, bạn phải bao gồm một phần text/plain là khối văn bản
đơn giản của tin nhắn. Các đối tượng nhiều phần dữ liệu ghi đè bất kỳ nội dung tập văn
bản đơn giản trên MimeMessage với setText ().
App Engine’s thực thi giao diện JavaMail có một lối tắt để gửi một tin nhắn email cho tất
cả các cán bộ quản lý của ứng dụng. Để gửi tin nhắn đến tất cả các nhà quản lý, sử dụng
một địa chỉ người nhận là "admins", không có biểu tượng @ hoặc tên miền.
Tiếp nhận tin nhắn email (Receiving Email Messages)
Với dịch vụ email kích nội địa hoạt trong cấu hình, một ứng dụng có thể nhận tin nhắn
email tại bất kỳ của một số địa chỉ. Một tin nhắn qua thư đến sẽ được chuyển đến các ứng
dụng trong các hình thức của một yêu cầu HTTP.


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×