java框架之SpringMVC(2)-補充及攔截器

高級參數綁定

package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Arrays;

@Controller
public class TestController {
    /**
     * 數組參數綁定
     */
    @RequestMapping("test")
    public void test(Integer[] ids) {
        System.out.println(Arrays.toString(ids));
        /*
        [1, 2]
         */
    }
}

例:數組參數綁定
package com.zze.springmvc.pojo;

import java.util.List;

public class QueryVo {

    private List<User> users;

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}

package com.zze.springmvc.web.controller;

import com.zze.springmvc.pojo.QueryVo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Arrays;

@Controller
public class TestController {
    /**
     * 集合參數綁定
     */
    @RequestMapping("test")
    public void test(QueryVo queryVo) {
        System.out.println(Arrays.toString(queryVo.getUsers().toArray()));
        /*
        [User{id=1, name='zhangsan'}, User{id=2, name='lisi'}]
         */
    }
}

例:集合參數綁定

參數轉換器

若是要進行日期類型參數綁定,SpringMVC 默認是不支持的,須要咱們手動定義一個轉換器來告知 SpringMVC 如何轉換,以下:html

package com.zze.springmvc.web.converter;

import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * String : 源類型
 * Date : 目標類型
 */
public class DateConverter implements Converter<String,Date> {
    public Date convert(String source) {
        Date date = null;
        try {
            date = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}
com.zze.springmvc.web.converter.DateConverter : 自定義的日期轉換器
<!--自定義轉換器工廠-->
<bean id="myConverters" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <!--註冊本身定義的日期轉換器-->
        <bean class="com.zze.springmvc.web.converter.DateConverter"/>
    </property>
</bean>
<!--使用上自定義的轉換器工廠-->
<mvc:annotation-driven conversion-service="myConverters"/>
config/spring/springmvc.xml : 註冊自定義轉換器

相關注解

@RequestMapping

package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TestController {
    /**
     * 請求 /test1 和 /test2 都會指向 test 方法
     */
    @RequestMapping(value = {"test1", "test2"})
    public void test() {

    }
}
例:多路由
package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("test")
public class TestController {
    /**
     * 由於類上使用了 RequestMapping 註解,此時 test 方法的訪問路徑就爲:
     *      /test/test1 和 /test/test2
     */
    @RequestMapping(value = {"test1", "test2"})
    public void test() {

    }
}
例:配置在類上
package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class TestController {
    /**
     * 限定請求方法只能爲 GET 和 POST
     */
    @RequestMapping(value = "test",method = {RequestMethod.POST,RequestMethod.GET})
    public void test() {

    }
}
例:限定請求方式

@RequestParam

package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class TestController {
    /**
     * @RequestParam
     *  name 指定所修飾參數對應請求參數名
     *  required 指定所修飾參數是否必須
     *  defaultValue 指定所修飾參數的默認值
     */
    @RequestMapping(value = "test")
    public void test(@RequestParam(name = "pid",required = false,defaultValue = "1") Integer id) {

    }
}
例:自定義請求參數映射

請求方法的返回值

在 SpringMVC 中,請求方法的返回值除了 ModelAndView,還能夠有以下幾種方式:java

package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TestController {
    /**
     * 轉發到 jsp
     */
    @RequestMapping(value = "test")
    public String test() {
        // 由於配置了視圖解析器,這裏的 userlist 實際指向 /WEB-INF/jsp/userlist.jsp
        return "userlist";
    }
}
返回 String,轉發到 JSP
package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TestController {
    /**
     * 轉發到 Action
     */
    @RequestMapping(value = "test")
    public String test() {
        return "forward:/user/list";
    }
}
返回 String,轉發到 Action
package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TestController {
    /**
     * 重定向到 Action
     */
    @RequestMapping(value = "test")
    public String test() {
        return "redirect:/user/list";
    }
}
返回 String,重定向到 Action
package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
public class TestController {
    /**
     * 訪問原生 request 和 response API
     */
    @RequestMapping(value = "test")
    public void test(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/plain;charset=utf-8");
//        request.getRequestDispatcher("/user/list").forward(request,response); 轉發
//        response.sendRedirect("/user/list"); // 重定向
        response.getWriter().write("你好世界");
    }
}
無返回值,訪問原生 Servlet API

請求亂碼問題解決

<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>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
WEB-INF/web.xml : 解決 POST 請求亂碼
<Connector port="8080"  protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />  
tomcat - server.xml : 解決 GET 請求亂碼

全局異常處理

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>消息頁</title>
</head>
<body>
${msg}
</body>
</html>
WEB-INF/jsp/msg.jsp : 一、建立一個消息通知頁
package com.zze.springmvc.web.util;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyExceptionResolver implements HandlerExceptionResolver {
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("msg");
        modelAndView.addObject("msg", "服務器異常!");
        return modelAndView;
    }
}
com.zze.springmvc.web.util.MyExceptionResolver : 二、編寫自定義的異常處理器
<!--註冊全局異常處理器-->
    <bean class="com.zze.springmvc.web.util.MyExceptionResolver"/>
config/spring/springmvc.xml : 三、直接註冊到 Spring 容器中就能夠生效

文件上傳

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.2.2</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>
pom.xml : 一、添加文件上傳依賴
<!--
配置多媒體處理器
注意:這裏的 id 必須使用 multipartResolver
-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--限制單次文件上傳大小不超過 8m-->
    <property name="maxUploadSize" value="8388608"/>
</bean>
config/spring/springmvc.xml : 二、配置多媒體處理器
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>圖片上傳</title>
</head>
<body>
<form action="/fileupload" method="post" enctype="multipart/form-data">
    <input type="file" name="picFile">
    <input type="submit" value="上傳">
</form>
</body>
</html>
WEB-INF/jsp/fileupload.jsp : 三、編寫文件上傳頁面
package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@Controller
public class TestController {

