學習SpringMVC

1 介紹

1.1 什麼是MVC?

  • Model:數據模型,提供要展現的數據,所以包含數據和行爲,能夠認爲是領域模型或JavaBean組件(包含數據和行爲),不過如今通常都分離開來:Value Object(數據Dao) 和 服務層(行爲Service)。也就是模型提供了模型數據查詢和模型數據的狀態更新等功能,包括數據和業務。
  • View:負責進行模型的展現,通常就是咱們見到的用戶界面,客戶想看到的東西。
  • Controller(調度員): 接收用戶請求,委託給模型進行處理(狀態改變),處理完畢後把返回的模型數據返回給視圖,由視圖負責展現。也就是說控制器作了個調度員的工做。
  • 最經常使用的MVC:(Model)Bean +(view) Jsp +(Controller) Servlet

1.2 Model1時代

  • 分爲:視圖層V和模型層M;由視圖層的view來控制分發數據並展現給用戶
  • 缺點:JSP職責不單一,太重,不便於維護

1.3 Model2時代(MVC延續至今)

  • 流程:分爲了Contrller,Model,View
  • 訪問流程:
  1. 用戶發請求
  2. Servlet接收請求數據,並調用對應的業務邏輯方法
  3. 業務處理完畢,返回更新後的數據給servlet
  4. servlet轉向到JSP,由JSP來渲染頁面
  5. 響應給前端更新後的頁面

1.4 回顧Servlet建立

  1. 建立maven,父工程:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ssl</groupId>
    <artifactId>SpringMVC</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <!--父工程導入依賴-->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

    </dependencies>

    <!--資源過濾器,防止導入資源失敗問題,最好在父子pom.xml裏都加入一下代碼-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>

            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

</project>
  1. 建立子工程,idea右鍵Add Framwork Support添加web支持
  2. 實現HelloServlet繼承HttpServlet接口,並建立/WEB-INF/jsp/test.jsp
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1 得到參數
        //2 調用業務層
        //3 視圖轉發或者重定向
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}
  1. web.xml中註冊HelloServlet,測試跳轉:http://localhost:8080/springmvc_01_servlet//helloServlet

<?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>HelloServlet</servlet-name>
        <servlet-class>com.ssl.web.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/helloServlet</url-pattern>
    </servlet-mapping>
</web-app>

2 第一個SpringMVC

  • 概念:SpringMVC是Spring框架中的一個分支,是基於Java實現MVC的輕量級Web框架
  • 核心:Spring的web框架圍繞DispatcherServlet [ 調度Servlet ] 設計的。

2.1 執行原理

SpringMVC底層工做原理:javascript

  1. DispatcherServlet表示前置控制器,是整個SpringMVC的控制中心。用戶發出請求,DispatcherServlet接收請求並攔截請求。css

    1. 假設url爲 : http://localhost:8080/SpringMVC/hello
    2. 服務器域名:http://localhost:8080
    3. web站點:/SpringMVC
    4. hello表示控制器:/hello
    5. 經過分析,如上url表示爲:請求位於服務器localhost:8080上的SpringMVC站點的hello控制器。
  2. HandlerMapping爲處理器映射。DispatcherServlet調用HandlerMapping,HandlerMapping根據請求url查找Handler。
  3. HandlerExecution表示具體的Handler,其主要做用是根據url查找控制器,如上url被查找控制器爲:hello。
  4. HandlerExecution將解析後的信息傳遞給DispatcherServlet,如解析控制器映射等。
  5. HandlerAdapter表示處理器適配器,其按照特定的規則去執行Handler。
  6. Handler讓具體的Controller執行。
  7. Controller將具體的執行信息返回給HandlerAdapter,如ModelAndView。
  8. HandlerAdapter將視圖邏輯名或模型傳遞給DispatcherServlet。
  9. DispatcherServlet調用視圖解析器(ViewResolver)來解析HandlerAdapter傳遞的邏輯視圖名。
  10. 視圖解析器將解析的邏輯視圖名傳給DispatcherServlet。
  11. DispatcherServlet根據視圖解析器解析的視圖結果,調用具體的視圖。
  12. 最終視圖呈現給用戶。

2.2 不使用註解開發

  • 瞭解具體的執行過程=面試談資。雖然開發中不會這麼麻煩的使用,但必須看完-理解-繼續學習

1 配置web.xml

  • 完成DispatcherServlet,關聯resource配置文件

