JAVAEE——Spring MVC

SpringMVC介紹

Spring web mvc 和Struts2都屬于表現層的框架,它是Spring框架的一部分


Spring

SpringMVC處理流程

處理流程

入門程序

創建工程

入門工程

導入jar包

jar包

在web.xml中配置前端控制器DispatcherServlet

<?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_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
</web-app>

在上面的url-pattern中攔截規則有如下:

  • /* 表示攔截所有 jsp js png .css 會全部攔截
  • *.action *.do 攔截以do action 結尾的請求
  • / 攔截所有(不包括jsp) 包含 .js .png .css

創建springmvc.xml

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--配置controller掃描包-->
    <context:component-scan base-package="cn.probuing.springmvc.controller"/>
</beans>

創建pojo

public class Item {
    // 商品id
    private int id;
    // 商品名稱
    private String name;
    // 商品價格
    private double price;
    // 商品創建時間
    private Date createtime;
    // 商品描述
    private String detail;

創建帶參數的構造器
set/get。。。
}

創建ItemController

ItemController是一個普通的java類,不需要實現任何接口
需要再類上添加@Controller注解,將Controller交由Spring管理
在方法上面添加@RequestMapping注解 里面指定請求的url

 @RequestMapping("/itemList.action")
    public ModelAndView queryItemList() {
        // 創建頁面需要顯示的商品數據
        // 創建頁面需要顯示的商品數據
        List<Items> list = new ArrayList<>();
        list.add(new Items(1, "1華為 榮耀8", 2399f, new Date(), "質量好!1"));
        list.add(new Items(2, "2華為 榮耀8", 2399f, new Date(), "質量好!2"));
        list.add(new Items(3, "3華為 榮耀8", 2399f, new Date(), "質量好!3"));
        list.add(new Items(4, "4華為 榮耀8", 2399f, new Date(), "質量好!4"));
        list.add(new Items(5, "5華為 榮耀8", 2399f, new Date(), "質量好!5"));
        list.add(new Items(6, "6華為 榮耀8", 2399f, new Date(), "質量好!6"));
        //創建modelandview 模型視圖對象
        ModelAndView mav = new ModelAndView();
        //設置視圖跳轉名稱
        mav.setViewName("WEB-INF/jsp/itemList.jsp");
        //設置model數據
        mav.addObject("itemList", list);
        return mav;
    }

啟動測試

測試

SpringMVC架構

框架結構

框架結構

組件說明

以下組件通常由SpringMVC提供實現

前端控制器 DispatcherServlet

用戶請求到達前端控制器,它就相當于MVC模式中的C,dispatcherServlet是整個流程控制的中心,由它調用其它組件處理用戶的請求,DispathcerServlet的存在降低了各個組件之間的耦合性

處理器映射器 HandlerMapping

HandlerMapping負責根據用戶請求url找到Handler(處理器)springmvc提供了不同的映射器實現不同的映射方式。

Handler處理器

Handler是繼DispathcerServlet前端控制器的后端控制器,在DispathcerServlet的控制下Handler對具體的用戶請求進行處理 由于Handler涉及到具體的用戶業務請求,所以一般情況需要自己開發Handler

HandlerAdapter 處理器適配器

通過HandlerAdapter對處理器進行執行,這是適配器模式的應用,通過擴展適配器可以對更對類型的處理器進行執行

ViewResolver 視圖解析器

ViewResolver 負責將處理結果生成View視圖,ViewResolver首先根據邏輯視圖名解析成物理視圖名即具體的頁面地址,再生成View視圖對象,最后對View進行渲染將處理結果通過頁面展示給客戶

View視圖

springmvc框架提供了很多View視圖類型的支持,包括:jstlView、freemarkerView、pdfView等

說明

在SpringMVC的各個組件中,處理器映射器,處理器適配器、視圖解析器稱為SpringMVC的三大組件
需要用戶開發的組件是:Handler View

注解映射器和適配器

配置處理器映射器

注解式處理器映射器,對類中標記了@ResquestMapping的方法進行映射。根據@RequestMapping定義的url匹配@ResquestMapping標記的方法,匹配成功返回HandlerMethod對象給前端控制器。
HandlerMethod對象中封裝URL對應的方法Method
從Spring3.1開始,廢除了DefaultAnnotationHandlerMapping的使用 拓建使用RequestMappingHandlerMapping完成注解式處理器映射

在springmvc.xml配置文件中配置如下

 <!--配置處理器映射器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

配置處理器適配器

注解式處理器適配器,對標記@RequestMapping的方法進行適配
從Spring3.1版本開始,廢除了AnnotationMethodHandlerAdapter的使用,推薦使用RequestMappingHandlerAdapter完成注解式適配器適配
在springmvc.xml配置文件中配置如下

 <!--配置處理器適配器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

注解驅動

直接配置處理器映射器和處理器適配器比較麻煩,可以使用注解驅動來加載 SpringMVC使用 <mvc:annotation-driven>自動加載RequestMappingHandlerMapping和RequestMappingHandlerAdapter
可以在springmvc.xml配置文件中使用<mvc:annotation-driven>替代注解處理器和適配器的設置

<mvc:annotation-driven/>

視圖解析器

視圖解析器使用SpringMVC框架默認的InternalResourceViewResolver,這個視圖解析器支持JSP視圖解析
在springmvc.xml配置文件中配置如下

  <!--視圖解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置邏輯視圖前綴-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--配置邏輯視圖后綴-->
        <property name="suffix" value=".jsp"/>
    </bean>

修改ItemController

// @RequestMapping:里面放的是請求的url,和用戶請求的url進行匹配
// action可以寫也可以不寫
@RequestMapping("/itemList.action")
public ModelAndView queryItemList() {
    // 創建頁面需要顯示的商品數據
    List<Item> list = new ArrayList<>();
    list.add(new Item(1, "1華為 榮耀8", 2399, new Date(), "質量好!1"));
    list.add(new Item(2, "2華為 榮耀8", 2399, new Date(), "質量好!2"));
    list.add(new Item(3, "3華為 榮耀8", 2399, new Date(), "質量好!3"));
    list.add(new Item(4, "4華為 榮耀8", 2399, new Date(), "質量好!4"));
    list.add(new Item(5, "5華為 榮耀8", 2399, new Date(), "質量好!5"));
    list.add(new Item(6, "6華為 榮耀8", 2399, new Date(), "質量好!6"));

    // 創建ModelAndView,用來存放數據和視圖
    ModelAndView modelAndView = new ModelAndView();
    // 設置數據到模型中
    modelAndView.addObject("itemList", list);
    // 設置視圖jsp,需要設置視圖的物理地址
    // modelAndView.setViewName("/WEB-INF/jsp/itemList.jsp");
    // 配置好視圖解析器前綴和后綴,這里只需要設置邏輯視圖就可以了。
    // 視圖解析器根據前綴+邏輯視圖名+后綴拼接出來物理路徑
    modelAndView.setViewName("itemList");

    return modelAndView;
}

整合mybatis

整合目標:控制層采用SpringMVC 持久層采用mybatis

導入jar包

導入jara包

創建數據庫配置文件db.properties

  • db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://140.210.70.23:3306/springmvc?characterEncoding=utf-8
jdbc.username=appUser
jdbc.password=AA1122BB

web.xml

  • 在web.xml加入Spring監聽器 ContextLoaderListener 并指定Spring配置文件
  • web.xml文件中配置SpringMVC的前端控制器
<?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_4_0.xsd"
         version="4.0">
    <!--指定配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--spring mvc 前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--指定SpringMVC配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
</web-app>

springmvc.xml

  • 在springmvc中配置controller掃描包
  • 視圖解析器
  • 注解驅動
<?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:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!--配置controller掃描包-->
    <context:component-scan base-package="cn.probuing.springmvc.controller"/>
    <!--配置處理器映射器-->
    <!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>-->
    <!--配置處理器適配器-->
    <!--<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>-->
    <!--注解驅動-->
    <mvc:annotation-driven/>

    <!--視圖解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置邏輯視圖前綴-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--配置邏輯視圖后綴-->
        <property name="suffix" value=".jsp"/>
    </bean>

        
   </beans>

applicationContext.xml

  • spring配置文件中配置 數據庫文件,連接池
  • 配置mybatis的工廠并指定核心配置文件的位置
  • 指定mapper動態代理開發的掃描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">


    <context:property-placeholder location="classpath:db.properties"/>

    <!-- 數據庫連接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="10"/>
        <property name="maxIdle" value="5"/>
    </bean>

    <!-- Mybatis的工廠 -->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 核心配置文件的位置 -->
        <property name="configLocation" value="classpath:SqlMapConfig.xml"/>
    </bean>

    <!-- Mapper動態代理開發   掃描 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 基本包 -->
        <property name="basePackage" value="cn.probuing.springmvc.dao"/>
    </bean>

</beans>

參數綁定

在開發中 需要從請求的參數中把請求的id取出來
id包含在Request對象中,可以從Request對象中取id
想獲得Request對象需要再Controller方法的形參中添加一個參數即可。Springmvc框架會自動把Request對象傳遞給方法

jsp頁面

    
    <td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>

Controller

/**
     * 通過id查詢商品
     *
     * @param request
     * @return
     */
    @RequestMapping("/itemEdit")
    public ModelAndView queryItemById(HttpServletRequest request) {
        String strId = request.getParameter("id");
        Items items = itemService.queryItemById(Integer.valueOf(strId));
        //傳遞結果回頁面
        ModelAndView mva = new ModelAndView();
        mva.setViewName("editItem");
        //設置數據
        mva.addObject("item", items);
        return mva;

    }

