日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实战SSM_O2O商铺_11【商铺注册】Controller层的实现

發布時間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实战SSM_O2O商铺_11【商铺注册】Controller层的实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 概述
  • 結構
  • Maven依賴
  • 封裝工具類HttPServletRequestUtil
  • Controller控制層編寫
  • Service層的改造
  • 單元測試
  • Github地址

概述

實戰SSM_O2O商鋪_10【商鋪注冊】Service層的實現 實現之后,接下來編寫控制層的代碼

用到了jackson-databind https://github.com/FasterXML/jackson-databind ,將前臺傳遞過來的JSON對象轉換為POJO類


結構


Maven依賴

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.8.7</version> </dependency>

封裝工具類HttPServletRequestUtil

Controller層與View層密不可分,需要接受View層傳遞過來的信息,我們使用SSM框架的話,傳遞的請求信息都存在HttpServletRequest中。 因此需要先封裝一個工具類來獲取HttPServletRequest中的值。

Controller層負責具體的業務模塊流程的控制,在此層里面要調用Serice層的接口來控制業務流程。

package com.artisan.o2o.util;import javax.servlet.http.HttpServletRequest;/*** * * @ClassName: HTTPServletRequestUtil* * @Description: 獲取前端請求HttpServletRequest中參數的工具類* * @author: Mr.Yang* * @date: 2018年5月21日 下午10:56:16*/ public class HttPServletRequestUtil {public static int getInt(HttpServletRequest request, String name) {try {return Integer.decode(request.getParameter(name));} catch (Exception e) {return -1;}}public static long getLong(HttpServletRequest request, String name) {try {return Long.valueOf(request.getParameter(name));} catch (Exception e) {return -1;}}public static Double getDouble(HttpServletRequest request, String name) {try {return Double.valueOf(request.getParameter(name));} catch (Exception e) {return -1d;}}public static Boolean getBoolean(HttpServletRequest request, String name) {try {return Boolean.valueOf(request.getParameter(name));} catch (Exception e) {return false;}}public static String getString(HttpServletRequest request, String name) {try {String result = request.getParameter(name);if (result != null) {result = result.trim();}if ("".equals(result))result = null;return result;} catch (Exception e) {return null;}} }

Controller控制層編寫