<?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">
    <!--配置DispatcherServlet:SpringMVC核心-->
    <servlet>
        <servlet-name>SpringMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--關聯一個SpringMvc的resource配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMvc_servlet.xml</param-value>
        </init-param>
        <!--啓動級別-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--匹配全部的請求: / :只匹配請求,不包含全部的.jsp
                      /*:匹配全部的請求,包括jsp頁面
    -->
    <servlet-mapping>
        <servlet-name>SpringMvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

2 配置springMvc_servlet.xml

  • 得到視圖解析器、映射器、適配器,綁定跳轉url
<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--處理器映射器HandlerMapping:查找訪問的url控制器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <!--處理器適配器HandlerAdapter:controller將處理好的數據返回給HandlerAdapter-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <!--視圖解析器ViewResolver:將後端處理好的數據和視圖傳給DispatchServlet,DS再交給ViewResolver先解析一遍,確認無誤再傳給前端
        必須熟悉,之後還要學模版引擎Thymeleaf/Freemarker...
        1 獲取ModeAndView的數據
        2 解析ModeAndView的視圖名字
        3 拼接視圖名字,找到對應的視圖 WEB-INF/jsp/hello.jsp
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <!--BeanNameUrlHandlerMapping處理器:綁定跳轉的url=頁面訪問的網址-->
    <bean id="/hello" class="com.ssl.controller.HelloController"/>
</beans>

3 /WEB-INF/jsp/hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>hello</title>
</head>
<body>
<%--接受傳遞的參數--%>
${msg}
</body>
</html>

4 HelloController實現Controller

public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //1 建立modelAndView
        ModelAndView mv = new ModelAndView();
        //2 調用業務層,這裏沒有,就不寫
        //3 封裝對象,放在mv中添加
        mv.addObject("msg", "Hello SpringMvc");
        //4 封裝要跳轉的視圖,WEB-INF/jsp/hello.jsp
        mv.setViewName("hello");
        return mv;
    }
}

==5 SpringMVC原理回顧==

  • 反覆觀看,理解原理!

2.3 使用註解開發

1 web.xml

<?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>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springMvc_servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

2 springMvc_servlet.xml

  • 註解省略了映射器、適配器,專一於寫視圖解析器;跳轉的Controller也不用配置進Spring

<?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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--自動掃描包,讓指定包下的註解生效,由IOC容器統一管理-->
    <context:component-scan base-package="com.ssl.controller"/>
    <!--讓SpringMvc不處理靜態資源。讓.css,.js等不進視圖解析器-->
    <mvc:default-servlet-handler/>
    <!--註解加載映射器、適配器,不用以前那麼麻煩配置了-->
    <mvc:annotation-driven/>
    <!--配置視圖解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

3 /WEB-INF/jsp/hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>hello</title>
</head>
<body>
${msg}
</body>
</html>

4 HelloController

  • 簡化了實現的接口,使用@註解配置映射器
  • 訪問:http://localhost:8080/springmvc_03_annotation/hello

@Controller
public class HelloController {
    /**
     * @param model 模型
     * @return 被視圖解析器處理:訪問"/WEB-INF/jsp/hello.jsp資源
     * 訪問的url:RequestMapping("/hello")
     */
    @RequestMapping("/hello")
    public String hello(Model model) {
        //封裝數據
        model.addAttribute("msg", "Hello SpringMvc_annotation");
        //被視圖解析器處理:訪問"/WEB-INF/jsp/hello.jsp資源
        return "hello";
    }

3 Controller和RestFul

  1. 配置web.xml
<?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>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring_mvc_servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

   <!-- <filter>
        <filter-name>encode</filter-name>
        <filter-class>com.ssl.filter.EncodeFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>encode</filter-name>
        <url-pattern>/</url-pattern>
    </filter-mapping>-->
    <filter>
        <filter-name>encode</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>encode</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
  1. spring_mvc_servlet.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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--自動掃描包,讓指定包下的註解生效,由IOC容器統一管理-->
    <context:component-scan base-package="com.ssl.controller"/>
    <!--讓SpringMvc不處理靜態資源。讓.css,.js等不進視圖解析器-->
    <mvc:default-servlet-handler/>
    <!--註解加載映射器、適配器,不用以前那麼麻煩配置了-->
    <mvc:annotation-driven/>
    <!--以上的是定死的代碼,
        如下是配置視圖解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <!--不使用註解開發的適配器:/demo1,注意點是id須要配置/-->
    <bean id="/demo" class="com.ssl.controller.ControllerDemo1"/>
</beans>

3.1 Controller

  • 不使用註解,極其不推薦使用,由於:html

    • 配置麻煩:<bean id="/demo" class="com.ssl.controller.ControllerDemo1"/> ,而且須要 implements Controller
    • 不夠靈活,太費力氣,浪費時間
    • 訪問:http://localhost:8080/springmvc_04_controller/demo
public class ControllerDemo1 implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("demo1","demo1:Controller會返回一個modelAndView");
        modelAndView.setViewName("demo1");
        return modelAndView;
    }
}

3.2 @Controller

  • 使用註解開發,@Controller註冊進Spring容器,若是返回值是String,而且有具體的頁面能夠跳轉,那麼就會被視圖解析器解析
  • 訪問:http://localhost:8080/springmvc_04_controller/demo2
@Controller
public class ControllerDemo2 {
    @RequestMapping("/demo2")
    public String test1(Model model) {
        model.addAttribute("demo2", "demo2");
        return "demo2";
    }
}

3.3 @RequestMapping

  • 能夠在類和方法上配置url訪問路徑
  • 訪問:http://localhost:8080/springmvc_04_controller/controller/demo3
@Controller
@RequestMapping("/controller")
public class ControllerDemo3 {
    @RequestMapping("/demo3")
    public String test1(Model model) {
        model.addAttribute("demo3", "demo3");
        return "demo3";
    }
}

3.4 RestFul風格

  • 優勢:前端

    • 最大的優點是安全,看不出源代碼的參數和意義
    • 實現地址複用,使得get和post訪問url相同,框架會自動進行類型轉換
    • 高效:支持緩存
  • 缺點:java

    • 不像原生的url見名知意,url理解不直觀
  • 實現方式:mysql

    • 1:url @GetMapping("/addRest/{a}/{b}") + 參數@PathVariable int a, @PathVariable int bjquery

    • 2:url @PostMapping("/addRest/{a}/{b}") + 參數不變@PathVariable int a, @PathVariable int bweb

      • 使用Postman中的post訪問:http://localhost:8080/springmvc_04_controller/addRest/1/2
