1. 程式人生 > >SpringMVC 總結 及 SSM 整合

SpringMVC 總結 及 SSM 整合

SpringMVC

 

SpringMVC的核心架構:

具體流程:

 

(1)首先使用者傳送請求——>DispatcherServlet,前端控制器收到請求後自己不進行處理,而是委託給其他的解析器進行處理,作為統一訪問點,進行全域性的流程控制;

 

(2)DispatcherServlet——>HandlerMapping,對映處理器將會把請求對映為HandlerExecutionChain物件(包含一個Handler處理器(頁面控制器)物件、多個HandlerInterceptor攔截器)物件;

 

(3)DispatcherServlet——>HandlerAdapter,處理器介面卡將會把處理器包裝為介面卡,從而支援多種型別的處理器,即介面卡設計模式的應用,從而很容易支援很多型別的處理器;

 

(4)HandlerAdapter——>呼叫處理器相應功能處理方法,並返回一個ModelAndView物件(包含模型資料、邏輯檢視名);

 

(5)ModelAndView物件(Model部分是業務物件返回的模型資料,View部分為邏輯檢視名)——> ViewResolver, 檢視解析器將把邏輯檢視名解析為具體的View;

 

(6)View——>渲染,View會根據傳進來的Model模型資料進行渲染,此處的Model實際是一個Map資料結構;

 

(7)返回控制權給DispatcherServlet,由DispatcherServlet返回響應給使用者,到此一個流程結束。

@RequestMapping(value="/{tag}")  

public String getArticleListByTag(HttpServletRequest request, @PathVariable String tag, QueryCondition queryCondition) throws Exception{  

    tag = new String(tag.getBytes("ISO-8859-1"), "UTF-8");   

   System.out.println("tag="+tag);

}

1.  mvc 框架要做哪些事情:

    a) 將 url 對映到 Java 類或 Java 類的方法。

    b) 封裝使用者提交的資料

    c) 處理請求----呼叫相關的業務處理----封裝響應的資料

    d) 將響應的資料進行渲染,jsp,html,freemarker等。

2.  springMVC 是一個輕量級的,基於請求響應的 mvc 框架。

3.  為什麼要學習 springMVC框架?

        效能較 struts2 好。

        簡單,便捷,易學。

        天生和 Spring 無縫整合(使用 Spring IOC,AOP)。

        使用約定優於配置。

        能夠進行簡單的 Junit 測試。

        支援 Restful 風格。

        異常處理。

        本地化、國際化。

        資料驗證、型別轉換。

        攔截器等其他優勢... 使用人多~

SpringMVC:

    1.  匯入相關jar包

    2.  配置web.xml  核心分發器:org.springframework.web.servlet.DispatcherServlet

 

<servlet>

<servlet-name>dispatcherServlet</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<init-param>

<!-- SpringMVC配置檔案路徑 -->

<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>

 

 

    3.  新增 springMVC 配置檔案:預設在 WEB-INF 下新增 [DispatcherServletName]-servlet.xml 檔案

    4.  編寫程式碼。Controller(Action)

    5.  使用註解開發。@Controller  需要在web.xml 中新增 掃描context:component-scan

