Spring MVC-01

SpringMVC

爲什麼使用SpringMVC

       原生JavaEE中,使用Servlet接受並處理請求,在實際應用中,某個項目可能涉及許多請求,例如:用戶註冊、登錄、修改密碼、修改資料、退出登錄等許多功能,多數情況下,自行創建Servlet只能處理一種請求,即對應一個功能,如果項目的功能較多,有幾百個,那麼也需要幾百個Servlet來處理請求,進而會導致項目在運行過程中,需要幾百個Servlet實例,同時,在編寫代碼時,每個Servlet都需要在web.xml文件中進行配置,就會產生大量的配置文件,在代碼維護方面,難度會非常大。

        使用SpringMVC主要解決了V-C交互的問題,即Controller如何接受用戶的請求,如何向客戶端進行響應,同時,它也解決了傳統的JavaEE中的問題,每個Controller可以處理若干種不同的請求,且不會產生大量的配置。

<servler>
    <serlvet-name><serlvet-name>
    <serlvet-class><serlvet-class>
</servler>
<servler-mapping>
    <serlvet-name><serlvet-name>
    <url-pattern><serlvet-pattern>
</servler-mapping>

SpringMVC執行流程

如何搭建SpringMVC

1.導入SpringMVC相關包

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>4.3.10.RELEASE</version>
</dependency>

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.12</version>
</dependency>

<dependency>
	<groupId>commons-dbcp</groupId>
	<artifactId>commons-dbcp</artifactId>
	<version>1.4</version>
</dependency>

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.6</version>
</dependency>

<dependency>
	<groupId>javax.annotation</groupId>
	<artifactId>javax.annotation-api</artifactId>
	<version>1.3.2</version>
</dependency>

<dependency>
	<groupId>javax.inject</groupId>
	<artifactId>javax.inject</artifactId>
	<version>1</version>
</dependency>  

2.配置前端控制器

<servlet>
	<description></description>
	<display-name>DispatcherServlet</display-name>
	<servlet-name>DispatcherServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
        <!-- DispatcherServlet的父類FrameworkServlet中的一個屬性值,用於指定配置文件位置 -->
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:mvc.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <!-- 將*.do請求全部轉到 前端控制器 -->
	<servlet-name>DispatcherServlet</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

3.編寫配置文件
       希望某個類被Spring管理,第一種做法時在Spring配置文件中通過<bean>節點進行配置,第二種做法是在Spring的配置文件種添加組件掃描,並在該類前添加【@Component】【@Controller】【@Service】【@Repository】註解。
       如果使用他人寫好的類,使用第一種做法,使用自己寫的類,使用第二種做法。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context" 
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
	xmlns:jee="http://www.springframework.org/schema/jee" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
<!-- 掃描控制器組件 -->
<context:component-scan base-package="controller"/>
		
<!-- 通知HandlerMapping,處理RequestMapping註解 -->
<mvc:annotation-driven/>
	
<!-- 視圖處理器 (視圖解析器)
    當控制器返回視圖名稱時候,利用視圖解析器InternalResourceViewResolver拼接前後綴,
    找到視圖對象如: 
        控制器返回 view 時候,拼接前後綴以後WEB-INF/jsp/view.jsp 用於定位jsp文件 -->
<bean id="viewResolver" 
	class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<!-- prefix: 前綴, suffer:後綴-->
	<property name="prefix" value="/WEB-INF/jsp/"/>
	<property name="suffix" value=".jsp"/>
</bean>

4.編寫子控制器
     如果關於此控制器的請求都是以相同的字符串作爲請求路徑的開始部分,如“/user/reg.do”,"/user/login.do","/user/updata.do",此時應在該類前添加@RequestMapping("/user")註解。

@Controller
public class HelloController {
		
	@RequestMapping("/demo.do")
	public String execute() {
		System.out.println("Hello World!"); 
		return "view"; // view.jsp
	}			
}

控制器中的方法應滿足:
a.使用pulbic權限  b.使用String類型作爲返回值類型(一般爲jsp文件名稱)  c.方法名稱自定義

如何接收前端頁面傳過來的參數:
【方式1】通過HttpServletRequest對象接受參數:request.getParameter("paramName") --- 不便於執行單元測試。
【方式2】將前端數據名稱作爲參數,寫入方法參數列表 --- 可手動傳參,方便單元測試。不適用於參數較多的請求方法。
【方式3】將多個參數封裝到某個類中,並使用這個類型作爲處理請求的方法的參數 【推薦】 使用時,需要注意的是:自定義類中的屬性的名稱必須與請求參數的名稱保持一致!

【小結】如何接收客戶端提交的請求參數
1.如果客戶端提交的請求參數較多,則優先使用第3種方式;
2.如果客戶端提交的請求參數的數量可能發生變化(例如隨着需求更新而改版),則優先使用第3種方式;
3.如果客戶端提交的請求參數的數量較少,並且固定,則優先使用第2種方式;
【方式2】與【方式3】可以組合使用