@Controller
public class RestFulController {

    /**
     * 原生的url:http://localhost:8080/springmvc_04/add?a=1&b=1
     */
    @RequestMapping("/add")
    public String getAdd1(int a, int b, Model model) {
        int result = a + b;
        model.addAttribute("add", "原生的url:結果爲" + result);
        return "add";
    }

    /**
     * RestFul方式一:method = get
     * RequestMapping("/addRest/{a}/{b}" method=requestMethod.GET) = @GetMapping()
     * http://localhost:8080/springmvc_04/addRest/1/1
     */
    @GetMapping("/addRest/{a}/{b}")
    public String getAdd2(@PathVariable int a, @PathVariable int b, Model model) {
        int result = a + b;
        model.addAttribute("add", "Rest的url:結果爲" + result);
        return "addRest";
    }

    /**
     * 複用相同的url
     * RestFul方式二:method=post,使用RestFul的話,請求的url和GET就同樣了
     */
    @PostMapping("/addRest/{a}/{b}")
    public String getAdd3(@PathVariable int a, @PathVariable int b, Model model) {
        int result = a + b;
        model.addAttribute("add", "Rest的url:結果爲" + result);
        return "addRest";
    }
}

3.5 重定向和轉發

  • 可使用原生的request轉發或者response重定向
  • 推薦使用SpringMvc的return 「forward:xxx」/"redirect:xxx"
@Controller
public class ModelTest1 {
    //原生的轉發:返回值是void,沒有通過視圖解析器;原生的重定向一樣如此,都不走視圖解析器,直接重定向
    @RequestMapping("/test1")
    public void test1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = request.getSession().getId();
        System.out.println(id);
        request.getRequestDispatcher("index.jsp").forward(request,response);
    }
    //SpringMvc轉發:測試結果是不走視圖解析器,url沒變是轉發
    @RequestMapping("/test2")
    public String test2(Model model) {
        model.addAttribute("demo1","這是test2中的Spring轉發");
        return "forward:/WEB-INF/jsp/demo1.jsp";
    }
    //SpringMvc重定向:測試結果是不走視圖解析器
    @RequestMapping("/test3")
    public String test3() {
        System.out.println("跳轉回首頁index.jsp");
        return "redirect:index.jsp";
    }
}

3.6 接受請求參數和數據回顯

  • 前端提交的name和後端映射器接受的形參名同樣,則直接接受
  • 前端提交的name和後端映射器接受的形參名不用同樣,再形參前@RequestParam("xxx")更更名稱一致面試

    • 養成習慣:不管是否同樣,都必須加上@RequestParam
  • 後端參數封裝若是成一個pojo,前端傳過來的name會自動pojo中的成員屬性,不匹配的屬性=null/0
  • 如何解決中文亂碼問題?請看下節!
@Controller
public class UserController {
    /** http://localhost:8080/springmvc_04/t1?id=1&name=abc&age=18
     * @param user SpringMvc 會自動封裝數據到參數裏的pojo,不匹配的屬性=null/0
     */
    @GetMapping("/t1")
    public String getUser(User user){
        System.out.println(user);
        return "test1";
    }
}

3.7 Model,ModelAndView等

  • Model:精簡版,適合初學者,大多數狀況封裝參數,設置轉發視圖層就夠用
  • ModelMap:繼承了LinkedHashMap,有它的方法和特性
  • ModelAndView:能夠在存儲數據的同時,能夠進行設置返回的邏輯視圖,進行控制展現層的跳轉
  • 怎麼學習:用80%的時間學號基礎,18%時間研究框架,2%學點英文,剩下不會的看官方文檔

4 亂碼問題

  • 方法一:web.xml裏面配置的SpringMvc自帶的過濾器CharacterEncodingFilterspring

    • <url-pattern>/*</url-pattern>:由於要跳轉到xxx.jsp頁面,因此url是/*(≠/)
<?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">
    <!--配置SpringMVC-->
    <servlet>
        <servlet-name>springMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring_mvc_servlet.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--web容器解決中文亂碼問題-->
    <filter>
        <filter-name>encode</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>encode</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
  • 方法二:一勞永逸,但須要重啓Tomcat服務器,修改Tomcat裏面的server.xml配置文件:URIEncoding = "UTF-8"
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           URIEncoding = "UTF-8"/>
<!-- A "Connector" using the shared thread pool-->

5 JSON

5.1 前端初識Json

  • 前端展現二者數據,學會js和json互相轉換
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>json</title>
    <script type="text/javascript">
        //user是一個js對象
        var user = {
            name: "張三",
            age: 18,
            sex: "男"
        };
        //後端傳的json實際上是一個字符串,前端將後端傳的json轉換成js對象渲染在頁面上
        //jsonUser:模擬後端傳的json數據
        //js轉換成json
        var jsonUser = JSON.stringify(user);
        console.log(jsonUser);
        //jsUser:js是一個對象
        //json轉換成js
        var jsUser = JSON.parse(jsonUser);
        console.log(jsUser)
    </script>
</head>
<body>
</body>
</html>

5.2 Jackson Databind

  • 使用 Jackson Databind能夠快速生成json數據

1 導入依賴

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.10.0</version>
</dependency>
  • json=一個字符串,因此會有中文亂碼問題,須要在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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--自動掃描包,讓指定包下的註解生效,由IOC容器統一管理-->
    <context:component-scan base-package="com.ssl.controller"/>
    <!--讓SpringMvc不處理靜態資源。讓.css,.js等不進視圖解析器-->
    <mvc:default-servlet-handler/>

    <!--註解加載映射器、適配器,解決Json數據中文亂碼問題-->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!--配置視圖解析器,明確json數據不走數據解析器,直接傳給前端-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

2 編寫Controller

  • @RestControoler:該類下全部方法不走視圖解析器,返回一個json數據
  • @ResponceBody:該方法不走視圖解析器,返回一個json數據
  • 訪問:http://localhost:8080/springmvc_05_json/t1,頁面顯示一個json數據,不通過視圖解析器
  • 回顧日期:new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss")
@RestController
public class UserController {
    /*  概念:先後端分離的項目,後端代碼不走視圖解析器,後端傳給前端的是json數據
        方法上:註解@ResponseBody指定該方法不走視圖解析器,會直接返回一個String=json數據就是一個字符串
        類上:註解@RestController指定該類下的全部方法都不走視圖解析器
        Json返回一個對象
     */
    @RequestMapping("/t1")
    public String json1() throws JsonProcessingException {
        User user = new User(1, "張三", 20);
        ObjectMapper jacksonMapper = new ObjectMapper();
        String str_user = jacksonMapper.writeValueAsString(user);
        //user.toString()是本身指定的String可是公司一般是容許的,一般是使用第三方工具來返回String
        //str_user有中文亂碼問題,springMvc能夠統一配置
        return str_user;
    }

    /**
     * Json返回一個List
     */
    @RequestMapping("/t2")
    public String json2() throws JsonProcessingException {
        User user1 = new User(1, "張三", 20);
        User user2 = new User(2, "張三", 21);
        User user3 = new User(3, "張三", 22);
        User user4 = new User(4, "張三", 23);
        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        return new ObjectMapper().writeValueAsString(list);
    }

    /**
     *  json返回一個日期格式
     */
    @RequestMapping("/t3")
    public String json3() throws JsonProcessingException {
        //方式一:原始純java日期轉換:推薦使用
        // String date = new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss").format(new Date());
        ObjectMapper objectMapper = new ObjectMapper();
        //方式二:使用mapper來制定日期格式,先關閉時間戳表示
        objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss"));
        Date date = new Date();
        return objectMapper.writeValueAsString(date);
    }

    @Test
    public void DateTest1() {
        //傳統的java日期格式轉換
        String date = new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss").format(new Date());
        System.out.println(date);
    }
}

5.3 FastJson

  • 阿里巴巴官方提供的,實現Json數據的另外一個工具,比JackSon Databind更方便

1 導包

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>

2 編寫Controller

  • 比Jackson使用更方便
@RequestMapping("/t4")
    public String json4() throws JsonProcessingException {
        User user1 = new User(1, "張三", 20);
        User user2 = new User(2, "張三", 21);
        User user3 = new User(3, "張三", 22);
        User user4 = new User(4, "張三", 23);
        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        String jsonString = JSON.toJSONString(list);
        return jsonString;
    }

6 SSM整合

6.1 環境

  • IDEA+Mysq5.7+Tomca5.7+Maven3.6
  • 數據庫
