1. SpringMVC控制器業務操作 在SpringMVC第二節中我們瞭解到mvc控制器處理頁面url請求返迴響應視圖,除了這些操作外,控制器還需要處理更重要的業務,如:接收前臺頁面傳遞的參數、綁定數據到頁面、返回json數據、文件上傳、文件下載等業務操作。 1.1.參數接收 1.1.1. 配置請 ...
1. SpringMVC控制器業務操作
在SpringMVC第二節中我們瞭解到mvc控制器處理頁面url請求返迴響應視圖,除了這些操作外,控制器還需要處理更重要的業務,如:接收前臺頁面傳遞的參數、綁定數據到頁面、返回json數據、文件上傳、文件下載等業務操作。
1.1.參數接收
1.1.1. 配置請求編碼過濾器
SpringMVC框架本身沒有處理請求編碼,在前臺參數接收Post請求的時候,可能會出現編碼亂碼的問題,而Spring框架為我們提供了一個請求編碼過濾器,我們只需要在web.xml中配置一個請求編碼過濾器即可:
web.xml中配置UTF-8編碼如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--配置post請求編碼亂碼處理過濾器--> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
1.1.2. 參數接收方式
GET接收方式:
① 使用方法的形參接收:註意形參要和請求參數一致;
@Controller @RequestMapping(value = "/paramController", method = RequestMethod.GET) public class ParamRecCotroller { /** * 參數接收方式一:使用形參接收,前臺get請求傳入的參數名和方法接收的參數名保持一致 * @param username * @param age */ @RequestMapping("/insert") public void insert(String username, Integer age){ System.out.println(username); System.out.println(age); } }
前臺get參數傳遞方式:
http://localhost:8080/paramController/insert?username=”青海”&age=21
獲取到的參數信息:
② 如果形參名稱和前臺傳入的參數名不一致,需要使用@RequestParam(value=”前臺參數名”)進行映射對應;
@Controller @RequestMapping(value = "/paramController", method = RequestMethod.GET) public class ParamRecCotroller { /** * 參數接收方式二:前臺get傳遞的參數url與方法形參某個參數不一致,需要使用@@RequestParam(value = "前臺參數名") * @param username * @param age */ @RequestMapping("/insert") public void insert(@RequestParam(value = "name") String username, Integer age){ System.out.println(username); System.out.println(age); } }
前臺get參數傳遞方式:
http://localhost:8080/paramController/insert?name=”青海”&age=21
獲取到的參數信息:
③ 直接使用一個Domain對象接收前臺參數,會根據Domain中的屬性來進行匹配裝值;
@Controller @RequestMapping(value = "/paramController", method = RequestMethod.GET) public class ParamRecCotroller { /** * 參數接收方式三:直接使用一個Domain對象來接收前臺參數,每個前臺參數必須和User裡面的屬性名保持一致(前臺參數直接映射屬性), * 不然無法獲取對應的參數值,而且必須保證User內有一個無參數的構造器 * @param user */ @RequestMapping("/insert") public void insert(User user){ System.out.println(user); } }
對應Domain中的User類:
public class User { private String username; private Integer age; private String password; public User() { } public User(String username, Integer age, String password) { this.username = username; this.age = age; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", age=" + age + ", password='" + password + '\'' + '}'; } }
前臺get參數傳遞方式:
http://localhost:8080/paramController/insert?username=”青海”&age=21&password= 3454
獲取到的參數信息:
④ 使用原始的HttpServletRequest來獲取請求參數信息;
@Controller @RequestMapping(value = "/paramController", method = RequestMethod.GET) public class ParamRecCotroller { /** * 參數接收方式四:直接使用HttpServletRequest獲取 * @param request */ @RequestMapping("/insert") public void insert(HttpServletRequest request){ String username = request.getParameter("username"); Integer age = Integer.valueOf(request.getParameter("age")); String pwd = request.getParameter("pwd"); System.out.println(username); System.out.println(age); System.out.println(pwd); } }
前臺get參數傳遞方式:
http://localhost:8080/paramController/insert?username=”青海”&age=21&pwd= 3454
獲取到的參數信息:
⑤ Restful風格請求參數傳遞:直接在映射地址上使用{id}占位符,id表示傳遞的參數名,方法接收時對方法的形參使用@PathVariable(“id”),這裡面的id應該和映射地址上的id名稱保持一致;
@Controller @RequestMapping(value = "/paramController", method = RequestMethod.GET) public class ParamRecCotroller { /** * 參數接收方式四:前臺請求地址中包含id參數信息,使用restful風格映射對應相同的提取參數 * 註意:前臺參數名稱必須與restful風格的參數一一對應,名稱一致 * @param idVal */ @RequestMapping("/insert/{id}") public void getUserById(@PathVariable(value = "id") Integer idVal){ System.out.println(idVal); } }
前臺get參數傳遞方式:
http://localhost:8080/paramController/insert/5
獲取到的參數信息:
1.2.數據傳遞
簡單地說,就是使用SpringMVC中Controller向前臺頁面傳遞數據。使用Controller進行數據傳遞的方式主要有四種傳遞方式:
① 通過ModelAndView對象傳遞
@Controller @RequestMapping("/dataController") public class DataTransController { /** * 頁面展示返回數據方式一:通過ModelAndView對象傳遞 * setViewName:返回一個結果視圖 * addObject(name, value):可以通過name到對應的顯示頁面上去取數據,value表示顯示的數據, * 也可以傳遞對象來取值 * @return */ @RequestMapping("/getData") public ModelAndView getDataRes(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("msg", "隨便寫一個msg信息"); modelAndView.setViewName("/WEB-INF/views/dataView.jsp"); User user = new User("青海", 21, "2332"); modelAndView.addObject("user", user); return modelAndView; } }
對應jsp頁面取值:
<body> ${msg}<br/> ${user}<br/> ${user.username}<br/> ${user.age}<br/> ${user.password}<br/> </body>
對應頁面展示數據信息如下:
② 通過Model對象進行數據傳遞;
@Controller @RequestMapping("/dataController") public class DataTransController { /** * 頁面展示返回數據方式二:通過Model對象傳遞 * return:返回一個結果視圖 * addObject(name, value):可以通過name到對應的顯示頁面上去取數據,value表示顯示的數據, * 也可以傳遞對象來取值 * @return */ @RequestMapping("/getModel") public String getModelRes(Model model){ model.addAttribute("msg", "Model對象的信息"); User user = new User("青海", 21, "2332"); model.addAttribute("user", user); return "/WEB-INF/views/modelDataView.jsp"; } }
對應jsp頁面取值:
${msg}<br/> ${user}<br/> ${user.username}<br/> ${user.age}<br/> ${user.password}<br/>
對應頁面展示數據信息如下:
③ 通過HttpServletRequest對象進行數據傳遞;
這種方式與Model對象傳遞方式類似,就是把參數換成HttpServletRequest對象,調用request.setAttribute(“msg”, 傳遞信息或者對象信息),這裡就不再詳細說明;
1.3.SpringMVC返回JSON數據
1.3.1. 實現方式
SpringMVC返回JSON數據格式需要導入Jackson的jar包,Jackson是解析JSON和XML的一個框架,簡單易用,性能較高。
在項目中我們需要導入Jackson json的工具包,如下:
jackson-annotations-2.5.0.jar
jackson-core-2.5.0.jar
jackson-databind-2.5.0.jar
對應Controller實現方式:
@Controller @RequestMapping("/jsonController") public class JsonDemoController { @RequestMapping("/getJson") //加上@ResponseBody註解,返回值是通過JSON流的方式輸出,Springmvc獲取返回值,把對象自動轉換為JSON //然後通過response.getWriter().print(jsonString)輸出在前臺頁面 @ResponseBody public User getJsonUserData(){ User user = new User("青海", 21, "2332"); return user; } }
前臺頁面進行數據訪問,訪問地址:http://localhost:8080/jsonController/getJson
同樣可以返回一個JSON集合,對應實現如下:
@Controller @RequestMapping("/jsonController") public class JsonDemoController { @RequestMapping("/getJsonList") @ResponseBody public List<User> getJsonUserLstData(){ User user1 = new User("青海", 21, "2332"); User user2 = new User("俊傑", 23, "3306"); List<User> userList = new ArrayList<>(); userList.add(user1); userList.add(user2); return userList; } }
前臺頁面進行數據訪問,訪問地址:http://localhost:8080/jsonController/getJsonList
1.3.2 日期型數據格式化
在處理日期Date類型的數據,如果後臺不進行處理,那麼預設返回的是時間戳的json日期格式:比如"birthday":1584261823034,此時需要在Domain的日期get屬性方法上加上@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
/** * 如果不加JsonFormat,預設返回的日期格式是時間戳:比如"birthday":1584261823034 * 需要在日期屬性Date的getXXX()方法上加上自定義的日期格式@JsonFormat註解 * @return */ @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8") public Date getBirthday() { return birthday; }
同理,在前臺向後臺傳入字元串類型的Date數據時,需要在Domain的日期set屬性方法上加上@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss"),後臺才能接收到對應的Date參數並轉換為日期數據到後臺
/** * 前臺Get方式brithday以字元形式傳遞,需要加上@DateTimeFormat註解, * 才能向後臺傳遞Date類型數據 * @param birthday */ @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") public void setBirthday(Date birthday) { this.birthday = birthday; }
1.4.SpringMVC文件上傳
SpringMvc自己沒有實現文件上傳,需要使用apache.commons.fileupload,需要導入文件上傳相關的包:
com.springsource.org.apache.commons.fileupload-1.2.0.jar
com.springsource.org.apache.commons.io-1.4.0.jar
創建FileUploadController:
@Controller @RequestMapping public class FileUploadController { //通過get請求,返回一個文件上傳的jsp頁面--結果視圖 @RequestMapping(value = "/upload", method = RequestMethod.GET) public String uploadFileGet(){ return "/WEB-INF/views/upload.jsp"; } //文件上傳的實現方法 @RequestMapping(value = "/upload", method = RequestMethod.POST) public String uploadFilePost(String name, MultipartFile imge, HttpServletRequest request) throws IOException { //獲取上傳文件的原始文件名 String oriFilename = imge.getOriginalFilename(); //獲取文件名的尾碼 String suffix = FilenameUtils.getExtension(oriFilename); //產生一個隨機的文件名 String uuidName = UUID.randomUUID().toString(); String fileName = uuidName + "." +suffix; //獲取文件的保存路徑 String fileDir = request.getServletContext().getRealPath("/upload"); //使用File流來寫入文件 File file = new File(fileDir, fileName); //文件夾不存在,就創建一個保存路徑 if(!file.getParentFile().exists()){ file.getParentFile().mkdirs(); } //IO流的拷貝 IOUtils.copy(imge.getInputStream(), new FileOutputStream(file)); return "/WEB-INF/views/upload.jsp"; } }
準備jsp上傳頁面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>文件上傳頁面</title> </head> <body> <!—文件上傳:必須寫:enctype="multipart/form-data"—> <form action="/upload" method="post" enctype="multipart/form-data"> 用戶名:<input type="text" name="name"/><br/> 頭像:<input type="file" name="imge"/><br/> <input type="submit" value="提交"/> </form> </body> </html>
在applicationContext-mvc.xml中配置multipartResolver:
<!--配置文件上傳解析器:id="multipartResolver",這個id不能亂寫,還可以 設置一個maxUploadSize屬性,就是上傳文件的大小--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize"> <value>2000000000</value> </property> </bean>
1.5. ViewResolver視圖解析器
前面我們在Controller中返回ModelAndView結果視圖時,如果是多個方法,需要一一返回結果視圖,結果視圖重覆的內容還是需要寫一遍,比較麻煩:
使用ViewResolver視圖解析器配置返回的結果視圖.jsp,可以設置視圖路徑的前尾碼,該配置可以讓我們寫視圖路徑的時間更加簡單。
具體需要在applicationContext-mvc.xml中配置如下內容:
<!--配置預設的視圖解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>
之後在Controller中即可簡化視圖訪問的寫法:
@Controller @RequestMapping("/resolver") public class ResolverController { @RequestMapping("/demo1") public ModelAndView demo1(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("resolver_demo1"); return modelAndView; } @RequestMapping("/demo2") public ModelAndView demo2(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("resolver_demo2"); return modelAndView; } }
對應前臺的頁面訪問: