SpringMVC進階及文件上傳案例

SpringMVC進階

第一節 Controller方法(Handler)的返回值

1.1 返回ModelAndView

  • 講解略, SpringMVC第一天 已使用

1.2 返回字符串(直接返回邏輯視圖名,數據使用Model和ModelMap封裝)

  • ModelAndView = ModelMap+ view(邏輯視圖名)
  • 如今直接將邏輯視圖名以字符串形式return(文件名)
  • Model接口方法 addAttribute(String key,Object value)存儲鍵值對,將被存儲到request域中
/**
     *  返回字符串,返回視圖邏輯名,文件名
     *  Model接口封裝數據
     *  鍵值對存儲request域對象
     */
    @RequestMapping("gotoResultModel")
    public String gotoResultModel(Model model){
        //封裝數據
        model.addAttribute("nowDate", new Date()+"====gotoResultModel");
        //指定頁面
        return "result";
    }
<fieldset>
    <h4>方法返回值String, 參數爲 Model類型</h4>
    <a href="${pageContext.request.contextPath}/default/gotoResultModel.do">測試</a>
</fieldset>
  • ModelMap封裝數據,方法addAttribute(String key,Object value)存儲鍵值對,將被存儲到request域中
/**
 *  返回字符串,返回視圖邏輯名,文件名
 *  ModelMap類封裝數據
 *  鍵值對存儲request域對象
 *  ModelMap類有獲取的方法,而Model接口沒有
 */
    @RequestMapping("gotoResultModelMap")
    public String gotoResultModelMap(ModelMap modelMap){
        //封裝數據
        modelMap.addAttribute("nowDate", new Date()+"====gotoResultModelMap");
        //指定頁面
        return "result";
    }
<fieldset>
        <h4>方法返回值String, 參數爲 ModelMap類型</h4>
        <a href="${pageContext.request.contextPath}/default/gotoResultModelMap.do">測試</a>
    </fieldset>

1.3 沒有返回值(Request, Response)

  • request對象實現轉發
/**
     * 返回值爲void類型, 使用Request對象 實現頁面跳轉(注意: 沒法將SpringMVC 提供的Model, ModelMap封裝的數據 請求轉發到目標頁面)
     * @param modelMap
     * @return
     */
    @RequestMapping("gotoResultRequest")
    public void gotoResultRequest(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //經過SpringMVC框架把封裝數據到Request域中( 跳轉頁面的方式必須採用的是SpringMVC框架提交的方式, 才能把數據 傳遞過去 )
        modelMap.addAttribute("nowDate", new Date()+"====gotoResultRequest");
        //指定頁面
        //請求轉發
//        request.setAttribute("鍵", "值");
        request.getRequestDispatcher("/default/gotoResultModelMap.do").forward(request, response);
    }
<fieldset>
        <h4>方法返回值void, 使用Request對象進行跳轉頁面</h4>
        <a href="${pageContext.request.contextPath}/default/gotoResultRequest.do">測試</a>
    </fieldset>
  • response對象實現重定向
/**
     * 返回值爲void類型, 使用Response跳轉頁面 (注意: 沒法將SpringMVC 提供的Model, ModelMap封裝的數據 重定向到目標頁面)
     */
    @RequestMapping("gotoResultResponse")
    public void gotoResultResponse(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //經過SpringMVC框架把封裝數據到Request域中( 跳轉頁面的方式必須採用的是SpringMVC框架提交的方式, 才能把數據 傳遞過去 )
        modelMap.addAttribute("nowDate", new Date()+"====gotoResultResponse");
        //指定頁面
        //重定向
        //response.sendRedirect("http://localhost:8080/default/gotoResultModelMap.do");
        response.sendRedirect(request.getContextPath()+"/default/gotoResultModelMap.do");
    }
<fieldset>
        <h4>方法返回值void, 使用Response對象進行跳轉頁面</h4>
        <a href="${pageContext.request.contextPath}/default/gotoResultResponse.do">測試</a>
    </fieldset>
  • response對象響應字符串
/**
 * 直接使用response對象響應字符串
 */
@RequestMapping("gotoResultResponseSendString")
public void gotoResultResponseString(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.getWriter().print("Hello MVC");
}
<fieldset>
    <p>05測試——SpringMVC(Controller方法沒有返回值,response響應字符串)</p>
    <a href="${pageContext.request.contextPath}/default/gotoResultResponseSendString.action">點擊測試</a>
</fieldset>

1.4 SpringMVC格式: 實現重定向和轉發的字符串寫法