默認支持的參數類型

處理器形參中添加如下類型的參數處理適配器會默認識別并進行賦值

  • HttpServletRequest 通過request對象獲取請求信息
  • HttpServletResponse 通過response處理響應信息
  • HttpSession 通過session對象得到session中存放的對象

Model/ModelMap

Model

除了ModelAndView之外,還可以使用Model來向頁面傳遞數據
Model是一個接口,在參數里直接聲明model即可

如果使用Model則可以不適用ModelAndView對象,Model對象可以向頁面傳遞數據View對象則可以使用String返回值替代
不管是Model還是ModelAndView其本質都是使用Request對象向jsp傳遞數據

/**
 * 根據id查詢商品,使用Model
 * 
 * @param request
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, Model model) {
    // 從request中獲取請求參數
    String strId = request.getParameter("id");
    Integer id = Integer.valueOf(strId);

    // 根據id查詢商品數據
    Item item = this.itemService.queryItemById(id);

    // 把結果傳遞給頁面
    // ModelAndView modelAndView = new ModelAndView();
    // 把商品數據放在模型中
    // modelAndView.addObject("item", item);
    // 設置邏輯視圖
    // modelAndView.setViewName("itemEdit");

    // 把商品數據放在模型中
    model.addAttribute("item", item);

    return "itemEdit";
}

ModelMap

ModelMap是Model接口的實現類,也可以通過ModelMap向頁面傳遞數據。
使用Model和ModelMap的效果一樣,如果直接使用Model,springmvc會實例化ModelMap

 * @param request
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(HttpServletRequest request, ModelMap model) {
    // 從request中獲取請求參數
    String strId = request.getParameter("id");
    Integer id = Integer.valueOf(strId);

    // 根據id查詢商品數據
    Item item = this.itemService.queryItemById(id);

    // 把結果傳遞給頁面
    // ModelAndView modelAndView = new ModelAndView();
    // 把商品數據放在模型中
    // modelAndView.addObject("item", item);
    // 設置邏輯視圖
    // modelAndView.setViewName("itemEdit");

    // 把商品數據放在模型中
    model.addAttribute("item", item);

    return "itemEdit";
}

綁定簡單類型

當請求的參數名稱和處理器形參名稱一致時會將請求參數與形參進行綁定。這樣從Request取參數的方法就可以進一步簡化

/**
 * 根據id查詢商品,綁定簡單數據類型
 * 
 * @param id
 * @param model
 * @return
 */