Controller 配置總結:

    第一種:    URL 對應 Bean

        如果要使用此類配置方式,需要在 XML 中做如下樣式配置:

            <!-- 表示講請求的 URL 和 Bean 名字對映 -->

            <bean    class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />

            <bean    name="/hello.do"    class="com.darryl.springmvc.controller.HelloController" />

       以上配置,訪問 /hello.do 就會尋找 id 為 /hello.do 的 Bean,此類方式僅適用小型的應用系統

    第二種:    為 URL 分配 Bean

        使用一個統一配置集合,對各個 URL 對應的 Controller 做關係對映

            <!-- 最常用的對映配置方式 -->

            <bean    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >

                    <property    name="mappings">

                            <props>

                                        <!-- key 對應 url 請求名    value: 對應處理器id -->

                                    <prop    key="/hello.do" > helloController </prop>

                            </props>

                    </property>

            </bean>

            <bean    id="helloController"    class="com.darryl.springmvc.controller.HelloController" />

        此類配置還可以使用萬用字元,訪問 /hello.do 時, Spring 會把請求分配給 helloController 進行處理

    第三種:    URL 匹配 Bean

        如果定義的 Controller 名稱規範,也可以使用如下配置

            <!-- 將 hello*.do 交給 helloController 處理-->

            <bean    class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />

            <bean    name="helloController"    class="com.darryl.springmvc.controller.HelloController" />

    第四種:    註解

        首先在配置檔案中開啟註解

            <!-- 啟用 Spring 註解-->

            <context:component-scan    base-package="com.darryl.springmvc.controller" />

            <bean    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

        在編寫類上使用註解 @org.springframework.stereotype.Controller 標記這個 Controller 物件

        使用 @RequestMapping("/hello.do")    指定方法對應處理的路徑

        * @Component:一個普通的Bean類。

        * @Repository :用於標註持久層DAO類

        * @Service :用於標註業務層類

        * @Controller :用於標註控制器類

        * @RequestMapping: Spring MVC使用@RequestMapping註解為控制器指定請求的URL。

            * @RequestMapping的value、method、params及heads分別表示請求url,請求方法,請求引數及請求頭的對映條件,他們之間是與的關係,聯合使用多個條件可以讓請求更加精確化。

            * params和headers支援簡單的表示式。

            * param1:表示請求必須包含param1的請求引數。

            * !param1:表示請求不能包含param1的請求引數。

            * param1!=value1:表示請求引數param1不能等於value1。

            * {"param1=value1","param2"}:表示請求引數param1必須等於value1,必須包含請求引數param2。

        * @PathVariable:URL模版方式     用來對映URL中的佔位符。對映的變數名必須和佔位符中的名稱一致。

        * @RequestParam:獲取請求引數     獲取頁面傳遞過來的引數,GET和POST都支援。 當引數與傳遞的引數同名時,可以省略@Requestparam

            * value:指定引數的名稱

            * required:指定引數是否為必填

            * defaultValue:指定引數的預設值

        * @RequestHeader:獲取請求頭內容    請求頭包含了若干的屬性,用來獲取客戶端的資訊。通過@RequestHeader可以用來獲取請求頭中的資訊

        * @CookieValue:用來獲取客戶端Cookie資訊。

        * @SessionAttributes:將模型中的某個屬性儲存到Session中,以便多個請求之間共享這個屬性。

            * 當類使用@SessionAttributes修飾,而方法中使用了和SessionAttributes修飾同名的對映引數,確沒有新增@ModelAttribute修飾時,則會報錯。

            HTTP Status 500 - Session attribute 'user' required - not found in session

            解決方案

                * 引數前使用@ModelAttribute修改對映的名稱。

                * 和@SessionAttributes中的名稱不同。

        * @ModelAttribute:方法形參標記該註解後,形參物件就會放到模型中。   

        * @ModelAndView:控制器處理方法如果返回ModelAndView,即包含檢視資訊,也包含模型資訊。

 

結果跳轉方式:

    1. 設定 ModelAndView 物件。根據 View 的名稱,和檢視解析器跳轉到指定的頁面。

        頁面:檢視解析器的字首 + view name + 檢視解析器的字尾

        ModelAndView mv = new ModelAndView();

        //封裝要顯示到檢視中的資料

        mv.addObject("msg","hello annotation");

        //檢視名

        mv.setViewName("hello");

    2. 通過 ServletAPI 物件來實現。不需要檢視解析器的配置

        通過 HttpServletResponse 來進行輸出。

        通過 HttpServletResponse 實現重定向。

        通過 HttpServletRequest 實現轉發。

    3. 通過 SpringMVC 來實現轉發和重定向----沒有檢視解析器

        轉發的實現1: 直接 return “路徑”

        轉發的實現2: 直接 return “forward:路徑”

        重定向的實現: 直接 return“redirect:路徑”

    4. 通過 SpringMVC 來實現轉發和重定向----有檢視解析器

        轉發的實現: 直接 return    "viewName"

        注意:重定向 不需要檢視解析器 return“redirect:路徑”

 

