1. 程式人生 > >SpringMVC學習筆記_02

SpringMVC學習筆記_02

1、springmvc對多檢視的支援

(1)匯入xml格式檢視支援的jar包

  注意:springmvc本身就支援xml格式,所以不用匯入其他支援的jar包了。

(2)在springmvc.xml中配置支援多檢視

    <!-- 配置支援多檢視 -->
    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <!-- 配置支援的媒體型別 -->
        <!-- spring3.2後改成如下配置 -->
        <property name="contentNegotiationManager">
            <bean class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
                <!-- 指定多個媒體型別 -->
                <property name="mediaTypes">
                    <map>
                        <entry key="json" value="application/json"></entry>
                        <entry key="xml" value="application/xml"></entry>
                        <!-- <entry key="pdf" value="application/pdf"></entry> 需要額外的jar包 -->
                    </map>
                </property>
            </bean>
        </property>

        <!-- 指定預設的檢視 -->
        <property name="defaultViews">
            <!-- 支援多個檢視 -->
            <list>
                <!-- 對json格式檢視的支援 -->
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"></bean>
                <!-- 對xml格式檢視的支援,需要注入建構函式,需要一個jar包:spring-oxm-3.2.0.RELEASE.jar -->
                <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                    <constructor-arg>
                        <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
                            <!-- 配置對哪些類進行xml轉換的支援,即繫結多個類,演示程式碼中我們只綁定了一個類 -->
                            <property name="classesToBeBound">
                                <list>
                                    <!-- 注意:需要在繫結的類中加入對xml格式檢視轉換的註解:@XmlRootElement -->
                                    <value>com.itheima.domain.User</value>
                                </list>
                            </property>
                        </bean>
                    </constructor-arg>
                </bean>
            </list>
        </property>
    </bean>

  小結:通過以上配置,模擬了WebService對多檢視的支援的功能。
(3)配置javabean,即在繫結的類User中加入對xml格式檢視轉換的註解:@XmlRootElement


(4)在web.xml中配置約定訪問的url

    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

(5)定義Controller

    // 多檢視支援
    // 返回的是物件,把返回的物件轉換成json格式檢視和xml格式的檢視
    @RequestMapping("multiView")
    public User multiView() {
        User user1 = new User();
        user1.setId(1);
        user1.setUsername("曉藝");
        user1.setAge("26");
        user1.setAddress("物資學院");
        user1.setBirthday(new Date());

        return user1;
    }

(6)訪問
  根據官方文件約定:訪問的時候需要加上響應的副檔名。
  即:訪問json格式的資料,需要加上json副檔名;訪問html格式的資料,需要加上html的副檔名;訪問xml格式的資料,需要加上xml的副檔名。
  根據我們web.xml檔案的訪問約定:副檔名.do是訪問jsp頁面的。
  我們約定rest目錄下所有以json和xml副檔名都支援相應的檢視。

我們訪問json格式資料的訪問形式如下:


我們訪問xml格式資料的訪問形式如下:

(7)<mvc:annotation-driven/>

    <mvc:annotation-driven/> 預設建立:註解處理器對映器、註解處理器介面卡、並提供對json格式資料的支援。

在springmvc.xml中進行配置:

    <!-- 表示預設建立:處理器對映器物件、處理器對映器物件,還表示預設啟動json格式資料的支援 -->
    <mvc:annotation-driven />

但是注意:此時javaBean不能添加註解@XmlRootElement了。@XmlRootElement表示提供對xml檢視支援。

 

2、SSM整合小案例

2.0、需求

  • 實現商品查詢列表,從mysql資料庫中查詢商品資訊。