@RequestMapping("/itemEdit")
public String queryItemById(int id, ModelMap model) {
    // 根據id查詢商品數據
    Item item = this.itemService.queryItemById(id);

    // 把商品數據放在模型中
    model.addAttribute("item", item);

    return "itemEdit";
}

支持綁定的數據類型

參數類型推薦使用包裝數據類型,因為基礎數據類型不可以為null
整形:Integer、int
字符串:String
單精度:Float、float
雙精度:Double、double
布爾型:Boolean、boolean
說明:對于布爾類型的參數,請求的參數值為true或false?;蛘?或0
請求url:
http://localhost:8080/xxx.action?id=2&status=false

處理器方法:
public String editItem(Model model,Integer id,Boolean status)

@RequestParam

使用@RequestParam常用于處理簡單類型的綁定

  • value 參數名字,即入參的請求參數名字
    required 是否必須 默認是true 表示請求中一定要有響應的參數 否則報錯
    default 默認值,表示如果請求中沒有同名參數時的默認值
@RequestMapping("/itemEdit")
public String queryItemById(@RequestParam(value = "itemId", required = true, defaultValue = "1") Integer id,
        ModelMap modelMap) {
    // 根據id查詢商品數據
    Item item = this.itemService.queryItemById(id);

    // 把商品數據放在模型中
    modelMap.addAttribute("item", item);

    return "itemEdit";
}