SpringMVC 資料的處理

    1. 提交資料的處理

        a. 提交的域名稱和處理方法的引數名一致即可。

            提交的資料

                

            處理方法

                

        b. 如過域名稱和引數名不一致

            提交的資料

                

            處理方法

                

        c. 提交的是一個物件

            要求提交的表單域名和物件的屬性名一致,引數使用物件即可。

                

            處理方法

                

    2. 將資料顯示到 UI 層

        第一種: 通過 ModelAndView——需要檢視解析器

        第二種: 通過 ModelMap 來實現,不需要檢視解析器,在方法引數中新增 ModelMap 引數

        

        ModelAndView  和 ModelMap 的區別:

            相同點:都可以將資料封裝顯示到表示層頁面中

            不同點:ModelAndView 可以指定跳轉的檢視,而 ModelMap不能

                          ModelAndView 需要檢視解析器,ModelMap 不需要配置檢視解析器

 

SpringMVC 亂碼及 restful

    1. 亂碼的解決——通過過濾器來解決亂碼:SpringMVC 中提供 CharacterEncodingFilter 解決 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>

        如果是 get 方式亂碼

        a) 修改 tomcat 的配置解決

        b )  自定義亂碼解決的過濾器 

    2. restful 風格的url

        優點:輕量級,安全,效率高       

 

//http://localhost:8080/restful/1/123/delete.do

     @RequestMapping("/{id}/{uid}/delete")

     public String delete(@PathVariable int uid,@PathVariable int id) {

          System.out.println("id "+id);

          System.out.println("uid "+uid);

          return "/index.jsp";

     }

    3.同一個 Controller 通過引數來達到不同的處理方法——不重要

 

SpringMVC 實現檔案上傳

    方式一:

        1. 通過 commons-fileupload 來實現,匯入相關jar包

        commons-fileupload,commons-io

        2. 配置 SpringMVC 的配置檔案

 

<bean id="multipartResolver"

          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

          <property name="defaultEncoding" value="utf-8"></property>

          <property name="maxUploadSize" value="10485760000"></property>

          <property name="maxInMemorySize" value="40960"></property>

     </bean>

 

         3. jsp頁面

 

<form action="upload.do" method="post" enctype="multipart/form-data">

          file:<input type="file" name="file"/>

          <input type="submit" value="上傳">

</form>

 

        4. Controller 程式碼

 

@RequestMapping("/upload")

     public String fileupload(@RequestParam("file")CommonsMultipartFile file,HttpServletRequest request) throws IOException {

          //獲取檔名

          //file.getOriginalFilename();

          //獲取上傳檔案的路徑

          String path = request.getRealPath("/fileupload");

          InputStream is = file.getInputStream();

          OutputStream os = new FileOutputStream(new File(path,file.getOriginalFilename()));

          int len = 0;

          byte[] buffer = new byte[400];

          while ((len=is.read(buffer))!=-1)

              os.write(buffer, 0, len);

          os.close();

          is.close();

          return "/index.jsp";

     }

        在Controller的MultipartFile引數前面必須加上@RequestParam

        批量上傳的程式碼:

 

@RequestMapping("/batch")

     public String fileupload(@RequestParam("file")CommonsMultipartFile file[],HttpServletRequest request) throws IOException {

          //獲取檔名

          //file.getOriginalFilename();

          //獲取上傳檔案的路徑

          String path = request.getRealPath("/fileupload");

          for (int i = 0; i < file.length; i++) {

              InputStream is = file[i].getInputStream();

              OutputStream os = new FileOutputStream(new File(path,file[i].getOriginalFilename()));

              int len = 0;

              byte[] buffer = new byte[400];

              while ((len=is.read(buffer))!=-1)

                   os.write(buffer, 0, len);

              os.close();

              is.close();

          }

          return "/index.jsp";

     }

    方式二:

        * 匯入CommonsMultipartResolver所依賴的jar包。

        * 新增配置檔案

 

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<!-- 指定預設的編碼格式 -->

<property name="defaultEncoding" value="UTF-8" />

<!-- 指定允許上傳的檔案大小,單位Byte -->

<property name="maxUploadSize" value="512000" />

</bean>

 

        MultipartFile屬性

            * MultipartFile可以獲取表單提交過來的檔案域

            * 常用方法

                * isEmpty():判斷是否提交檔案

                * getContentType():獲取檔案型別

                * getName():獲取表單元素名稱

                * getOriginalFilename():獲取提交的檔名稱

                * getInputStream():獲取檔案流

                * getSize():獲取檔案大小

                * getBytes():獲取位元組陣列

 

<form action="fileupload" method="post" enctype="multipart/form-data">

<input type="file" name="file" />

<input type="submit" value="上傳" />

<br />

<div class="msg">${message}</div>

</form>

<c:if test="${ !empty imageurl }">

<img src="${imageurl}" />

</c:if>

@RequestMapping("/fileupload")

public String fileupload(ServletRequest request, @RequestParam("file") MultipartFile file, Model model)

throws IOException {

if (!file.isEmpty()) {

String imageurl = saveFile(request, file);

model.addAttribute("imageurl", imageurl);

} else {

model.addAttribute("message", "請選擇要上傳的檔案");

}

return "fileupload";

}

private String saveFile(ServletRequest request, MultipartFile file) throws IOException {

// 獲取檔案的上傳路徑

String uploadPath = request.getServletContext().getRealPath("uploads");

File uploadPathFile = new File(uploadPath);

if (!uploadPathFile.exists()) {

uploadPathFile.mkdirs();

}

// 獲取檔名稱

String filename = file.getOriginalFilename();

// 擷取檔案字尾

String fileext = filename.substring(filename.lastIndexOf("."));

// 生成新的隨機檔名稱

String newfileName = UUID.randomUUID() + fileext;

// 檔案儲存路徑

File savePath = new File(uploadPath + "/" + newfileName);

// 上傳檔案

file.transferTo(savePath);

return "uploads/" + newfileName;

}

    如果提示檔案找不到(404)需要修改springmvc.xml配置檔案,加上以下配置

        <mvc:default-servlet-handler/>

SpringMVC 中 form標籤:

    匯入SpringMVC 表單標籤:

         <%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>

 

<form:form action="/loginPost" method="post" commandName="user">

</form:form>

<!-- 或者 -->

<form:form action="/loginPost" method="post" modelAttribute="user">

</form:form>

 

    普通標籤

        * form:input:對應<input type="text">

        * form:password:對應<input type="password" />

        * form:hidden:對應<input type="hidden" />

        * form:textarea:對應<textarea />

        * form:checkbox:對應<input type="checkbox" />

        * form:radiobutton:對應<input type="radiobutton"/>

    

    表單標籤的通用屬性

        SpringMVC提供了多個表單標籤,用以繫結表單欄位的屬性值,它們共有的屬性如下。

        * path:表單欄位,對應html中的name屬性,支援級聯屬性。

        * htmlEscape:是否對錶單的HTML特殊字元進行轉換,預設值為true。

        * cssClass:對應的css樣式。

        * cssErrorClass:發生錯誤時,對應的css樣式。

    支援繫結集合資料的標籤標籤:

        * checkboxes:多選列表

        * radiobuttons:單選列表

        * select:下拉列表

            * option/options:select中的元素

    form:radiobuttons:單選框組標籤,用於構造多個單選框

        * path:(必填)名稱,要繫結的屬性。

        * items:(必填)可以是一個list、String[]和Map。

        * itemValue:指定radio的value值,可以使集合中bean的一個屬性值。

        * itemLabel:指定radio的label值。

        * delimiter:多個單選框可以通過delimiter指定分隔符。

    form:errors:顯示錶單元件或資料效驗所對應的錯誤。

        * :顯示錶單中所有的錯誤。

        * <form:errors path="user" />:顯示所有以user為字首的屬性對應的錯誤。

        * :顯示username表單元素的錯誤。

 