@RequestMapping("/handle_reg.do")
public String handleReg(String username,String password,Integer age) {
	return "handle_reg";
}

關於@RequestMapping】註解
        可以用於【限制請求類型】,當限制了請求類型之後,如果客戶端使用錯誤的方式來提交請求,則會出現【405】錯誤,提示內容例如:
        Request method 'GET' not supported

實現方式爲:

@RequestMapping(value="/handle_login.do", method=RequestMethod.POST)

關於【value】屬性
       取值是【String[ ]】,當只配置1個路徑時,直接使用字符串值即可,如果有多個路徑,則寫成數組格式,例如:

@RequestMapping({"/reg.do", "/register.do"}) 

另有【path】屬性,與【value】是完全等效的,該屬性是從4.2版本開始啓用的。

關於【method】屬性
         
用於設置請求方式,取值爲【RequestMethod】枚舉的數組,與【value】一樣,如果只有1個值時可以直接編寫,如果有多個值,必須寫成數組格式。
         與【@RequestMapping】註解相似的還有【@GetMapping】、【@PostMapping】等,這些註解就是限制了請求類型的@RequestMapping,例如【@PostMapping("/handle_login.do")】等效於【@RequestMapping(value="/handle_login.do", method=RequestMethod.POST)】,這些註解是從4.3版本開始啓用的。

關於@RequestParam註解
【@RequestParam】是添加在請求參數之前的註解。
 通過【@RequestParam】註解可以解決請求參數名與處理請求的方法的參數名不一致的問題,例如: 

@RequestParam("uname") String username

 需要注意的是:一旦使用以上註解,默認情況下,該參數是必須提交的!如果沒有提交對應的參數,則會導致【400】錯誤:
       HTTP Status 400 - Required String parameter 'uname' is not present

       所以,該註解還可以用於【強制要求客戶端必須提交某些參數】。該註解有boolean類型的屬性【required】,表示【是否必須】的意思,默認值爲【true】。

       該註解還有String類型的屬性【defaultValue】,表示【默認值】,即客戶端的請求中並不包含該參數時,給定一個該參數對應的默認值,設置默認值時,需要將【required】顯式的設置爲【false

@RequestParam(value="uname",required=false,defaultvalue="SpringMVC") String username

重定向
        當處理請求的方法的返回值以【redirect:】作爲前綴時,表示【重定向】,在使用重定向時,冒號右側的部分必須是相對路徑或絕對路徑,不可以是視圖名!

5.編寫視圖頁面
在/WEB-INF/jsp文件夾下創建view.jsp文件

<%@ contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
	    <meta charset="utf-8">
	    <title>View</title>
	</head>
    <body>
	    <h1>Hello World!</h1>
    </body>
</html>

6.測試
       控制器向JSP傳送數據,Spring利用【ModelAndView】或【ModelMap】封裝數據,並且傳遞給JSP,好處主要爲可以更好的將控制器與Request解耦,使控制器可以單獨進行測試。具體執行流程見上圖。
       注意:【ModelAndView】及【ModelMap】只能在轉發的需求中使用,如果出現重定向操作,需使用【session】存儲數據
哪些數據需要保存在Session中:
1.當前登錄的用戶的唯一標識,例如用戶ID等;
2.使用頻率極高的數據,如用戶的用戶名,用戶的頭像等;
3.不便於使用其他方式傳遞或保存的數據(實現成本更高);
在SpringMVC的控制器中,處理請求時,如果需要使用Session,則需要在控制器方法中添加【HttpSession】作爲參數,然後在方法體內部使用即可。

PS:【ModelAndView】實現

	@RequestMapping("/hand_login.do")
	//方法返回值類型爲:ModelAndView
	public ModelAndView handLogin(String username,String password) {
		ModelAndView mav = new ModelAndView();
		if("root".equals(username) && "1234".equals(password)) {
				mav.addObject("successMsg","ModelAndView:登錄成功");//設置view屬性值
				mav.setViewName("success");//設置view屬性名
		}else {
			mav.addObject("errorMsg","ModelAndView:登錄失敗");
			mav.setViewName("error");
		}
		return mav;
	} 

PS:【ModelMap】實現  -----【推薦使用

	@RequestMapping("/hand_reg.do")
	public String handReg(String username,String password,
			ModelMap modelMap) {//類似HttpRequest對象,直接使用ModelMap對象
		if("root".equals(username) && "1234".equals(password)) {
			modelMap.addAttribute("successMsg","ModelAndView:註冊成功");
			return "success";
		}else {
			modelMap.addAttribute("errorMsg","ModelAndView:註冊失敗");
			return "error";
		}
	}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章