綁定POJO類型

如果提交的參數很多,或者提交的表單中的內容很多的時候,可以使用簡單類型接受數據,也可以使用pojo接收數據。

  • 要求:pojo對象中的屬性名和表單中的input的name屬性一致

Controller

 @RequestMapping(value = "/updateitem.action")
    public String updateitem(Items items) {
        itemService.updateItemsById(items);

        return "success";
    }
  • 處理亂碼問題
    加入過濾器

    <!--編碼過濾器-->
    <filter>
        <filter-name>encoding</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>encoding</filter-name>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>
    

綁定包裝POJO

創建包裝的POJO QueryVo

package cn.probuing.springmvc.pojo;

/**
 * @Auther: wxblack-mac
 * @Date: 2018/8/28 17:45
 * @Description:
 */
public class QueryVo {
    private Items items;

    public Items getItems() {
        return items;
    }

    public void setItems(Items items) {
        this.items = items;
    }
}

jsp頁面

    <!-- <form id="itemForm" action="" method="post" enctype="multipart/form-data"> -->
    <form id="itemForm" action="${pageContext.request.contextPath }/updateitem.action" method="post">
        <input type="hidden" name="items.id" value="${item.id }" /> 修改商品信息:
        <table width="100%" border=1>
            <tr>
                <td>商品名稱</td>
                <td><input type="text" name="items.name" value="${item.name }" /></td>
            </tr>
            <tr>
                <td>商品價格</td>
                <td><input type="text" name="items.price" value="${item.price }" /></td>
            </tr>

自定義參數綁定

有時候參數無法被springmvc轉換,我們需要自定義轉換參數

自定義Converter 實現Converter接口 泛型為 源類型和轉換后的類型

/**
 * @Auther: wxblack-mac
 * @Date: 2018/8/28 19:05
 * DataConverter
 * S:需要轉換的源的類型
 * T:需要轉換的目標類型
 */
public class DataConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        //轉換s
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
            Date date = sdf.parse(s);
            return date;
        } catch (ParseException e) {
            return null;
        }
    }
}

配置轉換器Converter

在springmvc.xml文件中

 <!--配置轉換器工廠bean-->
    <bean id="conversionservicefactorybean"
          class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <!--配置轉換器-->
        <property name="converters">
            <list>
                <!--指定自定義轉換器實現類-->
                <bean class="cn.probuing.springmvc.converters.DataConverter"/>
            </list>
        </property>
    </bean>

高級參數綁定

數組參數

 @RequestMapping(value = "deletes.action")
    public String deletes(Integer[] ids) {
        for (Integer id : ids) {
            System.out.println(id+"111");
        }
        return "success";
    }

集合參數

<c:forEach items="${itemList }" var="item" varStatus="s">
<tr>
    <td><input type="checkbox" name="ids" value="${item.id}"/></td>
    <td>
        <input type="hidden" name="itemList[${s.index}].id" value="${item.id }"/>
        <input type="text" name="itemList[${s.index}].name" value="${item.name }"/>
    </td>
    <td><input type="text" name="itemList[${s.index}].price" value="${item.price }"/></td>
    <td><input type="text" name="itemList[${s.index}].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
    <td><input type="text" name="itemList[${s.index}].detail" value="${item.detail }"/></td>
    
    <td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>