package com.artisan.o2o.web.shopadmin;import java.io.IOException; import java.util.HashMap; import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartFile; import org.springframework.web.multipart.commons.CommonsMultipartResolver;import com.artisan.o2o.dto.ShopExecution; import com.artisan.o2o.entity.PersonInfo; import com.artisan.o2o.entity.Shop; import com.artisan.o2o.enums.ShopStateEnum; import com.artisan.o2o.service.ShopService; import com.artisan.o2o.util.HttPServletRequestUtil; import com.fasterxml.jackson.databind.ObjectMapper;@Controller @RequestMapping("/shopadmin") public class ShopController {@Autowiredprivate ShopService shopService;/*** * * @Title: registerShop* * @Description:* * @param request* 因為是接收前端的請求,而前端的信息都封裝在HttpServletRequest中,* 所以需要解析HttpServletRequest,獲取必要的參數* * 1. 接收并轉換相應的參數,包括shop信息和圖片信息 2. 注冊店鋪 3. 返回結果給前臺* @return* * @return: Map<String,Object>*/@RequestMapping(value = "/registshop", method = RequestMethod.POST)@ResponseBodypublic Map<String, Object> registerShop(HttpServletRequest request) {Map<String, Object> modelMap = new HashMap<String, Object>();// 1. 接收并轉換相應的參數,包括shop信息和圖片信息// 1.1 shop信息// shopStr 是和前端約定好的參數值,后端從request中獲取request這個值來獲取shop的信息String shopStr = HttPServletRequestUtil.getString(request, "shopStr");// 使用jackson-databind 將json轉換為pojoObjectMapper mapper = new ObjectMapper();Shop shop = null;try {// 將json轉換為pojoshop = mapper.readValue(shopStr, Shop.class);} catch (Exception e) {e.printStackTrace();// 將錯誤信息返回給前臺modelMap.put("success", false);modelMap.put("errMsg", e.getMessage());}// 1.2 圖片信息 基于Apache Commons FileUpload的文件上傳// Spring MVC中的 圖片存在CommonsMultipartFile中CommonsMultipartFile shopImg = null;// 從request的本次會話中的上線文中獲取圖片的相關內容CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());if (commonsMultipartResolver.isMultipart(request)) {MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;// shopImg是和前端約定好的變量名shopImg = (CommonsMultipartFile) multipartRequest.getFile("shopImg");} else {// 將錯誤信息返回給前臺modelMap.put("success", false);modelMap.put("errMsg", "圖片不能為空");}// 2. 注冊店鋪if (shop != null && shopImg != null) {// Session TODO// 店主persionInfo的信息,肯定要登錄才能注冊店鋪。// 所以這部分信息我們從session中獲取,盡量不依賴前端,這里暫時時不具備條件,后續改造,先硬編碼,方便單元測試PersonInfo personInfo = new PersonInfo();personInfo.setUserId(1L);shop.setOwner(personInfo);// 注冊店鋪// se = shopService.addShop(shop, shopImg); 改造前的調用方式// 這個時候,我們從前端獲取到的shopImg是CommonsMultipartFile類型的,如何將CommonsMultipartFile轉換為file.// 網上也有將CommonsMultipartFile轉換為File的方法,并通過maxInMemorySize的設置盡量不產生臨時文件// 這里我們換個思路,因為CommonsMultipartFile可以獲取InputStream,Thumbnailator又可以直接處理輸入流// 因為InputStream中我們無法得到文件的名稱,而thumbnail中需要根據文件名來獲取擴展名,所以還要再加一個參數String類型的fileName// 既然第二個和第三個參數都是通過shopImg獲取的,為什么不直接傳入一個shopImg呢?// 主要是為了service層單元測測試的方便,因為service層很難實例化出一個CommonsMultipartFile類型的實例ShopExecution se = null;;try {se = shopService.addShop(shop, shopImg.getInputStream(), shopImg.getOriginalFilename());if (se.getState() == ShopStateEnum.CHECK.getState()) {modelMap.put("success", true);modelMap.put("errMsg", "注冊成功");} else {modelMap.put("success", false);modelMap.put("errMsg", se.getStateInfo());}} catch (IOException e) {e.printStackTrace();modelMap.put("success", false);modelMap.put("errMsg", "addShop Error");}} else {// 將錯誤信息返回給前臺modelMap.put("success", false);modelMap.put("errMsg", "請輸入店鋪信息");}return modelMap;}}

在Controller層,處理圖片的環節,接收前端傳遞過來的圖片類型為CommonsMultipartFile,而我們之前為了方便Service層的單元測試,addShop接口的定義如下

ShopExecution addShop(Shop shop, File shopFile);

所以,Controller在調用Servie層的時候,需要將CommonsMultipartFile轉換為File,這里我們換個思路,因為CommonsMultipartFile可以獲取InputStream,Thumbnailator又可以直接處理輸入流,因為InputStream中我們無法得到文件的名稱,而thumbnail中需要根據文件名來獲取擴展名,所以還要再加一個參數String類型的fileName。

既然第二個和第三個參數都是通過shopImg獲取的,為什么不直接傳入一個shopImg呢?主要是為了service層單元測測試的方便,因為service層很難實例化出一個CommonsMultipartFile類型的實例


Service層的改造

package com.artisan.o2o.service;import java.io.InputStream;import com.artisan.o2o.dto.ShopExecution; import com.artisan.o2o.entity.Shop;public interface ShopService {// 修改入參,將File類型的入參修改為InputStream,同時增加String類型的文件名稱ShopExecution addShop(Shop shop, InputStream shopFileInputStream, String fileName);}

ShopServiceImpl實現類中:

// 修改入參,將File類型的入參修改為InputStream,同時增加String類型的文件名稱@Override@Transactionalpublic ShopExecution addShop(Shop shop, InputStream shopImgInputStream, String fileName) {// 非空判斷 (這里先判斷shop是否為空,嚴格意義上講shop中的are的屬性也需要判斷)if (shop == null) {return new ShopExecution(ShopStateEnum.NULL_SHOP_INFO);}// 關鍵步驟1. 設置基本信息,插入tb_shop// 初始狀態: 審核中shop.setEnableStatus(0);shop.setCreateTime(new Date());shop.setLastEditTime(new Date());int effectedNum = shopDao.insertShop(shop);if (effectedNum <= 0) {throw new ShopOperationException("店鋪創建失敗");} else {// 關鍵步驟2. 添加成功,則繼續處理文件,獲取shopid,用于創建圖片存放的目錄if (shopImgInputStream != null) {try {// 需要根據shopId來創建目錄,所以也需要shop這個入參addShopImg(shop, shopImgInputStream, fileName);} catch (Exception e) {logger.error("addShopImg error {} ", e.toString());throw new ShopOperationException("addShopImg error:" + e.getMessage());}// 關鍵步驟3. 更新tb_shop中 shop_img字段effectedNum = shopDao.updateShop(shop);if (effectedNum <= 0) {logger.error("updateShop error {} ", "更新店鋪失敗");throw new ShopOperationException("updateShop error");}}}// 返回店鋪的狀態:審核中,以及店鋪信息return new ShopExecution(ShopStateEnum.CHECK, shop);}/*** * * @Title: addShopImg* * @Description: 根據shopId創建目錄,并生成水印圖片* * @param shop* @param shopImg* * @return: void*/private void addShopImg(Shop shop, InputStream shopImgInputStream, String fileName) {String imgPath = FileUtil.getShopImagePath(shop.getShopId());// 生成圖片的水印圖String relativeAddr = ImageUtil.generateThumbnails(shopImgInputStream, imgPath, fileName);// 將相對路徑設置個shop,用于更新數據庫shop.setShopImg(relativeAddr);}

ImageUitl工具類的改造

// 增加fileName參數 public static String generateThumbnails(InputStream ins, String destPath, String fileName) {// 拼接后的新文件的相對路徑String relativeAddr = null;try {// 1.為了防止圖片的重名,不采用用戶上傳的文件名,系統內部采用隨機命名的方式String randomFileName = generateRandomFileName();// 2.獲取用戶上傳的文件的擴展名,用于拼接新的文件名String fileExtensionName = getFileExtensionName(fileName);// 3.校驗目標目錄是否存在,不存在創建目錄validateDestPath(destPath);// 4.拼接新的文件名relativeAddr = destPath + randomFileName + fileExtensionName;logger.info("圖片相對路徑 {}", relativeAddr);// 絕對路徑的形式創建文件String basePath = FileUtil.getImgBasePath();File destFile = new File(basePath + relativeAddr);logger.info("圖片完整路徑 {}", destFile.getAbsolutePath());// 5.給源文件加水印后輸出到目標文件Thumbnails.of(ins).size(500, 500).watermark(Positions.BOTTOM_RIGHT, ImageIO.read(FileUtil.getWaterMarkFile()), 0.25f).outputQuality(0.8).toFile(destFile);} catch (Exception e) {e.printStackTrace();throw new RuntimeException("創建水印圖片失敗:" + e.toString());}return relativeAddr;}// 修改入參File類型,直接使用String類型 private static String getFileExtensionName(String fileName) {String extension = fileName.substring(fileName.lastIndexOf("."));logger.debug("extension: {}", extension);return extension;}

單元測試

我們改造了Service層的代碼,這里我們重新來進行單元測試

package com.artisan.o2o.service;import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Date;import org.junit.Assert; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired;import com.artisan.o2o.BaseTest; import com.artisan.o2o.dto.ShopExecution; import com.artisan.o2o.entity.Area; import com.artisan.o2o.entity.PersonInfo; import com.artisan.o2o.entity.Shop; import com.artisan.o2o.entity.ShopCategory; import com.artisan.o2o.enums.ShopStateEnum;public class ShopServiceTest extends BaseTest {@AutowiredShopService shopService;@Testpublic void testAddShop() {Shop shop = new Shop();PersonInfo personInfo = new PersonInfo();Area area = new Area();ShopCategory shopCategory = new ShopCategory();personInfo.setUserId(1L);area.setAreaId(1);shopCategory.setShopCategoryId(1L);shop.setOwner(personInfo);shop.setArea(area);shop.setShopCategory(shopCategory);shop.setShopName("咖啡店Improve");shop.setShopDesc("小工匠的咖啡店Improve");shop.setShopAddr("NanJing-Improve");shop.setPhone("9876553");shop.setPriority(99);shop.setCreateTime(new Date());shop.setLastEditTime(new Date());shop.setEnableStatus(ShopStateEnum.CHECK.getState());shop.setAdvice("審核中Improve");File shopFile = new File("D:/o2o/artisan.jpg");ShopExecution se = null;InputStream ins = null;try {ins = new FileInputStream(shopFile);se = shopService.addShop(shop, ins, shopFile.getName());} catch (FileNotFoundException e) {e.printStackTrace();}Assert.assertEquals(ShopStateEnum.CHECK.getState(), se.getState());} }

可以在addShop實現方法中增加斷點,通過debug的方式來逐步調試。

數據庫表:

圖片:


Github地址

代碼地址: https://github.com/yangshangwei/o2o

總結

以上是生活随笔為你收集整理的实战SSM_O2O商铺_11【商铺注册】Controller层的实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。