/**
     * 返回值爲String類型, 經過SpringMVC框架 使用重定向 實現頁面跳轉(注意: 不能夠將SpringMVC 提供的Model, ModelMap封裝的數據 請求轉發到目標頁面)
     *
     * 格式用法: redirect:請求的地址
     */
    @RequestMapping("gotoResultRedirect")
    public String gotoResultRedirect(ModelMap modelMap){
        //經過SpringMVC框架把封裝數據到Request域中( 跳轉頁面的方式必須採用的是SpringMVC框架提交的方式, 才能把數據 傳遞過去 )
        modelMap.addAttribute("nowDate", new Date()+"====gotoResultRedirect");
        //指定頁面
        //請求轉發
        return "redirect:/default/gotoResultModelMap.do";
    }

    /**
     * 返回值爲String類型, 經過SpringMVC框架 使用請求轉發 實現頁面跳轉(注意: 能夠將SpringMVC 提供的Model, ModelMap封裝的數據 請求轉發到目標頁面)
     *
     * 格式用法: forward:請求的地址
     */
    @RequestMapping("gotoResultForward")
    public String gotoResultForward(ModelMap modelMap){
        //經過SpringMVC框架把封裝數據到Request域中( 跳轉頁面的方式必須採用的是SpringMVC框架提交的方式, 才能把數據 傳遞過去 )
        modelMap.addAttribute("nowDate", new Date()+"====gotoResultForward");
        //指定頁面
        //請求轉發
        return "forward:/default/gotoResultModelMap.do";
    }
  • index.jsp
<fieldset>
    <h4>方法返回值String, 使用SpringMVC的 請求轉發進行跳轉頁面</h4>
    <a href="${pageContext.request.contextPath}/default/gotoResultForward.do">測試</a>
</fieldset>

<fieldset>
    <h4>方法返回值String, 使用SpringMVC的 重定向進行跳轉頁面</h4>
    <a href="${pageContext.request.contextPath}/default/gotoResultRedirect.do">測試</a>
</fieldset>

第二節 Json格式數據實現Ajax交互

json數據是我們企業級開發數據交互常常使用的一種方式,它比較輕量級,格式比較清晰html

交互:前端和後端的互動前端

  • 前端傳遞json字符串到後臺,後臺如何可以自動轉換爲pojo對象
  • @RequestBody註解,將JSON 字符串轉換爲POJO對象
    • 做用:用於獲取請求體(按照http協議進行一個完整的封裝,每每都是由請求頭+請求體等組成)內容,不適用於Get請求方式
  • 後臺return 對象,可否前端直接接收到json格式的字符串
    • @ResponseBody註解
      • 做用:該註解用於將Controller的方法返回的對象轉換爲json字符串返回給客戶端

AJax的格式:

Vue的Ajax異步請求 axios發送get請求
axios.get('/user?id=12345')
    .then(response => {
    	console.log(response.data);
	})
    .catch(error => {
    	console.dir(error)
	});
或
axios.get('/user',{
        params:{
			id:12345
        }
	})
    .then(response => {
    	console.log(response.data);
	})
    .catch(error => {
    	console.dir(error)
	});
Vue的Ajax異步請求 axios發送post請求
axios.post('/user', json對象)
    .then(response => {
		console.log(response.data);
	})
    .catch(error => {
		console.dir(err)
    });
或
axios.post('/user', 參數字符串)
    .then(response => {
		console.log(response.data);
	})
    .catch(error => {
		console.dir(err)
    });

代碼演示

1. pom.xml
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.9.0</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.0</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.9.0</version>
    </dependency>
</dependencies>
2.index.jsp頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首頁</title>
    <%--導入js文件--%>
    <script src="js/vue.js"></script>
    <script src="js/axios-0.18.0.js"></script>
</head>
<body>
    SpringMVC框架的進行 Ajax 交互

    <fieldset>
        <h4>Ajax 的Json數據</h4>
        <div id="app">
            <input type="button" @click="clickMe()" value="發送Ajax數據">
            <%--使用插值表達式--%>
            {{ userList }}
        </div>
    </fieldset>
</body>
</html>
<script>
    <!-- 建立一個Vue對象 -->
    new Vue({
        el: '#app',
        data:{
            userList: []
        },
        methods:{
            clickMe:function(){

                var params = {id:1, username:'你好', sex:'男'};
                //發起ajax
               axios.post("/ajax/testAjax.do", params)
                   .then(response => {
                       //成功
                       //console.log(response.data);
                       this.userList = response.data
                   }).catch(error =>{
                       //失敗
                       console.dir(error);
                   });
            }
        }
    })
