SpringMVC 註解實現參數映射

image-20200620175456961

參考資料:https://spring-mvc.linesh.tw/

1. 請求參數映射

@RequestMapping 註解的作用是建立請求 URL 和處理方法之間數據的對應關係。

該註解可以作用在方法和類上:

  • 作用在類上:一級訪問目錄
  • 作用在方法上:二級訪問目錄

注意:/ 表示應用的根目錄開始,路徑上不能只寫一個 /

1.1 RequestMapping

屬性:

path: 指定請求路徑的 url
value: value 屬性和 path 屬性是一樣的
method: 指定該方法的請求方式
params: 指定限制請求參數的條件
headers: 發送的請求中必須包含的請求頭

1.2 請求參數的映射

映射機制:
表單提交的數據都是 k=v 格式的,如 username=jack&password=123
SpringMVC 的參數映射過程是把表單提交的請求參數,作爲控制器中方法的參數進行映射的

映射要求

提交表單的 name屬性 和 形參的名稱 必須相同,否則獲取到的爲 null。

支持類型

  • 基本數據類型和字符串類型
  • 實體類型(JavaBean)
  • 集合數據類型(List、map集合等)
  • 日期類型轉換處理(Date)
1.2.1 基本類型/字符串屬性封裝

提交表單的name和參數的名稱必須相同的,區分大小寫。

1.2.2 實體類屬性封裝

要求提交表單的 name 和 JavaBean 中的屬性名稱需要一致,如果一個 JavaBean 類中包含其他的引用類型,那麼表單的name屬性需要編寫成:對象.屬性

1.2.3 集合屬性封裝
  • list[index].屬性名
  • map['key'].屬性名

注意:如果請求參數是中文,可以在 web.xml 中配置 Spring 提供的字符集過濾器來解決中文亂碼問題

User

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;

    private List<Car> carList;
    private Map<String, Car> carMap;

    private Date birth;
}

UserController

@Controller // spring 三層中的控制層註解
@RequestMapping("/user") // 類上:指定控制器即 Servlet 的一級目錄
public class UserController {

    // <a href="user/login">登陸1</a>
    @RequestMapping("/login") // 方法上:指定控制器即 Servlet 的二級目錄
    public String login() {
        System.out.println("login...");
        return "/success.jsp";
    }

    //name=id 與形參 id 相同: <a href="user/test_param?id=2001">登陸2</a>
    @RequestMapping("/test_param")
    public void test_param(String id) {
        System.out.println("id=" + id);
    }

    // @RequestParam 註解映射 name 名稱爲相同:<a href="user/test_param2?id=2001&name=張三">登陸3</a>
    @RequestMapping("/test_param2")
    public void test_param2(@RequestParam("id") String uid, String name) {
        System.out.println("uid=" + uid + ", name=" + name);
    }

    /**
     * 實體類型 + 集合類型 + 日期類型的映射
     * <form action="user/test_entity" method="get">
     *     編號:<input type="text" name="id"> <br>
     *     姓名:<input type="text" name="username"> <br>
     *     密碼:<input type="password" name="password"> <br>
     *     list:<input type="text" name="carList[1].cname"> <br>
     *     list:<input type="text" name="carList[2].cname"> <br>
     *     map: <input type="text" name="carMap['mycar'].cname"> <br>
     *
     *     date:<input type="date" name="birth">
     *     <input type="submit">
     * </form>
     */
    @RequestMapping("/test_entity")
    public void test_entity(User user) {
        System.out.println(user);
    }
}

web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <display-name>Archetype Created Web Application</display-name>

    <!--配置中文亂碼過濾器-->
    <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>

    <!--配置前端控制器-->
    <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>

springmvc.xml

    <!--開啓註解掃描-->
    <context:component-scan base-package="com.demo"/>

    <!--視圖解析對象-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp"/>
    </bean>

    <!--開啓SpringMVC框架註解支持-->
    <mvc:annotation-driven/>
1.2.4 Date類型封裝

如果對象的屬性中有Date類型,頁面輸入參數格式是 2019/1/1 可以自動參數映射,如果頁面輸入參數格式是 2019-1-1 則無法映射,需要使用自定義類型轉換器來解決。

注意:表單提交的任何數據類型全部都是字符串類型,但是後臺定義 Integer 類型,數據也可以封裝上,說明 Spring 框架內部會默認進行數據類型轉換。

如果想自定義數據類型轉換,可以實現 Converter 的接口

  1. 創建日期轉換工具類
//把字符串轉換日期
public class StringToDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        if ("".equals(s)) {
            throw new RuntimeException("日期字符串不能爲空");
        }

        try {
            return new SimpleDateFormat("yyyy-MM-dd").parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        throw new RuntimeException("日期類型轉換異常");
    }
}
  1. 修改 springmvc.xml
    <!--開啓註解掃描-->
    <context:component-scan base-package="com.demo"/>

    <!--視圖解析對象-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp"/>
    </bean>

    <!--配置自定義類型轉換器 - 解決日期轉換問題-->
    <bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.demo.utils.StringToDateConverter"/>
            </set>
        </property>
    </bean>

    <!--開啓SpringMVC框架註解支持-->
    <mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>