    @RequestMapping(value = "fileupload", method = RequestMethod.GET)
    public String upload() {
        return "fileupload";
    }

    @RequestMapping(value = "fileupload", method = RequestMethod.POST)
    public String upload(Model model, MultipartFile picFile) throws IOException {
        File file = new File("D:/upload/" + picFile.getOriginalFilename());
        picFile.transferTo(file);
        model.addAttribute("msg", "上傳成功");
        return "fileupload";
    }
}
com.zze.springmvc.web.controller.TestController : 四、編寫文件上傳服務端代碼
// 新建目錄 D:/upload
// 瀏覽器訪問 localhost:8080/fileupload
五、測試:

JSON交互

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.4.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.4.2</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.2</version>
pom.xml : 加入 json 支持依賴
package com.zze.springmvc.web.controller;

import com.zze.springmvc.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.ParseException;
import java.text.SimpleDateFormat;

@Controller
public class TestController {
    /**
     * 返回 JSON 格式數據
     * 返回值設爲要序列化的類型,並在方法上添加上 @ResponseBody 註解
     */
    @RequestMapping("getUser")
    @ResponseBody
    public User getUser() throws ParseException {
        User user = new User();
        user.setId(1);
        user.setName("張三");
        user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1998-1-1"));
        user.setGender("男");
        user.setAddress("河北");
        return user;
    }
}

返回 JSON 格式數據
package com.zze.springmvc.web.controller;

import com.zze.springmvc.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class TestController {

    /**
     * 一、使用 @RequestBody 修飾入參
     * 二、請求方式爲 POST,content-type 爲 application/json
     * 三、json 中字段名與 pojo 屬性一致
     */
    @RequestMapping("addUser")
    @ResponseBody
    public User addUser(@RequestBody User user){
        System.out.println(user);
        user.setGender("女");
        return user;
    }
}

接收 JSON 格式數據

要使用該方式進行 JSON 交互,必須配置註解驅動。web

<!--配置註解驅動,至關於同時使用最新處理器映射器和處理器適配器,同時對 JSON 數據響應提供支持-->
<mvc:annotation-driven/>

Restful風格

package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class TestController {

    @RequestMapping("user/{id}")
    @ResponseBody
    public void getUser(@PathVariable Integer id){
        System.out.println(id);
        /*
        請求 localhost:8080/user/1
        控制檯輸出: 1
         */
    }
}
com.zze.springmvc.web.controller.TestController

攔截器

SpringMVC 的處理器攔截器相似於 Servlet 開發中的過濾器 Filter,用於對處理器進行預處理和後處理。spring

package com.zze.springmvc.web.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor1 implements HandlerInterceptor {
    /**
     * 處理器執行前執行
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor.preHandle");
        return true; // true:放行 false:攔截
    }

    /**
     * 處理器執行後, modelAndView 返回前執行
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor.postHandle");
    }

    /**
     * 處理器執行後執行
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor.afterCompletion");
    }
}
com.zze.springmvc.web.interceptor.MyInterceptor1 : 一、定義攔截器 1
package com.zze.springmvc.web.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor2 implements HandlerInterceptor {
    /**
     * 處理器執行前執行
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor.preHandle");
        return true; // true:放行 false:攔截
    }

    /**
     * 處理器執行後, modelAndView 返回前執行
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor.postHandle");
    }

    /**
     * 處理器執行後執行
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor.afterCompletion");
    }
}
com.zze.springmvc.web.interceptor.MyInterceptor2 : 二、定義攔截器 2
<!--註冊攔截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--攔截全部請求,包括二級以上目錄-->
        <mvc:mapping path="/**"/>
        <!--指定路徑不攔截-->
        <mvc:exclude-mapping path="/login"/>
        <bean class="com.zze.springmvc.web.interceptor.MyInterceptor1"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.zze.springmvc.web.interceptor.MyInterceptor2"/>
    </mvc:interceptor>
</mvc:interceptors>
config/spring/springmvc.xml : 三、註冊攔截器
package com.zze.springmvc.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class TestController {

    @RequestMapping("test")
    public void test() {
        System.out.println("from TestController.test");
    }
}
com.zze.springmvc.web.controller.TestController : 四、編寫測試 Controller

五、測試,請求 localhost:8080/test ,控制檯輸出以下:
相關文章
相關標籤/搜索