2015-01-12 22 views
10

tôi sử dụng bộ nhớ cache mùa xuân với phương pháp này mà trả về giá trị truy vấn như JSON:Làm thế nào để có bộ nhớ cache mùa xuân lưu trữ các ResponseBody và không phải là đối tượng trung gian

@RequestMapping("/getById") 
@ResponseBody 
@Cacheable 
public HugeValue getHugeValueFromSlowFoo(@RequestParam(value = "id", defaultValue = "") String id) { 
    return Foo.getById(id); 
} 

này hoạt động tốt và HugeValue đối tượng được lưu trữ trong cache (Hazelcast trong trường hợp này). Tôi muốn tiếp tục cải thiện điều này bởi vì thời gian thực hiện để tạo JSON từ HugeValue là khá cao. Tôi có thể yêu cầu bộ nhớ đệm mùa xuân lưu vào bộ nhớ cache phiên bản JSON-ified của đối tượng của tôi không?

tôi sử dụng Jackson với mùa xuân Boot 1.2 và Spring 4.1

Trả lời

6

Nếu không thực sự biết trường hợp sử dụng chính xác của bạn (tôi chưa cho phép để thêm ý kiến ​​cho hỏi không may), tôi cố gắng để cung cấp cho một bản tóm tắt ngắn về những ý tưởng Tôi có ý. Tất cả đều cho rằng bạn sử dụng Jackson để lập bản đồ json và ít nhất Mùa xuân 3.1.

Không có tính năng enableResponseBodyCaching trong SpringMVC theo như tôi biết.

Thay thế đầu tiên: Sử dụng bộ nhớ đệm http vì có vẻ như bạn thực sự muốn lưu toàn bộ phản hồi http. Xuân cung cấp một cách thẳng về phía trước của global configuration:

<mvc:interceptors> 
    <bean id="webContentInterceptor" 
      class="org.springframework.web.servlet.mvc.WebContentInterceptor"> 
     <property name="cacheSeconds" value="0"/> 
     <property name="useExpiresHeader" value="true"/> 
     <property name="useCacheControlHeader" value="true"/> 
     <property name="useCacheControlNoStore" value="true"/> 
    </bean> 
</mvc:interceptors> 

Nếu bạn muốn kiểm soát này mỗi Controller, kế thừa từ mùa xuân AbstractController và thiết lập thuộc tính cacheSeconds theo Javadoc.

Sức mạnh thực sự của bộ đệm http đi kèm với proxy http trước máy chủ của bạn.

Ý tưởng thứ hai: Triển khai lớp con của riêng bạn MappingJackson2HttpMessageConverter. Trong writeInternal() bạn có thể thêm một số logic truy cập bộ nhớ cache để truy xuất phiên bản đã được ánh xạ thay vì ánh xạ đối tượng đầu vào. Cách tiếp cận này có nghĩa là bạn sẽ nhấn các dịch vụ của mình để truy xuất đối tượng java đằng sau luồng Json. Nếu điều này là tốt cho bạn bởi vì cũng có bộ nhớ đệm tại một số điểm, cách tiếp cận này là giá trị một thử imho.

Ý tưởng thứ ba: Tự mình lập bản đồ json trong dịch vụ trình bao bọc chuyên dụng cung cấp chuỗi/luồng json thô. Bạn có thể dễ dàng tiêm Jackson Mapper (tên lớp ObjectMapper) và kiểm soát toàn bộ bản đồ. Chú thích dịch vụ này sau đó cho phép bạn lưu vào bộ nhớ cache kết quả. Trong Bộ điều khiển, bạn chỉ cung cấp ResponseEntity của loại theo bạn sử dụng (Chuỗi hoặc một số luồng). Điều này thậm chí sẽ ngăn chặn truy cập dịch vụ sâu hơn nếu có kết quả được lưu trong bộ nhớ cache.

Chỉnh sửa: Có thể là MappingJackson2JsonView cũng có thể hữu ích. Thành thật mà nói, tôi không bao giờ làm việc với nó trước đây vì vậy tôi không thể thực sự nói điều gì đó về việc sử dụng nó.

Hy vọng điều đó sẽ giúp và/hoặc tạo cảm hứng! Chúc mừng

+0

Cảm ơn câu trả lời kỹ lưỡng và giải pháp thay thế tuyệt vời. Tôi sẽ chờ lâu hơn một chút nếu các câu trả lời khác đến nhưng bây giờ tôi thích tất cả các lựa chọn thay thế mà bạn mô tả và ý tưởng thứ ba dường như phù hợp mặc dù có một số công việc liên quan đến việc thực hiện điều này. Vì vậy, lười biếng là lý do duy nhất để tôi chờ đợi một câu trả lời thứ tư có thể có thể cần ít công việc ;-). Một bộ nhớ cache trình duyệt không phải là những gì tôi muốn bởi vì tôi có hàng ngàn người dùng sẽ nhận được kết quả tương tự và bộ nhớ cache của trình duyệt sẽ không hoạt động một cách hoàn hảo vì HugeValue sẽ cần phải được lấy ra và giải thích cho từng người dùng. – Marged

+0

Cấu hình WebContentInterceptor thực sự yêu cầu máy khách không lưu lại phản hồi ... –

1

Tôi nghĩ điều này có thể hiệu quả.

public interface HugeValueService{ 
    public String getHugeValueFromSlowFoo(String id); 
} 

public class HugeValueServiceImpl implements HugeValueService{ 
    @Cacheable 
    public String getHugeValueFromSlowFoo(String id) { 
     return Foo.getById(id); 
    } 
} 

Your Class 
---------- 
@RequestMapping("/getById") 
@ResponseBody 
public HugeValue getHugeValueFromSlowFoo(@RequestParam(value = "id", defaultValue = "") String id) { 
    return hugeValueService.getHugeValueFromSlowFoo(id); 
} 

Chúc may mắn !!!

1

Cache json và đặt nó vào phản hồi theo cách thủ công.

public void getHugeValueFromSlowFoo(@RequestParam(value = "id", defaultValue = "") String id, ServletResponse resp) 
{ 
    String jsonSerializedHugeValue = Bar.getById(id); // serialize manually with ObjectMapper 
    resp.getWriter().write(jsonSerializedHugeValue); 
    resp.setContentType("application/json"); 
    resp.flushBuffer(); 
} 
+0

Tác phẩm này, nhưng không phải là "kiểu khởi động". Mà tôi thừa nhận đã không đề cập đến như là một điều kiện tiên quyết ;-) – Marged

+0

Trong khi không thường được sử dụng (và chính xác, vì nó không cần thiết hầu hết thời gian) đó là một mã mùa xuân và khởi động thích hợp. Nó cũng sạch sẽ, rõ ràng và dễ đọc. – Dariusz

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