2.1、使用eclipse,建立一個動態web工程並匯入jar包

  • 其中Dynamic web module version版本選擇 2.5,這樣相容性好一些;
  • Default output folder設定為 WebRoot\WEB-INF\classes
  • Content directory設定為 WebRoot
  • 更改JRE System Library[J2SE-1.5]為 JRE System Library[jre1.7.0_80]
  • 刪掉沒用的庫:EAR Libraries
  • 增加伺服器執行環境庫 Server Runtime,不然jsp檔案會報錯。
  • 建立完專案後,將整個專案的編碼改為UTF-8。
  • 操作步驟:選中專案右鍵 --> Properties --> Resource --> Text file encoding --> Other中選擇UTF-8。
  • 對於動態的java web專案,為了工程目錄結構的清爽,我們將引入的jar包放到“Web App Libraries”中,可以通過“小三角”選擇是否“Show 'Referenced Libraries' Node ”進行調節。
  • 對於普通的java專案,為了工程目錄結構的清爽,我們將引入的jar包放到“Referenced Libraries”中,可以通過“小三角”選擇是否“Show 'Referenced Libraries' Node ”進行調節。

匯入jar包
  包括:spring(包括springmvc)、mybatis、mybatis-spring整合包、資料庫驅動、第三方連線池、jstl、c3p0管理資料來源、log4j、junit。
  參考:“mybatis與springmvc整合全部jar包”目錄。

本次案例共匯入28個jar包。如下圖所示:

2.2、web.xml配置檔案(入口)

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5">
    <display-name>day63_SpringMVC_01</display-name>

    <!-- 配置spring編碼過濾器 -->
    <filter>
        <filter-name>characterEcoding</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>characterEcoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- 配置前端控制器:DispatcherServlet -->
    <servlet >
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 顯示配置載入springmvc.xml檔案,即配置springmvc.xml檔案的初始化引數 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <!-- 配置servlet攔截副檔名 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
    <!-- 配置servlet攔截目錄 -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

    <!-- 配置載入spring的配置檔案:beans.xml -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:beans.xml</param-value> <!-- 這兩種方式均可 -->
        <!-- <param-value>/WEB-INF/classes/beans.xml</param-value> -->
    </context-param>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>

2.3、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:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-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/context 
        http://www.springframework.org/schema/context/spring-context-3.2.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
    <!-- 配置掃描,把Controller交給spring管理 -->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!-- 表示預設建立處理器對映器物件、處理器對映器物件,還表示預設啟動json格式資料的支援 -->
    <mvc:annotation-driven />

    <!-- 配置jsp檢視解析器,InternalResourceViewResolver負責解析出真正的邏輯檢視 -->
    <!-- 後臺返回邏輯檢視:index,jsp檢視解析器解析出真正的物理檢視:字首+邏輯檢視+字尾 ==>/WEB-INF/jsps/index.jsp -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsps/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>
</beans>

2.4、bean.xml配置檔案(相當於applicationContext.xml)

bean.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:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-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/context 
        http://www.springframework.org/schema/context/spring-context-3.2.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
    <context:component-scan base-package=""></context:component-scan>

    <!-- 1、配置資料來源 -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!-- 2、配置sqlSessionFactory,用於生產sqlSession -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="classpath:sqlMapConfig.xml"></property>
    </bean>
    <!-- 配置mybatis的Mapper介面代理開發,需要遵循的幾點規範 -->
    <!-- 
        1、mapper介面的全限定名要和mapper對映檔案的namespace的值相同。
        2、mapper介面的方法名稱要和mapper對映檔案中的statement的id相同。
        3、mapper介面的方法引數只能有一個,且型別要和mapper對映檔案中statement的parameterType的值保持一致。
        4、mapper介面的返回值型別要和mapper對映檔案中statement的resultType的值或resultMap中的type的值保持一致。
        5、mapper介面和mapper對映檔案必須在同一目錄下。
    -->
    <!-- mapper代理開發方式之批量mapper配置,預設bean的id為類名首字母小寫 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定批量mapper配置的包名 -->
        <property name="basePackage" value="com.itheima.dao"></property>
        <!-- 當只有一個SqlSessionFactory時,預設是不需要配置SqlSessionFactory的 -->
        <!-- 當有多個SqlSessionFactory時,可以指定使用的SqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

    <!-- 3、配置事務管理 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 配置通知:管理事務的策略 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="insert*" propagation="REQUIRED"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!-- 配置攔截service:切面程式設計 -->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service.*.*(..))"/>
    </aop:config>