create database `ssmbuild`;
use `ssmbuild`;
CREATE TABLE `books` (
  `bookId` int(10) NOT NULL AUTO_INCREMENT COMMENT '書id',
  `bookName` varchar(100) NOT NULL COMMENT '書名',
  `bookCounts` int(11) NOT NULL COMMENT '數量',
  `detail` varchar(200) NOT NULL COMMENT '描述',
  KEY `bookId` (`bookId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ssl</groupId>
    <artifactId>ssmbuild</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--依賴:junit,數據庫驅動,鏈接池,Servlet,jsp,mybatis,mybatis-mvc,Spring,SpringMVC-->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
    </dependencies>


    <!--Maven資源過濾設置-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>

            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
</project>

6.2 開發流程

  • 需求分析+設計數據庫+業務+傳給前端頁面
  • 總體效果:

6.3 整合Mybatis

  • mybatis-config.xml

    • 數據庫鏈接交給Spring-dao.xml配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--核心配置文件-->
<configuration>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--配置數據源,交給Spring去作-->
    <!--取別名-->
    <typeAliases>
        <!--resultMap:默認類名小寫爲使用id-->
        <package name="com.ssl.pojo"/>
    </typeAliases>
    <mappers>
        <mapper class="com.ssl.dao.BookMapper"/>
    </mappers>
</configuration>
# db.properties配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=false&amp;useUnicode=true&amp;characterEncoding=utf-8
username=root
password=123456

6.4 整合Spring

  • 1 spring-dao.xml

    • 數據庫鏈接讀取db.properties有bug,手動鏈接jdbcurl和user
<?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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--1 關聯數據庫配置文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--2 鏈接池 此次使用c3p0的鏈接池.常見的數據庫:
    dbcp:半自動操做,不能自動鏈接
    c3p0:自動化操做,而且能夠配置到對象中
    druid,hikari(SpringBoot)-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${driver}"/>
        <property name="jdbcUrl" value="${url}"/>
        <property name="user" value="${username}"/>
        <property name="password" value="${password}"/>
        <!--c3p0的私有屬性-->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!--關閉鏈接後,不自動commit-->
        <property name="autoCommitOnClose" value="false"/>
        <property name="checkoutTimeout" value="10000"/>
        <property name="acquireRetryAttempts" value="2"/>
     </bean>
    <!--3 sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--綁定數據庫-->
        <property name="dataSource" ref="dataSource"/>
        <!--綁定Mybatis的配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    <!--4 配置dao接口掃描包,動態的實現了dao接口能夠注入到Spring容器中,不用寫mapperImpl.xml-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--注入sqlSessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--掃描要掃描的dao的包-->
        <property name="basePackage" value="com.ssl.dao"/>
    </bean>
</beans>
  • 2 spring-service.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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--1 掃描service下的包-->
    <context:component-scan base-package="com.ssl.service"/>
    <!--2 將咱們的全部業務類,注入到Spring,這裏使用bean配置,平時是使用註解-->
    <bean id="BookServiceImpl" class="com.ssl.service.BookServiceImpl">
        <property name="bookMapper" ref="bookMapper"/>
    </bean>
    <!--3  聲明式事務配置-->
    <bean  id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--4 AOP橫切事務,這裏用不到-->
</beans>
  • 3 application.xml

    • 導入其餘配置進spring主配置文件
<?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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <import resource="classpath:spring-dao.xml"/>
    <import resource="classpath:spring-service.xml"/>
    <import resource="classpath:spring-mvc.xml"/>
</beans>

6.5 整合SpringMVC

  • 增長web項目的支持
  • web.xml
<?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">
    <!--SpringMVC配置-->
    <!--1 DispatcherServlet-->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:application.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <!--2 亂碼過濾-->
    <filter>
        <filter-name>encodingFilter</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>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--3 Session過時時間-->
    <session-config>
        <session-timeout>15</session-timeout>
    </session-config>

</web-app>
  • spring-mvc.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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--1 註解驅動-->
    <mvc:annotation-driven/>
    <!--2 靜態資源過濾-->
    <mvc:default-servlet-handler/>
    <!--3 掃描包:Controller-->
    <context:component-scan base-package="com.ssl.controller"/>
    <!--4 視圖解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

6.6 dao層

  • BookMapper接口和BookMapperMapper.xml
public interface BookMapper {
    //增長一本書
    int addBook(Books books);

    //刪除一本書
    int deleteBookById(@Param("bookId") int id);

    //修改一本書
    int updateBook(Books books);

    //查詢一本書根據id
    Books queryBookById(@Param("bookId")int id);

    //查詢所有書
    List<Books> queryAllBook();

    Books queryBookByName(@Param("bookName") String bookName);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--核心配置文件-->
<mapper namespace="com.ssl.dao.BookMapper">
    <insert id="addBook" parameterType="Books">
        insert into ssmbuild.books(bookName, bookCounts, detail)
        values (#{bookName},#{bookCounts},#{detail});
    </insert>
    <delete id="deleteBookById" parameterType="int">
        delete from ssmbuild.books where bookId = #{bookId}
    </delete>
    <update id="updateBook" parameterType="Books">
        update ssmbuild.books set
        bookName=#{bookName},
        bookCounts=#{bookCounts},
        detail=#{detail}
        where bookId=#{bookId};
    </update>
    <select id="queryBookById" parameterType="int" resultType="Books">
        select * from ssmbuild.books where bookId = #{bookId};
    </select>
    <select id="queryAllBook" resultType="Books">
        select * from ssmbuild.books;
    </select>

    <select id="queryBookByName" parameterType="String" resultType="Books">
         select * from ssmbuild.books where bookName=#{bookName}
    </select>
</mapper>

6.7 service層

public interface BookService {
    //增長一本書
    int addBook(Books books);

    //刪除一本書
    int deleteBookById(int id);

    //修改一本書
    int updateBook(Books books);

    //查詢一本書根據id
    Books queryBookById(int id);

    //查詢所有書
    List<Books> queryAllBook();

    Books queryBookByName(String bookName);
}
public class BookServiceImpl implements BookService {
    //注入Dao層
    private BookMapper bookMapper;
    public void setBookMapper(BookMapper bookMapper) {
        this.bookMapper = bookMapper;
    }

    @Override
    public int addBook(Books books) {
        return bookMapper.addBook(books);
    }

    @Override
    public int deleteBookById(int id) {
        return bookMapper.deleteBookById(id);
    }

    @Override
    public int updateBook(Books books) {
        return bookMapper.updateBook(books);
    }

    @Override
    public Books queryBookById(int id) {
        return bookMapper.queryBookById(id);
    }

    @Override
    public List<Books> queryAllBook() {
        return bookMapper.queryAllBook();
    }

    @Override
    public Books queryBookByName(String bookName) {

        return bookMapper.queryBookByName(bookName);
    }
}

6.8 controller層

@Controller
@RequestMapping("/book")
public class BookController {

    @Autowired
    @Qualifier("BookServiceImpl")
    private BookService bookService;

    //查詢所有的書籍,而且返回到一個書籍展現頁面
    @RequestMapping("/allBook")
    public String list(Model model) {
        List<Books> books = bookService.queryAllBook();
        model.addAttribute("list", books);
        return "allBook";
    }

    //跳轉到增長書籍頁面
    @RequestMapping("/toAddBook")
    public String toAddBook() {
        return "addBook";
    }

    //添加書籍
    @RequestMapping("/addBook")
    public String addBook(Books books) {
        int result = bookService.addBook(books);
        if (result > 0) {
            System.out.println("添加書籍成功");
        }
        return "redirect:/book/allBook";
    }

    @RequestMapping("/toUpdateBook")
    public String toUpdate(int bookId, Model model) {
        Books books = bookService.queryBookById(bookId);
        model.addAttribute("book", books);
        return "updateBook";
    }

    /*
        沒有提交事務操做,更新會失敗
     */
    @RequestMapping("/updateBook")
    public String updateBook(Books books) {
        int result = bookService.updateBook(books);
        if (result > 0) {
            System.out.println("修改書籍成功");
        }
        return "redirect:/book/allBook";
    }

    /*
        刪除書籍,回顧RestFul風格
     */
    @RequestMapping("/deleteBook/{bookId}")
    public String deleteBook(@PathVariable("bookId") int bookId) {
        int result = bookService.deleteBookById(bookId);
        if (result > 0) {
            System.out.println("刪除書籍成功");
        }
        return "redirect:/book/allBook";
    }

    @RequestMapping("/queryBook")
    public String queryBook(String queryBookName, Model model) {
        Books books = bookService.queryBookByName(queryBookName);
        //複用,這樣就顯示一個
        List<Books> list = new ArrayList<>();
        list.add(books);
        if (books == null) {
            list= bookService.queryAllBook();
            model.addAttribute("errMsg","未查任何書籍");
        }
        model.addAttribute("list", list);
        return "allBook";
    }
}

6.9 前端頁面

index.xml
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
    <style>
        /*消除字體藍色下劃線*/
        a {
            text-decoration: none;
            color: black;
            font-size: 18px;
        }

        h3 {
            width: 180px;
            height: 38px;
            margin: 100px auto;
            text-align: center;
            line-height: 38px;
            background: deepskyblue;
            border-radius: 5px;
        }
    </style>
</head>
<body>
<h3>
    <a href="${pageContext.request.contextPath}/book/allBook">進入書籍展現頁面</a>
</h3>
</body>
</html>
WEB-INF/jsp/addBook.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%--BootStrap美化界面--%>
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <div class="row clearfix">
        <%--屏幕分紅12列--%>
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small>新增書籍</small>
                </h1>
            </div>
        </div>
    </div>
    <%--BootStrap官網拿"表單"數據  name屬性保證pojo屬性名稱一致 required保證必須提交--%>
    <form action="${pageContext.request.contextPath}/book/addBook" method="post">
        <div class="form-group">
            <label for="bName">書籍名稱:</label>
            <input type="text" name="bookName" class="form-control" id="bName" required>
        </div>
        <div class="form-group">
            <label for="bCount">書籍數量:</label>
            <input type="text" name="bookCounts" class="form-control" id="bCount" required>
        </div>
        <div class="form-group">
            <label for="bDesc">書籍描述:</label>
            <input type="text" name="detail" class="form-control" id="bDesc" required>
        </div>
        <div class="form-group">
            <input type="submit" class="form-control" value="添加">
        </div>

    </form>
</head>
<body>

</body>
</html>
WEB-INF/jsp/allBook.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>書籍展現頁面</title>
    <%--BootStrap美化界面--%>
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

</head>
<body>

<div class="container">
    <div class="row clearfix">
        <%--屏幕分紅12列--%>
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small> 書籍列表——————————顯示全部書籍</small>
                </h1>
            </div>
        </div>
        <div class="row">
            <div class="col-md-4 column">
                <a class="btn btn-primary" href="${pageContext.request.contextPath}/book/toAddBook">新增書籍</a>
                <a class="btn btn-primary" href="${pageContext.request.contextPath}/book/allBook">顯示所有書籍</a>
            </div>

            <div class="col-md-4 column"></div>

            <div class="col-md-8 column">
                <form action="${pageContext.request.contextPath}/book/queryBook" method="post" style="float: right">
                    <%--前端未傳任何信息,就顯示錯誤提示信息:未查任何書籍--%>
                    <span style="color: red;font-weight: bold">${errMsg}</span>
                    <%--class="form-inline"保證在同一行--%>
                    <input type="text" name="queryBookName" class="form-inline" placeholder="請輸入要查詢的書籍名稱">
                    <input type="submit" value="查詢" class="btn btn-primary">

                </form>
            </div>
        </div>

    </div>
    <div class="row clearfix">
        <div class="col-md-12 column">
            <table class="table table-hover table-striped">
                <thead>
                <tr>
                    <th>書籍編號</th>
                    <th>書籍名稱</th>
                    <th>書籍數量</th>
                    <th>書籍詳情</th>
                    <th>操做</th>
                </tr>
                </thead>
                <%--書籍從數據庫中查詢出來,從這個list中遍歷出來,foreach--%>
                <tbody>
                <c:forEach var="book" items="${list}">
                    <tr>
                        <td>${book.bookId}</td>
                        <td>${book.bookName}</td>
                        <td>${book.bookCounts}</td>
                        <td>${book.detail}</td>
                        <td>

                            <a href="${pageContext.request.contextPath}/book/toUpdateBook?bookId=${book.bookId}">修改</a>
                            &nbsp; | &nbsp;
                            <a href="${pageContext.request.contextPath}/book/deleteBook/${book.bookId}">刪除</a>
                        </td>
                    </tr>
                </c:forEach>
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>
WEB-INF/jsp/updateBook.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%--BootStrap美化界面--%>
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <div class="row clearfix">
        <%--屏幕分紅12列--%>
        <div class="col-md-12 column">
            <div class="page-header">
                <h1>
                    <small>修改書籍</small>
                </h1>
            </div>
        </div>
    </div>
    <%--BootStrap官網拿"表單"數據  name屬性保證pojo屬性名稱一致 required保證必須提交--%>
    <form action="${pageContext.request.contextPath}/book/updateBook" method="post">
        <%--提交失敗:沒有回顯:問題:
            1. 事務沒有提交
            2. sql執行失敗,沒有提交BookId,須要前端的隱藏域
        --%>
        <%--添加bookId的隱藏域--%>
        <input type="hidden" name="BookId" value="${book.bookId}">
        <div class="form-group">
            <label for="bName">書籍名稱:</label>
            <input type="text" name="bookName" class="form-control" id="bName" value="${book.bookName}" required>
        </div>
        <div class="form-group">
            <label for="bCount">書籍數量:</label>
            <input type="text" name="bookCounts" class="form-control" id="bCount" value="${book.bookCounts}"required>
        </div>
        <div class="form-group">
            <label for="bDesc">書籍描述:</label>
            <input type="text" name="detail" class="form-control" id="bDesc" value="${book.detail}" required>
        </div>
        <div class="form-group">
            <input type="submit" class="form-control" value="添加">
        </div>

    </form>
</head>
<body>

</body>
</html>

7 Ajax

7.1 概念

  • Ajax就是一個異步無刷新請求,無需更新整個頁面就異步加載一些數據,交互性更強
  • 模擬異步請求
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模擬Ajax異步請求</title>
    <script>
        function go() {
            var url = document.getElementById("url").value;
            document.getElementById("iframe1").src = url;
        }
    </script>
</head>
<body>
<div>
    <p>請輸入地址:</p>
    <p>
        <input type="text" id="url">
        <input type="button" id="button" value="提交" onclick="go()">
    </p>
</div>
<div>
    <iframe id="iframe1" style="width:100%;height: 500px">
    </iframe>
</div>
</body>
</html>

7.2 使用JQ使用Ajax

1 初試Ajax

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
    <%--加載動態的JQ資源--%>
    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
    <script>
        /*
        AJax後盾必須懂的東西:
        url:後端接受的地址
        data:後端接受到的請求參數,json數據格式=先後端分離時候,後端傳的數據便於前端接受就是json數據
        success:後端接受成功返回的函數
        error:後盾失敗接受返回的函數
        */
        function username() {
            $.post({
                url: "${pageContext.request.contextPath}/a1",
                data: {"name": $("#username").val()},
                success: function (data, status) {
                    console.log("data:" + data);
                    console.log("status:" + status);
                }
            })
        }

    </script>
</head>
<body>
<%--實現Ajax異步請求
    1 綁定單擊事件
    2 單擊事件函數使用Jq:$.post({})
--%>
用戶名:<input type="text" id="username" onclick="username()">
</body>
</html>

2 Ajax實現異步加載

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Ajax</title>

    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
    <script>
        /*頁面加載完*/
        $(function () {
            /*綁定btn單擊事件*/
            $("#btn").click(function () {
                /*JQ使用Ajax異步請求*/
                $.post("${pageContext.request.contextPath}/a2", function (data) {
                    // data接受返回的值
                    //console.log(data);
                    var html = "";
                    for (let i = 0; i < data.length; i++) {
                        html += "<tr>" +
                            "<td>" + data[i].name + "</td>" +
                            "<td>" + data[i].age + "</td>" +
                            "<td>" + data[i].sex + "</td>" +
                            +"<tr>"
                    }
                    $("#content").html(html);
                });
            });

        })
    </script>
</head>
<body>
<input type="button" id="btn" value="加載數據">
<table>
    <tr>
        <td>姓名</td>
        <td>年齡</td>
        <td>性別</td>
    </tr>
    <tbody id="content">

    </tbody>

</table>
</body>
</html>

3 實現登陸驗證

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login</title>
    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
    <script>
        function nameFun() {
            $.post({
                url: "${pageContext.request.contextPath}/a3",
                data: {"name": $("#name").val()},
                success: function (data) {
                    //console.log(data);
                    if (data.toString() === "用戶名成功") {
                        $("#userInfo").css("color", "green");
                    } else {
                        $("#userInfo").css("color", "red");
                    }
                    $("#userInfo").html(data);
                }
            })
        }

        function passwordFun() {
            $.post({
                url: "${pageContext.request.contextPath}/a3",
                data: {"password": $("#password").val()},
                success: function (data) {
                    if (data.toString() === "密碼正確") {
                        $("#userPasswordInfo").css("color", "green");
                    }else {
                        $("#userPasswordInfo").css("color", "red");
                    }
                    $("#userPasswordInfo").html(data);
                }
            })
        }
    </script>
</head>
<body>
<p>
    用戶名:<input type="text" id="name" onclick="nameFun()">
    <%--span提示信息--%>
    <span id="userInfo"></span>
</p>
<p>
    用戶密碼:<input type="password" id="password" onclick="passwordFun()">
    <span id="userPasswordInfo"></span>
</p>
</body>
</html>

appliacation.xml添加json亂碼問題

<?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:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--1 自動掃描包,讓指定包下的註解生效,由IOC容器統一管理-->
    <context:component-scan base-package="com.ssl.controller"/>
    <!--2 註解驅動-->
    <mvc:annotation-driven/>
    <!--  使用JQ,使用靜態資源過濾須要引用,動態就不須要-->
    <mvc:default-servlet-handler/>
    <!--註解加載映射器、適配器,解決Json數據中文亂碼問題-->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    <!--3 以上的是定死的代碼,如下是配置視圖解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

7.3 後端須要的前端知識

  • HTML+CSS+Js(超級熟練)
  • Js必會?:

    • 函數閉包?
    • DOM

      • id,name.tag
      • create,remove
    • BOM:瀏覽器對象模型

      • window
      • document

8 攔截器

8.1 概念

  • 數據獨立性:Servlet中的是過濾器,而攔截器是SpringMVC框架獨有的,獨享request和response
  • 攔截器只會攔截訪問的控制器方法,若是訪問的是jsp/html/css等式不會攔截的
  • 攔截器是基於AOP思想的,和AOP實現是同樣的,在application.xml中配置
<!--攔截器配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--
                /**是攔截以後全部的請求,好比/admin/a1/2131
            -->
        <mvc:mapping path="/**"/>
        <bean class="com.ssl.config.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

8.2 自定義攔截器

  • 實現 HandlerInterceptor
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //return true:執行下一個攔截器
        System.out.println("===========處理前,這裏進行攔截處理=================");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("===========處理後,一般進行日誌管理=================");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("===========清潔中=================");
    }
}
  • applica.xml配置
<!--攔截器配置-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--
                /**是攔截以後全部的請求,好比/admin/a1/2131
            -->
        <mvc:mapping path="/**"/>
        <bean class="com.ssl.config.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

8.3 登陸驗證判斷

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        request.getRequestURL();
        //URL:http://localhost:8080/springmvc_07_interceptor/user//main
        System.out.println("URL:" + request.getRequestURL());
        //URI:/springmvc_07_interceptor/user//main
        System.out.println("URI:" + request.getRequestURI());

        if (session.getAttribute("username") == null || session.getAttribute("password") == null) {
            request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        } else if (session.getAttribute("username").equals("admin") && session.getAttribute("password").equals("123456")) {
            return true;
        }
        if (request.getRequestURI().contains("ogin")) {
            return true;
        }
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
        return false;
    }
}
@Controller
@RequestMapping("/user")
public class LoginController {

    @RequestMapping("/main")
    public String main() {
        //沒登陸就不等進入首頁
        return "main";
    }

    @RequestMapping("/goLogin")
    public String goLogin() {
        return "login";
    }


    @RequestMapping("/login")
    public String login(String username, String password, HttpSession session, Model model) {
        session.setAttribute("username", username);
        session.setAttribute("password", password);
        model.addAttribute("username", username);
        return "main";
    }

    @RequestMapping("/outUser")
    public String outUser(HttpSession session) {
        session.removeAttribute("username");
        session.removeAttribute("password");
        return "main";
    }
}

9 文件上傳

  • 前端form添加enctype="multipart/form-data",method="post"
<form enctype="multipart/form-data" method="post" action="">
    
  </form>
  • 後端pom導包
<dependencies>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>
        <!--導入高版本的api-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
    </dependencies>
  • Spring自帶的文件上傳,application.xml配置
<!--4 文件上傳配置-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="utf-8"/>
        <!--最大上傳大小:單位是1字節-->
        <property name="maxUploadSize" value="10485760"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>
@RestController
public class FileController {
    @RequestMapping("/upFile")
    public String upFile(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
        //設置文件保存路徑
        String path = request.getServletContext().getRealPath("/upload");
        System.out.println("path:" + path);
        File realPath = new File(path);
        if (!realPath.exists()) {
            realPath.mkdir();
        }
        System.out.println("上傳的文件地址:" + realPath);
        //CommonsMultipartFile的方法寫文件,簡化
        file.transferTo(new File(realPath + "/" + file.getOriginalFilename()));
        return "redirect:/index.jsp";
    }
}

10 文件下載

  • 方式一:寫方法下載
@RequestMapping(value = "/download")
    public String downLoad(HttpServletResponse response, HttpServletRequest request) throws IOException {
        //手動設置,要下載的圖片地址
        String path = request.getServletContext().getRealPath("/upload");
        String fileName = "1.png";
        //設置響應頭
        response.reset();//設置頁面不緩存,清空buffer
        response.setCharacterEncoding("UTF-8");
        response.setContentType("multipart/form-data");//二進制傳輸數據
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
        File file = new File(path, fileName);
        //讀取文件-輸入流
        InputStream input = new FileInputStream(file);
        //寫入文件-輸出流
        OutputStream out = response.getOutputStream();
        byte[] buff = new byte[1024];
        int index = 0;
        while ((index = input.read(buff)) != -1) {
            out.write(buff,0,index);
            out.flush();
        }
        input.close();
        out.close();
        return "redirect:/index.jsp";
    }
<a href="${pageContext.request.contextPath}/static/1.png">圖片下載</a>
相關文章
相關標籤/搜索