</tr>
</c:forEach>

SpringMVC和Struts2區別

  • 1、SpringMVC的入口是一個Servlet即前端控制器。而Struts2入口是一個filter過濾器
  • 2、SpringMVC請求參數傳遞到方法的形參,Struts2傳遞參數是通過類的屬性
  • 3、SpringMVC是基于方法開發(一個url對應一個方法),可以設計成單例或者多例
  • 4、Struts采用值棧存儲請求和響應數據,通過OGNL存儲數據 SpringMVC通過參數計息期將request請求內容解析,并給方法形參賦值,將數據和視圖封裝成ModelAndView對象,最后又將ModelAndView中的模型數據通過request域傳輸到頁面,jsp視圖解析器默認使用jstl

@RequestMapping

通過@RequestMapping注解可以定義不同的處理器映射規則

URL路徑映射

@RequestMapping(value="item")或者 @RequestMapping("/item")
value是一個數組,可以將多個url映射到同一個方法

/**
 * 查詢商品列表
 * @return
 */
@RequestMapping(value = { "itemList", "itemListAll" })
public ModelAndView queryItemList() {
    // 查詢商品數據
    List<Item> list = this.itemService.queryItemList();
    // 創建ModelAndView,設置邏輯視圖名
    ModelAndView mv = new ModelAndView("itemList");
    // 把商品數據放到模型中
    mv.addObject("itemList", list);
    return mv;
}

添加到類上 窄化路徑

對于重復的父路徑可以使用URL放在類上可以指定簡化的類路徑

//@RequestMapping("item")
public class ItemController {

請求方法限定

method={RequestMethod.POST,RequestMethod.GET} 指定請求方式

  • 限定GET方法
@RequestMapping(method = RequestMethod.GET)
  • 限定POST方法
@RequestMapping(method = RequestMethod.POST)

Controller方法返回值

返回ModelAndView

controller 方法中定義ModelAndView對象并返回,對象中可添加moedel數據,指定View

返回void

在Controller方法形參上可以定義request和response
適合json 和 ajax請求時的方式

/**
 * 返回void測試
 * 
 * @param request
 * @param response
 * @throws Exception
 */
@RequestMapping("queryItem")
public void queryItem(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 1 使用request進行轉發
    // request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request,
    // response);

    // 2 使用response進行重定向到編輯頁面
    // response.sendRedirect("/springmvc-web2/itemEdit.action");

    // 3 使用response直接顯示
    response.getWriter().print("{\"abc\":123}");
}

返回字符串

邏輯視圖名

controller 方法返回字符串可以指定邏輯視圖名,通過視圖解析為物理視圖地址

Redirect重定向

Controller方法返回字符串可以重定向到一個url地址

/**
 * 更新商品
 * 
 * @param item
 * @return
 */
@RequestMapping("updateItem")
public String updateItemById(Item item) {
    // 更新商品
    this.itemService.updateItemById(item);

    // 修改商品成功后,重定向到商品編輯頁面
    // 重定向后瀏覽器地址欄變更為重定向的地址,
    // 重定向相當于執行了新的request和response,所以之前的請求參數都會丟失
    // 如果要指定請求參數,需要在重定向的url后面添加 ?itemId=1 這樣的請求參數
    return "redirect:/itemEdit.action?itemId=" + item.getId();
}

forward轉發

Controllrer方法執行后繼續執行另一個Controller方法

/**
 * 更新商品
 * 
 * @param item
 * @return
 */
@RequestMapping("updateItem")
public String updateItemById(Item item) {
    // 更新商品
    this.itemService.updateItemById(item);

    // 修改商品成功后,重定向到商品編輯頁面
    // 重定向后瀏覽器地址欄變更為重定向的地址,
    // 重定向相當于執行了新的request和response,所以之前的請求參數都會丟失
    // 如果要指定請求參數,需要在重定向的url后面添加 ?itemId=1 這樣的請求參數
    // return "redirect:/itemEdit.action?itemId=" + item.getId();
    // 修改商品成功后,繼續執行另一個方法
    // 使用轉發的方式實現。轉發后瀏覽器地址欄還是原來的請求地址,
    // 轉發并沒有執行新的request和response,所以之前的請求參數都存在
    return "forward:/itemEdit.action";
}

異常處理器

Springmvc在處理請求過程中出現異常信息交由異常處理器進行處理,自定義異常處理器可以實現一個系統的異常處理邏輯

異常處理思路

系統中異常包括兩類:預期異常和運行時異常,前者通過捕獲異常從而獲取異常信息,后者主要通過規范代碼開發、測試通過手段減少運行時異常發生

異常處理過程

異常處理器自定義實現類

實現HandlerExceptionResolver接口

/**
 * @Auther: wxblack-mac
 * @Date: 2018/8/30 14:50
 * @Description:
 */
public class MyExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        System.out.println(o);
        ModelAndView mav = new ModelAndView();
        mav.addObject("error", "未知異常");
        mav.setViewName("error");
        return mav;
    }
}

