2010-06-05 26 views
10

Tôi đang viết một hình ảnh để đáp ứng servlet với hiệu suất tốt nhất. Bất kỳ lời khuyên, thực hành, kinh nghiệm?Viết hình ảnh để đáp ứng servlet với hiệu suất tốt nhất

+0

Tôi lưu hình ảnh trong DB trong dự án hiện tại. Bộ điều khiển lò xo cụ thể nhận các mảng byte của hình ảnh từ DB và ghi chúng vào phản hồi của servlet. Cũng sẽ có một máy chủ web ở phía trước thùng chứa servlet. Như tôi biết, điều này có thể dẫn đến một số vấn đề về hiệu suất. Ngay bây giờ tôi không có rắc rối, nhưng muốn biết nếu có một số giải pháp tốt cho vụ án. Ví dụ. một số thực hành bộ nhớ đệm, tiêu đề cụ thể, v.v. Một số trải nghiệm về DB vs FileSystem làm cửa hàng hình ảnh được đánh giá cao. Lưu trữ hình ảnh trong cơ sở dữ liệu dường như với tôi thoải mái hơn. – tabdulin

Trả lời

22

Để có hiệu suất và hiệu quả tốt nhất, không đặt toàn bộ nội dung trong byte[]. Mỗi byte ăn, có, một byte từ bộ nhớ của Java. Hãy tưởng tượng 100 người dùng đồng thời yêu cầu 10 hình ảnh của mỗi 100KB, đã mất 100MB bộ nhớ Java.

Lấy hình ảnh như một InputStream từ DB sử dụng ResultSet#getBinaryStream(), bọc nó trong một BufferedInputStream và ghi nó vào OutputStream của phản ứng được bọc trong một BufferedOutputStream qua một nhỏ byte[] đệm.

Giả sử bạn chọn hình ảnh kết thúc bằng phím cơ sở dữ liệu như nhận dạng, sử dụng này trong HTML của bạn:

<img src="images/123"> 

Tạo một lớp Servlet được ánh xạ trong web.xml trên một url-pattern của /images/* và thực hiện các phương pháp doGet() của nó như sau .:

Long imageId = Long.valueOf(request.getPathInfo().substring(1)); // 123 
Image image = imageDAO.find(imageId); // Get Image from DB. 
// Image class is just a Javabean with the following properties: 
// private String filename; 
// private Long length; 
// private InputStream content; 

response.setHeader("Content-Type", getServletContext().getMimeType(image.getFilename())); 
response.setHeader("Content-Length", String.valueOf(image.getLength())); 
response.setHeader("Content-Disposition", "inline; filename=\"" + image.getFilename() + "\""); 

BufferedInputStream input = null; 
BufferedOutputStream output = null; 

try { 
    input = new BufferedInputStream(image.getContent()); 
    output = new BufferedOutputStream(response.getOutputStream()); 
    byte[] buffer = new byte[8192]; 
    for (int length = 0; (length = input.read(buffer)) > 0) { 
     output.write(buffer, 0, length); 
    } 
} finally { 
    if (output != null) try { output.close(); } catch (IOException logOrIgnore) {} 
    if (input != null) try { input.close(); } catch (IOException logOrIgnore) {} 
} 

Trong ImageDAO#find() bạn có thể sử dụng ResultSet#getBinaryStream() để có được những hình ảnh như một InputStream từ cơ sở dữ liệu.

+0

một biến thể nhỏ về điều này có thể là để cho phép ImageDAO ghi lại phản hồi hoặc có thể sử dụng kiểu gọi lại như kiểu (nghĩ spring JdbcTemplate hoặc HibernateTemplate).Nếu không thì JDBCConnection và ResultSet sẽ phải được mở sau khi trở về từ ImageDAO.find() để cho ImageStream InputStream hoạt động. –

+0

Xin chào, trong khi bạn nói "không sử dụng byte []" bạn sử dụng 'byte [] buffer = new byte [8192];', thì điểm là gì? – hguser

+0

@hguser: Tôi đã làm rõ câu trả lời. – BalusC

0

bạn có thể sử dụng byte của loại mảng cho hình ảnh từ servlet nếu nó có trong cơ sở dữ liệu kiểu Blob.

byte[] image; 

hoặc có một cách khác, nhưng có một chút phức tạp. khi u gọi servlet của bạn, vì vậy trước đó u cần phải xác định xem cuộc gọi là cho hình ảnh hay đó là cuộc gọi bình thường. nếu nó là một cuộc gọi bình thường thì u có thể gọi servlet, nhưng nếu nó gọi cho hình ảnh thì đừng gọi servlet nhưng u có thể lưu trữ các tham chiếu hình ảnh tại một số vị trí vật lý trong máy tính và lấy lại.

Nhưng phương pháp này sẽ không hoạt động nếu u có hình ảnh trong DB, thay vì u có thể có đường dẫn tương đối trong DB và sau đó u có thể lấy hình ảnh từ đường dẫn đó.

0

Nếu hình ảnh tĩnh, hãy nhớ rằng phản hồi nhanh nhất là phản hồi được xử lý trước khi nó đến với bạn.

Bạn có thể đứng lên httpd của Apache trước máy chủ Tomcat của bạn. Bạn có thể sử dụng các biến thể khác của bộ nhớ đệm máy chủ cạnh. Có rất nhiều thủ thuật dọc theo những dòng đó.

Tất nhiên, điều này cho thấy rằng ứng dụng của bạn được viết nơi URL có hiệu quả ánh xạ tới một hình ảnh theo cách dễ dàng lưu vào bộ nhớ cache. Nếu ứng dụng của bạn thiếu điều này, các lợi ích là đủ lớn để xem xét tái cơ cấu.

Các vấn đề liên quan