</beans>

2.6、編寫程式碼

mapper層(dao層):
  mapper介面程式碼使用Mybatis的逆向工程生成的。
service層:
  ItemsService.java

public interface ItemsService {

    public List<Items> findAll();

    public Items findById(Integer id);

    public void saveOrUpdate(Items items);

    public void deleteById(Integer id);

}

  ItemsServiceImpl.java

@Service
public class ItemsServiceImpl implements ItemsService {

    // 注入介面物件(Mapper介面使用代理類)
    @Resource
    private ItemsMapper itemsMapper;

    public List<Items> findAll() {
        List<Items> list = itemsMapper.findAll();
        return list;
    }

    public Items findById(Integer id) {
        Items items = itemsMapper.selectByPrimaryKey(id);
        return items;
    }

    public void saveOrUpdate(Items items) {
        itemsMapper.updateByPrimaryKey(items); // 商品id通過頁面隱藏域傳過來的
    }

    public void deleteById(Integer id) {
        itemsMapper.deleteByPrimaryKey(id);
    }

}

controller層(web層/Action層):
  ItemsController.java

@Controller
@RequestMapping("/items")
public class ItemsController {

    // 注入service物件
    @Resource
    private ItemsService itemsService;

    // 查詢所有商品方法
    @RequestMapping("list")
    // springmvc使用Model物件進行頁面資料回顯,Model物件相當於javaweb時所學的application物件(應用域物件),所以Model物件中的資料,在頁面上可以通過EL表示式進行獲取。
    // 有了Model物件,才可以向物件中放值,那麼Model物件該如何建立呢?
    // 答:“由於springmvc中放到方法裡面的物件會自動被建立”,那麼我們就把Model物件放到方法裡面。
    public String list(Model model) { 
        List<Items> itemsList = itemsService.findAll();
        model.addAttribute("itemsList", itemsList);
        return "itemsList";
    }

    // 修改商品方法
    @RequestMapping("editById")
    public String editById(Integer id, Model model) {
        // 跟據id查詢商品
        Items items = itemsService.findById(id);
        model.addAttribute("items", items);
        return "editItems";
    }

    // 修改後儲存方法
    @RequestMapping("saveOrUpdate")
    public String saveOrUpdate(Items items) {
        itemsService.saveOrUpdate(items); // 商品id通過頁面隱藏域傳過來的
        return "redirect:list.do";
    }

    // 跟據id進行刪除
    @RequestMapping("deleteById")
    public String deleteById(Integer id) {
        itemsService.deleteById(id); 
        return "redirect:list.do";
    }

    // 跟據ids進行批量刪除
    @RequestMapping("deleteByIds")
    public String deleteByIds(Integer[] ids) { // 特別注意:標籤input的name的屬性值id要與方法的形式引數名稱id相同。形參名稱也可以起別名!但需要其他註解配合哦!
        for (Integer id : ids) {
            itemsService.deleteById(id); 
        }
        return "redirect:list.do";
    }
}

2.7、springmvc檔案上傳

需求分析:
  使用ajax,響應json格式資料的形式上傳圖片並立刻回顯。頁面不重新整理圖片回顯立刻。

ajax能不能提交表單?
答:ajax自己不能提交表單。要想ajax提交表單,需要藉助一個外掛。

為什麼我們要提交表單?
答:因為我們要提交一個檔案物件,需要將檔案物件關聯到表單裡面。
當我們點選一個按鈕的時候,這個被關聯到表單裡的物件,才會被提交。