@RequestMapping("dataBind")

public String dataBind(Map<String, Object> map) {

//生成繫結的集合屬性

List<String> genderList = new ArrayList<String>();

genderList.add("男");

genderList.add("女");

map.put("genderList", genderList);

 

//生成繫結自定義型別的集合屬性

List<Role> roleList = new ArrayList<Role>();

roleList.add(new Role(1, "管理員"));

roleList.add(new Role(2, "老師"));

roleList.add(new Role(3, "學生"));

map.put("roleList", roleList);

 

//User中必須包含和path同名的get和set方法,否則會報錯

User user = new User();

user.setUsername("admin");

user.setPassword("123");

//繫結物件時,需要重寫toString()方法才能比較值。

user.setGender("男");

user.setRole(new Role(3, "學生"));

user.setAge(22);

 

map.put("user", user);

return "dataBind";

}

<form:form action="loginPost" method="post" modelAttribute="user">

<table>

<tr>

<td>使用者名稱:</td>

<td><form:input path="username" /></td>

</tr>

<tr>

<td>密碼:</td>

<td><form:password path="password" /></td>

</tr>

<tr>

<td>性別:</td>

<td>

<form:radiobuttons path="gender" items="${genderList}"/>

</td>

</tr>

<tr>

<td>年齡</td>

<td>

<form:input path="age"/>

</td>

</tr>

<tr>

<td>角色:</td>

<td>

<!-- 這裡items表示要繫結的集合屬性,如果是字串集合,不需要指定itemValue

和itemLabel,如果是自定義的集合物件,則必須指定 -->

<form:radiobuttons path="role" itemValue="roleId" itemLabel="roleName"

items="${roleList}"/>

</td>

</tr>

<tr>

<td></td>

<td><input type="submit" value="登入" /></td>

</tr>

</table></form:form>

 

SpringMVC 中 Ajax 的處理:

    1. 使用 HttpServletResponse 來處理——不需要配置解析器

 

@RequestMapping("/ajax")

     public void ajax(String name,HttpServletResponse response) throws IOException {

          if("siggy".equals(name)) {

              response.getWriter().println("true");

          } else {

              response.getWriter().println("false");

          }

     }

$(function() {

          $("#txtName").blur(function() {

              $.post("ajax.do",

              {

                   'name' : $("#txtName").val()

              }, function(data) {

                   alert(data);

              })

          })

     });

 

    2. SpringMVC處理 json 資料

        a) 匯入 jar 包

            <groupId>com.fasterxml.jackson.core</groupId>

            <artifactId>jackson-databind</artifactId>

        b) 配置 json 轉換器

 

<!-- 用於將物件轉換為 JSON -->

     <bean id="stringConyerter"

          class="org.springframework.http.converter.StringHttpMessageConverter">

          <property name="supportedMediaTypes">

              <list>

                   <value>text/plain;charset=UTF-8</value>

              </list>

          </property>

     </bean>

     <bean id="jsonConverter"

          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">

     </bean>

     <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">

          <property name="messageConverters">

              <list>

                   <ref bean="stringConverter"/>

                   <ref bean="jsonConverter"/>

              </list>

          </property>

     </bean>

 

        c) Controller 程式碼

 

@RequestMapping("/json")

     @ResponseBody

     public List<User> json(){

          List<User> list = new ArrayList<User>();

          list.add(new User(1,"張三","男"));

          list.add(new User(2,"李四","男"));

          list.add(new User(3,"王五","男"));

          return list;

     }

 

        d) jsp 程式碼

 

<script type="text/javascript" src="js/jquery.min.js"></script>

<script type="text/javascript">

     $(function() {

          $("#btn").click(function() {

              $.post("json.do"

              , function(data) {

                   //alert(data);

                   var html="";

                   for(var i=0;i<data.length;i++) {

                        html+="<tr><td>"+data[i].id+"</td><td>"+data[i].name+"</td><td>"+data[i].sex+"</td></tr>";

                   }

                   $("#content").html(html);

              })

          }