</script>
3. 處理器 AjaxController.java
/**
 * @RestController: 至關於在類上標記了Controller
 *                  至關於在每個處理器方法上標記了@ResponseBody
 *
 * @RestController比@Controller 多了 @ResponseBody
 *
 * @ResponseBody: 做用是能夠把返回值以流的形式返回ajax
 *                能夠把對象轉換爲json串
 * @RequestBody: 把請求體(json字符串)轉換對象, 須要引入json須要的依賴
 */
package com.itheima.controller;

//@Controller
//@ResponseBody
@RestController
@RequestMapping("ajax")
public class AjaxController {

    //測試Ajax的方法
    @RequestMapping("testAjax")
    //@ResponseBody
    public List<User> testAjax(@RequestBody User user){
        //打印接受的數據
        System.out.println("user = " + user);

        //準備給客戶端瀏覽器返回的json數據
        User user1 = new User();
        user1.setId(1);
        user1.setUsername("王五");
        user1.setSex("男");

        User user2 = new User();
        user2.setId(2);
        user2.setUsername("趙六");
        user2.setSex("女");

        ArrayList<User> userList = new ArrayList<User>();
        userList.add(user1);
        userList.add(user2);

        return userList;
    }
}

第三節 SpringMVC對Restful風格URL的支持(瞭解)

3.1http請求方式:get post put delete

  • get:主要是想作selectvue

  • post:主要是想作insertjava

  • put:主要是想作updateios

  • delete:主要是想作deleteweb

  • 以上是http協議的標準,可是你用post請求也徹底能夠完成crud操做(無非就是把參數傳遞到後臺對應處理便可)ajax

3.2 什麼是RESTful?

RESTful就是一個資源定位及資源操做的風格。不是標準也不是協議,只是一種風格。基於這個風格設計的軟件能夠更簡潔,更有層次。spring

  • 資源:互聯網全部的事物均可以被抽象爲資源 urljson

  • (只要互聯網上的事物能夠用一個url來表示,那麼它就是一個資源)axios

  • 資源操做:使用POST、DELETE、PUT、GET,使用不一樣方法對資源進行操做。

    分別對應添加、刪除、修改、查詢。

3.3 傳統方式操做資源

操做啥(原來url)?操做誰(傳入的參數)

url中先定義動做,而後傳遞的參數代表這個動做操做的是哪一個對象(數據)

先定位動做,而後定位對象

http://localhost:8080/springmvc02/user/queryUserById.do?id=1查詢

http://localhost:8080/springmvc02/user/saveUser.do 新增

http://localhost:8080/springmvc02/user/updateUser.do 更新

http://localhost:8080/springmvc02/user/deleteUserById.do?id=1 刪除

3.3 使用RESTful操做資源

先定義對象

http://localhost:8080/springmvc02/user/1 (操做的對象) 查詢,GET

http://localhost:8080/springmvc02/user 新增,POST

http://localhost:8080/springmvc02/user 更新,PUT

http://localhost:8080/springmvc02/user/1 刪除,DELETE

3.4 HiddenHttpMethodFilter過濾器

因爲瀏覽器 form 表單只支持 GET 與 POST 請求,而DELETE、PUT 等 method 並不支持,Spring3.0以後添加了一個過濾器,能夠將瀏覽器請求改成指定的請求方式,發送給咱們的控制器方法,使得支持 GET、POST、PUT 與DELETE請求.

<?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_3_1.xsd"
         version="3.1">

    <!--配置表單 可以使用POST、DELETE、PUT、GET,使用不一樣方法對資源進行操做-->
    <filter>
        <filter-name>methodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>methodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
  • 增長請求參數_method,該參數的取值就是咱們須要的請求方式
package com.itheima.controller;

@RestController()
public class RestFulController {
    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
    public String find(@PathVariable("id") Integer ids){
        System.out.println("get:"+id);
        return "show";
    }

    @RequestMapping(value = "/user/{id}", method = RequestMethod.POST)
    public String save(@PathVariable("id") Integer id){
        System.out.println("post:"+id);
        return "show";
    }

    //@ResponseBody
    @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
    public String update(@PathVariable("id") Integer id){
        System.out.println("put:"+id);
        return "show";
    }