虛擬碼示例如下:
    // 圖片回顯
    <img src=“圖片路徑”/>
    // 把檔案關聯表單,觸發ajax事件
    <input type="file" onchange="ajax事件"/>
    <input type="hidden" value="圖片相對路徑"/>

    // 本示例開始,我們不使用 enctype="multipart/form-data" 提交檔案物件了
    // 我們直接使用ajax提交檔案物件,我們新增隱藏域,向後臺提交圖片相對路徑

(1)匯入跨伺服器上傳檔案的jar包、IO、fileupload

(2)模擬2臺伺服器
  建立一個動態的java web專案:圖片伺服器專案,圖片伺服器專案的伺服器和上傳圖片專案的伺服器埠不一致即可。如下圖所示:

(3)springmvc支援檔案上傳,需要先在springmvc.xml配置檔案中開啟檔案上傳
  在springmvc.xml配置檔案中新加入的內容如下:

    <!-- 配置開啟檔案上傳,因為我們要跨伺服器上傳,需要寫上id,該id名稱固定 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 配置檔案上傳大小 -->
        <property name="maxUploadSize" value="1024000"></property>
    </bean>

(4)前臺頁面ajax
  功能:傳送請求,請求上傳圖片,圖片需要被關聯在表單裡。


使用ajax提交form表單的外掛:jquery.form.js

(5)後臺程式碼

@Controller
@RequestMapping("/upload")
public class UploadController {

    @RequestMapping("uploadPic")
    public void uploadPic(HttpServletRequest request, String fileName, PrintWriter out) {
        // 1、準備檔案上傳流
        // 由於上傳的圖片在請求裡面,它是流型別的,直接通過Request物件不能操作
        // 所以先要把Request物件強轉成多部件請求物件
        MultipartHttpServletRequest mhr = (MultipartHttpServletRequest) request;
        // 根據檔名稱獲取普通多部件檔案物件
        CommonsMultipartFile cmFile = (CommonsMultipartFile) mhr.getFile(fileName);
        // 獲取檔案上傳流
        byte[] fbytes = cmFile.getBytes();

        // 2、準備檔名稱
        // 檔名稱在伺服器有可能重複,我們使用時間來區分他們
        String newFileName = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        newFileName = sdf.format(new Date());
        // 在毫秒的時候檔名也可能重複,我們再加點鹽
        Random r = new Random(); // [0,1)
        for (int i = 0; i < 3; i++) {
            newFileName = newFileName + r.nextInt(10);
        }

        // 3、獲取副檔名
        String originalFilename = cmFile.getOriginalFilename();
        // int x = a.lastIndexOf(b); // 表示b字串在a字串中最後出現的位置,從0開始
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")); 

        // 4、建立jesy伺服器,進行跨伺服器上傳
        Client client = Client.create();
        // 把檔案關聯到遠端伺服器
        // 圖片檔案的完整路徑為:http://127.0.0.1:9005/day64_SSMImageServer/upload/20181027174523998.png
        WebResource resource = client.resource(Commons.PIC_HOST + "/upload/" + newFileName + suffix);
        // 上傳圖片檔案
        resource.put(String.class, fbytes);

        // 5、ajax回撥函式需要回顯什麼東西呢?
        // 圖片需要回顯:需要圖片的完整路徑
        // 資料庫儲存圖片:需要圖片的相對路徑
        String fullPath = Commons.PIC_HOST + "/upload/" + newFileName + suffix;
        String relativePath = "/upload/" + newFileName + suffix;
        // json格式的資料:{"":"","":""}
        String result = "{\"fullPath\":\"" + fullPath + "\",\"relativePath\":\"" + relativePath + "\"}";
        out.print(result);
    }
}

(6)修改圖片伺服器檔案上傳許可權

(7)圖片上傳位置

(8)圖片列表回顯
  回顯圖片需要使用<img/>標籤
itemsList.jsp

    <c:set var="picPath" value="http://127.0.0.1:9090/day64_SSMImageServer"></c:set>
......
    <td>
        <img id='imgSize1ImgSrc' src='${picPath}${items.pic}' height="100" width="100"/>
    </td>