方法形參中:httpServletRequest 請求對象 httpServletResponse 響應對象
Object o:異常信息封裝 包名+類名+方法名
Exception e:異常對象
返回的ModelAndView 可以指定視圖和數據

配置異常處理

  <!--自定義異常處理-->
    <bean class="cn.probuing.springmvc.exceptionhandler.MyExceptionHandler"/>

上傳圖片

加入上傳圖片的jar包

jar包

配置文件上傳解析器

  • 文件上傳解析器 id必須設置為multipartResolver
 <!--配置文件文件上傳解析器-->
    <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="commonsMultipartResolver">
        <!--設置文件大小-->
        <property name="maxUploadSize" value="5000000"/>
    </bean>

jsp頁面



<form id="itemForm" action="{pageContext.request.contextPath }/updateitem.action" method="post" enctype="multipart/form-data"> <input type="hidden" name="items.id" value="{item.id }"/> 修改商品信息:
<table width="100%" border=1>
<tr>
<td>商品名稱</td>
<td><input type="text" name="items.name" value="{item.name }"/></td> </tr> <tr> <td>商品價格</td> <td><input type="text" name="items.price" value="{item.price }"/></td>
</tr>
<tr>
<td>商品生產日期</td>
<td><input type="text" name="items.createtime"
value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
</tr>

    <tr>
        <td>商品圖片</td>
        <td>
            <c:if test="${item.pic !=null}">
                <img src="/pic/${item.pic}" width=100 height=100/>
                <br/>
            </c:if>
            <input type="file" name="pictureFile"/>
        </td>
    </tr>
    <%--

--%>
<tr>
<td>商品簡介</td>
<td><textarea rows="3" cols="30" name="items.detail">${item.detail }</textarea>
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="提交"/>
</td>
</tr>
</table>

</form>

java代碼

方法接收時,圖片形參的名字必須要和jsp頁面 傳遞的圖片的name一致

  @RequestMapping(value = "/updateitem.action")
    public String updateitem(QueryVo vo, MultipartFile pictureFile) throws IOException {
        //創建圖片名稱
        String picName = UUID.randomUUID().toString().replaceAll("-", "");
        //獲取文件名
        String oriName = pictureFile.getOriginalFilename();
        //獲取圖片后綴
        String ext = FilenameUtils.getExtension(oriName);

        //保存圖片
        pictureFile.transferTo(new File("/Users/wxblack-mac/pic/" + picName + "." + ext));
        //保存數據庫
        vo.getItems().setPic(picName + "." + ext);
        itemService.updateItemsById(vo.getItems());

        return "redirect:/itemEdit.action?id=" + vo.getItems().getId();
    }

JSON數據交互

@RequestBody

@RequestBody注解用于讀取http請求的內容,通過springmvc提供的HttpMessageConverter接口將讀取到的內容轉換為java對象并綁定到Controller方法的參數上

@ResponseBody

@ReponseBody注解用于將Controller的方法返回的對象,通過SpringMVC提供的HttpMessageConverter接口轉換為指定格式的數據。通過Response響應到客戶端

加入jar包

圖片.png

Controller

@RequestMapping(value = "/json.action")
    public @ResponseBody
    Items json(@RequestBody Items items) {
        return items;
    }