1.3 常用註解

  • @RequestParam 註解
    作用:把請求中的指定名稱的參數傳遞給控制器中的形參賦值

    • value:請求參數中的名稱
    • required:請求參數中是否必須提供此參數,默認值是true,必須提供
  • @PathVariable 註解
    作用:擁有映射 url 中的佔位符的。url 中有 /delete/{id} ,{id} 就是佔位符,也叫 URI模板

    • value:指定 url 中的佔位符名稱
jsp:
<a href="user/testPathVariable/123">testPathVariable</a>

controller:
    @RequestMapping(value="/testPathVariable/{uid}")
    public String testPathVariable(@PathVariable(name="uid") String id){
        System.out.println(id); // 123
        return "success";
    }

Restful 風格的 URL,即通過 PathVariable 實現:
請求路徑一樣,可以根據不同的請求方式去執行後臺的不同方法,如京東的商品鏈接…
restful風格的URL優點:結構清晰、符合標準、易於理解、擴展方便

1.4 其他註解

  • @RequestHeader 註解
    作用:獲取指定請求頭的值
    • value:請求頭的名稱
jsp:
<a href="user/testRequestHeader">RequestHeader</a>

controller:
    @RequestMapping(value="/testRequestHeader")
    public String testRequestHeader(@RequestHeader(value="Accept") String header){
        System.out.println(header); // 打印 accept 的頭信息
        return "success";
    }
  • @CookieValue 註解
    作用:用於獲取指定cookie的名稱的值
    • value:cookie的名稱
jsp:
<a href="user/testCookieValue">CookieValue</a>

controller:
    @RequestMapping(value="/testCookieValue")
    public String testCookieValue(@CookieValue(value="JSESSIONID") String cookieValue){
        System.out.println(cookieValue); // session id值
        return "success";
    }

2. 響應數據和結果視圖

2.1 返回值分類

  • String
    Controller 方法返回字符串可以指定邏輯視圖的名稱,根據視圖解析器爲物理視圖的地址。
    應用時可以設置參數類型爲 Model,使用 Model 對象調用 addAttribute 方法來存儲數據,同 request。

    request.setAttribute(“data”, data);

    model.addAttribute(“data”, data);

  • void
    如果控制器的方法返回值編寫成 void,執行程序報 404 的異常,默認查找 JSP 頁面沒有找到。
    應用時可以設置參數類型爲 HttpServletRequest 和 HttpServletResponse,使用轉發或者重定向來跳轉頁面

  • ModelAndView
    ModelAndView 對象是 Spring 提供的一個對象,可以調用 addObject 方法來保存數據以及調用 setViewName 方法來跳轉頁面。

  • forward: & redirect: 前綴
    可以在前端控制器的方法中直接返回 forward: 或 redirect: 爲前綴的路徑字符串,由 SpringMVC 反射中自動解析路徑選擇 轉發或重定向 跳轉頁面。

    使用forward關鍵字進行請求轉發:return “forward:轉發的JSP路徑”

    使用redirect關鍵字進行重定向(默認會把項目路徑加上):return “redirect:重定向的JSP路徑”

User

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
}

UserController

@Controller
@RequestMapping("/user")
public class UserController {
    public List<User> getUsers() {
        List<User> list = new ArrayList<User>();
        list.add(new User(1, "aaa", "123"));
        list.add(new User(2, "bbb", "456"));
        list.add(new User(3, "ccc", "789"));
        return list;
    }

    // String 返回值跳轉
    @RequestMapping("/testString")
    public String testString(HttpServletRequest request) {
        List<User> users = getUsers();
        request.setAttribute("users", users);
        return "/list.jsp";
    }

    // void 無返回值跳轉
    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        List<User> users = getUsers();
        request.setAttribute("users", users);
        request.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(request, response);
    }

    // ModelAndView 返回值跳轉
    @RequestMapping("/testModelAndView")
    public ModelAndView testModelAndView() {
        List<User> users = getUsers();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("users", users);
        modelAndView.setViewName("/list.jsp");
        return modelAndView;
    }

    // forward / redirect 前綴指定 轉發 或 重定向
    @RequestMapping("testForwardAndRedirect")
    public String testForwardAndRedirect(HttpServletRequest request) {
        List<User> users = getUsers();
        request.getSession().setAttribute("users", users);
        return "forward:/index.jsp";
        //return "redirect:/index.jsp";
    }
}

web.xml:中文亂碼過濾器、前端控制器。

springmvc.xml

    <!--開啓註解掃描-->
    <context:component-scan base-package="com.demo"/>

    <!--視圖解析對象-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp"/>
    </bean>

    <!--開啓SpringMVC框架註解支持-->
    <mvc:annotation-driven />

3. 配置不攔截靜態資源

DispatcherServlet 會攔截到所有的資源,導致一個問題就是靜態資源 img、css、js 也會被攔截到,從而不能被使用。

解決方案就是需要配置靜態資源不進行攔截,在 springmvc.xml 配置文件添加如下配置:

方式一:<mvc:resources> + <servlet-mapping>

<!-- springmvc.xml 前端控制器,哪些靜態資源不攔截-->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>

<!-- web.xml 配置 servlet 映射,html資源不被攔截 -->
<servlet-mapping>
	<serlvet-name>default</serlvet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>

方式二:所有靜態資源不被攔截

<!-- springmvc.xml 所有靜態資源不攔截-->
<mvc:default-servlet-handler />
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章