Spring 基于Session的创建实例
需求
提供一个网页,根据导入的Excel数据计算结果。
第一版本设计
Controller层
@RestController public class QuoteController { private static Logger logger = LoggerFactory.getLogger(QuoteController.class.getName()); private String SESSION_KEY_QUOTE = "quote"; private String SESSION_KEY_QUOTE_RESULT = "quote_result"; @Autowired QuoteService quoteService; //报价数据导入 @RequestMapping(value = "quote/import", method = RequestMethod.POST) public String quoteImport(MultipartFile file, Double ratio) { // 判断文件是否为空 if(!file.isEmpty()){ try { List<QuoteItem> items = quoteService.upload(file); List<QuoteCacResult> cacResult = quoteService.calculate(items, ratio); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); request.getSession().setAttribute(SESSION_KEY_QUOTE, items); request.getSession().setAttribute(SESSION_KEY_QUOTE_RESULT, cacResult); } catch (Exception e) { logger.error(e.getMessage()); return e.getMessage(); } } return "success"; } @RequestMapping(value = "quote/recalculate", method = RequestMethod.POST) public String recalculate(Double ratio){ CommonResult<List<QuoteCacResult>> result = new CommonResult<>(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); if (request.getSession().getAttribute(SESSION_KEY_QUOTE) != null){ List<QuoteItem> items = (List<QuoteItem>)request.getSession().getAttribute(SESSION_KEY_QUOTE); List<QuoteCacResult> cacResult = quoteService.calculate(items, ratio); request.getSession().setAttribute(SESSION_KEY_QUOTE_RESULT, cacResult); } return "success"; } @RequestMapping(value = "quote/result", method = RequestMethod.GET) public CommonResult<List<QuoteCacResult>> quoteCala(){ CommonResult<List<QuoteCacResult>> result = new CommonResult<>(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); if (request.getSession().getAttribute(SESSION_KEY_QUOTE_RESULT) == null) { result.setData(new ArrayList<>()); }else { List<QuoteCacResult> data = (List<QuoteCacResult>)request.getSession().getAttribute(SESSION_KEY_QUOTE_RESULT); result.setData(data); } return result; } }
Service层
存在的问题
1,导入的数据通过参数返回给计算函数,没有对象数据的封装
2,Controller存在大量关于Session存储、获取代码
改进版本
Controller层
@RestController public class QuoteController { private static Logger logger = LoggerFactory.getLogger(QuoteController.class.getName()); @Autowired private QuoteService quoteService; //报价数据导入 @RequestMapping(value = "quote/import", method = RequestMethod.POST) public String quoteImport(MultipartFile file, Double ratio) { // 判断文件是否为空 if(!file.isEmpty()){ try { quoteService.upload(file); quoteService.calculate(ratio); } catch (Exception e) { logger.error(e.getMessage()); return e.getMessage(); } } return "success"; } @RequestMapping(value = "quote/recalculate", method = RequestMethod.POST) public String recalculate(Double ratio){ quoteService.calculate(ratio); return "success"; } @RequestMapping(value = "quote/result", method = RequestMethod.GET) public CommonResult<List<QuoteCacResult>> quoteCala(){ CommonResult<List<QuoteCacResult>> result = new CommonResult<>(); result.setData(quoteService.getCalcResult()); return result; } }
Servie层
总结
1, 改进版本更简洁,更面向对象
2,注意calcResult必须声明封装get,set方法。否则proxy不起作用,参见
https://stackoverflow.com/questions/39488124/how-to-use-session-scoped-component-in-controller
3, 采用Spring Boot搭建的项目,无须配置RequestContextListener上面代码就能生效。
签名:删除冗余的代码最开心,找不到删除的代码最痛苦!