JS發送Json數據

 $(function () {
            var params = '{"id": 1,"name": "測試商品","price": 99.9,"detail": "測試商品描述","pic": "123456.jpg"}';
            alert(params);
            $.ajax({
                url: "${pageContext.request.contextPath}/json.action",
                data: params,
                contentType: "application/json;charset=UTF-8",
                type: "post",
                dataType: "json",
                success: function (data) {
                    alert(data.name);
                }
            });
        });

配置Json轉換器

如果不適用注解驅動,就需要給處理器適配器配置json轉換器
在springmvc.xml配置文件中,給處理器適配器加入json轉換器

<!--處理器適配器 -->

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

  <property name=*"messageConverters"*>

  <list>

  <bean class=*"org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"*></bean>

  </list>

  </property>

  </bean>

RESTful支持

什么是restful?

Restful就是一個資源定位及資源操作的風格。不是標準也不是協議,只是一種風格?;谶@個風格設計的軟件可以更簡潔,更有層次,更易于實現緩存等機制
傳統方式操作資源
http://127.0.0.1/item/queryItem.action?id=1 查詢,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 刪除,GET或POST

使用RESTful操作資源
http://127.0.0.1/item/1 查詢,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 刪除,DELETE

測試

  • 首先我們指定參數注入在地址中,在地址中的參數使用{}包裹并使用@PathVariable指定地址中的參數,對應到方法的形參中
  /**
     * 通過id查詢商品
     *
     * @return
     */
    @RequestMapping("/itemEdit/{id}.html")
    public ModelAndView queryItemByIdRestFul(@PathVariable Integer id) {
        Items items = itemService.queryItemById(id);
        //傳遞結果回頁面
        ModelAndView mva = new ModelAndView();
        mva.setViewName("editItem");
        //設置數據
        mva.addObject("item", items);
        return mva;
    }
  • 訪問


    訪問地址

攔截器

定義

SpringMVC 的處理器攔截器類似于Servlet開發中的過濾器Filter,用于對處理器進行預處理和后處理

public class HandlerInterceptor1 implements HandlerInterceptor {
    // controller執行后且視圖返回后調用此方法
    // 這里可得到執行controller時的異常信息
    // 這里可記錄操作日志
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        System.out.println("HandlerInterceptor1....afterCompletion");
    }

    // controller執行后但未返回視圖前調用此方法
    // 這里可在返回用戶前對模型數據進行加工處理,比如這里加入公用信息以便頁面顯示
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {
        System.out.println("HandlerInterceptor1....postHandle");
    }

    // Controller執行前調用此方法
    // 返回true表示繼續執行,返回false中止執行
    // 這里可以加入登錄校驗、權限攔截等
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
        System.out.println("HandlerInterceptor1....preHandle");
        // 設置為true,測試使用
        return true;
    }
}

攔截器定義 springmvc.xml

<!-- 配置攔截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <!-- 所有的請求都進入攔截器 -->
        <mvc:mapping path="/**" />
        <!-- 配置具體的攔截器 -->
        <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1" />
    </mvc:interceptor>
    <mvc:interceptor>
        <!-- 所有的請求都進入攔截器 -->
        <mvc:mapping path="/**" />
        <!-- 配置具體的攔截器 -->
        <bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2" />
    </mvc:interceptor>
</mvc:interceptors>

多個攔截器調用總結

  • 按照配置執行后,我們可以看到 preHandler方法返回false后第一個攔截器只執行了preHandler方法,其他的兩個方法沒有執行,第二個攔截器的所有方法不執行,且Controller也不執行了

  • HandlerInterceptor1的preHandler方法返回true HandlerInterceptor2返回false時,我們可以看到第二個攔截器的preHandler方法返回false后第一個攔截器的postHandler沒有執行,第二個攔截器的postHandler和afterCompletion沒有執行,且controller也不執行了

preHandler按攔截器定義的順序調用
postHandler按攔截器定義的順序逆序調用
afterCompletion按攔截器定義順序逆序調用

postHandler在攔截器鏈內所有攔截器返回成功調用,在多個攔截器時,只有所有攔截器的preHandler返回成功時 才會執行postHandler方法
afterCompletion只有preHandle 返回true才調用 在多個攔截器時,只要當前

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容