    //@ResponseBody
    @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
    public String delete(@PathVariable("id") Integer id){
        System.out.println("delete:"+id);
        return "show";
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首頁</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/user/1">get請求</a>

<form action="${pageContext.request.contextPath}/user/1" method="post">
    <input type="submit" value="post請求">
</form>

<form action="${pageContext.request.contextPath}/user/1" method="post">
    <%--
    1. 該表單的請求方式還必須是post
    2. 添加一個隱藏域,屬性名是_method ,值:put或者delete
    3. jsp僅僅支持get和post請求,全部put和delete請求的處理器(方法)必須標記@ResponseBody(或者在類上標記@RestController)
    --%>
    <input type="hidden" name="_method" value="PUT">
    <input type="submit" value="put請求">
</form>

<form action="${pageContext.request.contextPath}/user/1" method="post">
    <%--
    1. 該表單的請求方式還必須是post
    2. 添加一個隱藏域,屬性名是_method ,值:put或者delete
    3. jsp僅僅支持get和post請求,全部put和delete請求的處理器(方法)必須標記@ResponseBody(或者在類上標記@RestController)
    --%>
    <input type="hidden" name="_method" value="DELETE">
    <input type="submit" value="delete請求">
</form>
</body>
</html>

第四節 SpringMVC實現文件上傳

前提

1. form表單請求方式必須是post
2. 添加form表單的參數:enctype 多部件表單類型 enctype="multipart/form-data"
3. 引入依賴:commons-upload, commons-io

一、文件上傳

a、引入依賴
<!-- 引入fileUpload會自動依賴commons-io --> 
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
b、spring-mvc.xml 配置文件
<!-- 配置文件上傳解析器 -->
<!-- id的值是固定的-->
<bean id="multipartResolver"
				class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 設置上傳文件的最大尺寸爲5MB -->
		<property name="maxUploadSize">
			<value>5242880</value>
		</property>
</bean>
c、頁面配置
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
        <input type="file" name="uploadFile">
        <input type="text" name="username">
        <input type="submit" value="上傳">
    </form>
d、controller代碼
@Controller()
public class UploadController {

    /**
     * 本地上傳
     MultipartFile接口方法:
     - String getOriginalFilename()獲取上傳文件名
     - byte[] getBytes()文件轉成字節數組
     - void transferTo(File file)轉換方法,將上傳文件轉換到File對象
     */
    @RequestMapping("/upload")
    public String upload(MultipartFile uploadFile, HttpServletRequest request){

        //32位的隨機內容的字符串
        String uuid = UUID.randomUUID().toString().replace("-","");
        //文件名稱
        String filename = uploadFile.getOriginalFilename();
        System.out.println("filename = " + filename);

        //文件上傳
        String realPath = request.getSession().getServletContext().getRealPath(request.getContextPath() + "/upload");
        File path = new File(realPath, uuid+filename);
        try {
            uploadFile.transferTo(path);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "success";
    }
}

二、跨服上傳

a、引入依賴
<!--引入jersey服務器的包-->
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-core</artifactId>
      <version>1.18.1</version>
    </dependency>
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
      <version>1.18.1</version>
    </dependency>
b、修改tomcat配置
1. tomcat默認不能跨服上傳的
2. tomcat/conf/web.xml 	
		
    <!--須要添加的-->
	<init-param>
    	<param-name>readonly</param-name>
    	<param-value>false</param-value>
    </init-param>
c、配置圖片服務器
1. 建立一個web項目
2. 配置一個tomcat,與原來tomcat端口號不一致
3. 在webapp目錄下建立一個upload目錄,空的文件夾不會編譯,須要在upload目錄添加(任意)一個文件
d、修改controller代碼
/**
     * 跨服上傳
       MultipartFile接口方法:
        - String getOriginalFilename()獲取上傳文件名
        - byte[] getBytes()文件轉成字節數組
     */
    @RequestMapping("/upload")
    public String upload(MultipartFile uploadFile, HttpServletRequest request){

        //32位的隨機內容的字符串
        String uuid = UUID.randomUUID().toString().replace("-","");
        //文件名稱
        String filename = uploadFile.getOriginalFilename();
        System.out.println("filename = " + filename);

        //跨服務器上傳
        String serverUrl = "http://localhost:8081/upload";
        //向服務器上傳的客戶端對象
        Client client = Client.create();
        WebResource resource = client.resource(serverUrl + "/" + uuid + filename);
        //執行上傳文件到 指定的服務器
        //轉出字節數組開始上傳
        try {
            resource.put(String.class, uploadFile.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "success";
    }

第五節 SpringMVC中的統一異常處理

package com.itheima.exception;

@Component
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
    /**
     * 解析異常
     * @param request  請求對象
     * @param response 響應對象
     * @param handler 處理器
     * @param ex  異常對象
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
//        System.out.println("出現了異常");
        ex.printStackTrace();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message", "系統錯誤,請聯繫管理員!!!");
        modelAndView.setViewName("error");
        return modelAndView;
    }
}
  • springmvc.xml配置異常處理器
<bean class="com.itheima.exception.MyHandlerExceptionResolver"></bean>
相關文章
相關標籤/搜索