SpringMVC

小公羊 2021-09-20 00:07:24 阅读数:881

springmvc

1.什麼是SpringMVC

1.1、什麼是MVC

  • MVC是模型(Model)、視圖(View)、控制器(Controller)的簡寫,是一種軟件設計規範。
  • 是將業務邏輯、數據、顯示分離的方法來組織代碼。
  • MVC主要作用是降低了視圖與業務邏輯間的雙向偶合
  • MVC不是一種設計模式,MVC是一種架構模式。當然不同的MVC存在差异。

Model(模型):數據模型,提供要展示的數據,因此包含數據和行為,可以認為是領域模型或JavaBean組件(包含數據和行為),不過現在一般都分離開來:Value Object(數據Dao) 和 服務層(行為Service)。也就是模型提供了模型數據查詢和模型數據的狀態更新等功能,包括數據和業務。

View(視圖):負責進行模型的展示,一般就是我們見到的用戶界面,客戶想看到的東西。

Controller(控制器):接收用戶請求,委托給模型進行處理(狀態改變),處理完畢後把返回的模型數據返回給視圖,由視圖負責展示。也就是說控制器做了個調度員的工作。

最典型的MVC就是JSP + servlet + javabean的模式。

1.2、Spring概述

Spring MVC是Spring Framework的一部分,是基於Java實現MVC的輕量級Web框架。

查看官方文檔:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web

我們為什麼要學習SpringMVC呢?

Spring MVC的特點:

  1. 輕量級,簡單易學
  2. 高效 , 基於請求響應的MVC框架
  3. 與Spring兼容性好,無縫結合
  4. 約定優於配置
  5. 功能强大:RESTful、數據驗證、格式化、本地化、主題等
  6. 簡潔靈活

Spring的web框架圍繞DispatcherServlet [ 調度Servlet ] 設計。

DispatcherServlet的作用是將請求分發到不同的處理器。從Spring 2.5開始,使用Java 5或者以上版本的用戶可以采用基於注解形式進行開發,十分簡潔;

正因為SpringMVC好 , 簡單 , 便捷 , 易學 , 天生和Spring無縫集成(使用SpringIoC和Aop) , 使用約定優於配置 . 能够進行簡單的junit測試 . 支持Restful風格 .异常處理 , 本地化 , 國際化 , 數據驗證 , 類型轉換 , 攔截器 等等......所以我們要學習 .

最重要的一點還是用的人多 , 使用的公司多 .

1.3、中心控制器

​ Spring的web框架圍繞DispatcherServlet設計。DispatcherServlet的作用是將請求分發到不同的處理器。從Spring 2.5開始,使用Java 5或者以上版本的用戶可以采用基於注解的controller聲明方式。

​ Spring MVC框架像許多其他MVC框架一樣, 以請求為驅動 , 圍繞一個中心Servlet分派請求及提供其他功能DispatcherServlet是一個實際的Servlet (它繼承自HttpServlet 基類)

SpringMVC的原理如下圖所示:

​ 當發起請求時被前置的控制器攔截到請求,根據請求參數生成代理請求,找到請求對應的實際控制器,控制器處理請求,創建數據模型,訪問數據庫,將模型響應給中心控制器,控制器使用模型與視圖渲染視圖結果,將結果返回給中心控制器,再將結果返回給請求者。

1.4、SpringMVC執行原理

圖為SpringMVC的一個較完整的流程圖,實線錶示SpringMVC框架提供的技術,不需要開發者實現,虛線錶示需要開發者實現。

簡要分析執行流程

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

    我們假設請求的url為 : http://localhost:8080/SpringMVC/hello

    如上url拆分成三部分:

    http://localhost:8080服務器域名

    SpringMVC部署在服務器上的web站點

    hello錶示控制器

    通過分析,如上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. 最終視圖呈現給用戶。

在這裏先聽一遍原理,不理解沒有關系,我們馬上來寫一個對應的代碼實現大家就明白了,如果不明白,那就寫10遍,沒有笨人,只有懶人!

2.實現SpringMVC(配置版)

  1. 新建一個Moudle,添加Web支持。
  2. 確定導入了SpringMVC的依賴
  3. 配置web.xml,注册DispatcherServlet前端控制器,這是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">
<!--1.注册前端控制器:DispatcherServlet,這是SpringMVC的核心-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 也可不配置參數,默認加載 /WEB-INF/springmvc-servlet.xml -->
<!-- DispatcherServlet要綁定一個springmvc配置文件:【servlet-name】- servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--啟動級別-1-->
<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>
  1. 配置SpringMVC的配置文件:springmvc-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--1.添加處理映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--2.添加處理器適配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--3.添加視圖解析器:DispatcherServlet給它的ModelAndView
1.獲取了ModelAndView的數據
2.解析ModelAndView的視圖名字
3.拼接視圖名字,找到對應的視圖 /WEB-INF/jsp/hello.jsp
4.將數據渲染到這個視圖上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前綴-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--後綴-->
<property name="suffix" value=".jsp"/>
</bean>
<!--4.Handler-->
<bean id="/hello" class="com.dzj.controller.HelloController" />
</beans>
  1. 創建Controller類
package com.dzj.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//注意:我們這裏先導入Controller接口
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception{
//模型和視圖
ModelAndView mv = new ModelAndView();
//業務代碼,假設這裏處理了一個業務,返回的結果為result
String result = "HelloSpringMVC!";
//封裝對象,放在ModelAanView中,Model
mv.addObject("msg",result);
//視圖跳轉封裝要跳轉的視圖,放在ModelAndView中,view
mv.setViewName("hello"); // 自動拼接成:/WEB-INF/jsp/hello.jsp
return mv;
}
}

3.實現SpringMVC(注解版)

第一步:新建一個Moudle,添加web支持,建立包結構 com.dzj.controller

第二步:由於Maven可能存在資源過濾問題,我們將配置完善!

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

第三步:在pom.xml文件引入相關的依賴:主要有Spring框架核心庫、SpringMVC、servlet、JSTL等。如果在父依賴中已經引入了,就不需要再引入。注意:在項目結構下添加 lib文件夾,添加 Library Files

<!--導入依賴-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2.1-b03</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<!--資源過濾-->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>

第四步:配置web.xml文件

  • 注册DispatcherServlet
  • 關聯SpringMVC配置文件
  • 啟動級別為1
  • 映射路勁為 “ / ” ,【不要用“ /* ” ,會404】
<!--1.注册前端控制器:DispatcherServlet,這是SpringMVC的核心-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 也可不配置參數,默認加載 /WEB-INF/springmvc-servlet.xml -->
<!-- DispatcherServlet要綁定一個springmvc配置文件:【servlet-name】- servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--啟動級別-1-->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- / 匹配接受用戶所有的請求;(不包括.jsp)-->
<!-- /* 匹配接受用戶所有的請求;(包括.jsp)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

第五步:添加Spring MVC配置文件

<?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
http://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.dzj.controller"/>
<!-- 讓Spring MVC 不處理靜態資源 .css .js .html .mp3 .mp4-->
<mvc:default-servlet-handler />
<!--
支持mvc注解驅動
在spring中一般采用@RequestMapping注解來完成映射關系;
要想使@RequestMapping注解生效;
必須想上下文中注册DefaultAnnotationHandlerMapping和一個AnnotationMethodHandlerAdapter實例,
這兩個實體分別在類級別和方法級別處理;
而annotation-driver配置幫助我們自動完成上述兩個實例的注入。
-->
<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>

第六步:創建controller,HelloController.java

@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
//在模型中添加 msg 和值,可以在jsp中取出並渲染
model.addAttribute("msg","Hello,SpringMVCAnnotation!");
return "hello"; // hello 會被視圖解析器處理
}
}

第七步:創建視圖層,hello.jsp

第八步:配置Tomcat運行

4.注解使用說明

@Controller

//被@Controller注解的類,代錶這個類被Spring托管,此類中的方法如果返回值是String類型,
// 並且有具體的頁面可以跳轉,那麼就會被視圖解析器解析
@Controller
public class ControllerTest2 {
@RequestMapping("/test2")
public String test2(Model model){
model.addAttribute("msg","ControllerTest2");
return "test";
}
}

@RequestMapping

@Controller
@RequestMapping("/c3") //標注在類上,可理解為第一層級目錄
public class ControllerTest3 {
@RequestMapping("/test2") //標注在方法上,可理解為第二層級目錄
public String test3(Model model){
model.addAttribute("msg","ControllerTest3");
return "test";
}
}
@Controller
public class ControllerTest3 {
@RequestMapping("/c3/test2") //等價於上面的寫法
public String test3(Model model){
model.addAttribute("msg","ControllerTest3");
return "test";
}
}

5.RestFul風格

@Controller
public class RestFulController {
// 原來的方式 ---> http://localhost:8080/add?a=3&b=7
// RestFul方式 ---> http://localhost:8080/add/1/2
// @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.DELETE)
@PostMapping("/add/{a}/{b}")
public String test1(@PathVariable int a,@PathVariable String b, Model model){
//a,b為前端傳遞過來的參數
String res = a + b;
model.addAttribute("msg","結果為1:" + res);
return "test";
}
@GetMapping("/add/{a}/{b}")
public String test2(@PathVariable int a,@PathVariable String b, Model model){
//a,b為前端傳遞過來的參數
String res = a + b;
model.addAttribute("msg","結果為2:" + res);
return "test";
}
}

6.SpringMVC的結果跳轉方式

1.ModelAndView

設置ModelAndView對象,根據view的名稱,和視圖解析器跳轉到指定的頁面

頁面 = {視圖解析器前綴} + viewName + {視圖解析器後綴}

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

對應的Controller類

public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//模型和視圖
ModelAndView mv = new ModelAndView();
//業務代碼,假設這裏處理了一個業務,返回的結果為result
String result = "HelloSpringMVC!";
//封裝對象,放在ModelAanView中,Model
mv.addObject("msg",result);
//視圖跳轉封裝要跳轉的視圖,放在ModelAndView中,view
mv.setViewName("hello"); // 自動拼接成:/WEB-INF/jsp/hello.jsp
return mv;
}
}

2.ServletAPI

@Controller
public class ModelTest1 {
@RequestMapping("/m1")
public String test1(HttpServletRequest req, HttpServletResponse resp){
HttpSession session = req.getSession();
System.out.println(session.getId());
return "test";
}
}

3.SpringMVC

不需要視圖解析器

@Controller
public class ModelTest1 {
@RequestMapping("/m1")
public String test1(Model model){
model.addAttribute("msg","ModleTest1");
//轉發,地址欄沒有發生變化
return "/WEB-INF/jsp/test.jsp"; //注意使用全路徑
// 也可寫成這樣 return "forward:/WEB-INF/jsp/test.jsp";
}
}
@Controller
public class ModelTest1 {
@RequestMapping("/m1")
public String test1(Model model){
model.addAttribute("msg","ModelTest1");
//重定向,地址欄會發生變化
return "redirect:/index.jsp";
}
}

有視圖解析器

默認情况下為轉發,在前面加上redirect為重定向

@Controller
public class ModelTest1 {
@RequestMapping("/m1")
public String test1(Model model){
model.addAttribute("msg","ModelTest1");
//轉發
return "test";
}
@RequestMapping("/m2")
public String test2(Model model){
model.addAttribute("msg","ModelTest1");
//重定向
return "redirect:/index.jsp";
}
}

7.SpringMVC數據處理

1.處理提交數據

提交的域名稱和處理方法的參數一致的情况

@Controller
@RequestMapping("/user")
public class UserController {
// http://localhost:8080/user/t1?name=dengzhijiang
@GetMapping("t1")
public String Test(String name, Model model){
//1.接受前端數據
System.out.println("接受前端的數據為:" + name);
//2.將業務處理後的結果返回給前端,Model
model.addAttribute("msg",name);
//3.視圖跳轉
return "test";
}
}

提交的域名稱和處理方法的參數不一致的情况

只需在參數前加上 @RequestParma,建議以後不管一不一樣都加上

@Controller
@RequestMapping("/user")
public class UserController {
// http://localhost:8080/user/t1?name=dengzhijiang
@GetMapping("t1")
public String Test(@RequestParam("username") String name, Model model){
//1.接受前端數據
System.out.println("接受前端的數據為:" + name);
//2.將業務處理後的結果返回給前端,Model
model.addAttribute("msg",name);
//3.視圖跳轉
return "test";
}
}

前端接受的是一個對象

1.接受前端用戶傳遞的參數,判斷參數的名字,假設名字直接在方法上,可以直接使用
2.假設傳遞的是一個對象User,匹配對象User中的字段,如果名字一致則ok,否則匹配不到
3.如果使用對象的話,前端傳遞的參數名,和對象名屬性必須一致,否則就是null
@GetMapping("t2")
public String Test2(User user, Model model){
// http://localhost:8080/user/t2?id=11&name=dengzhijiang&age=22
System.out.println(user);
model.addAttribute("msg",user);
//3.視圖跳轉
return "test";
}

2.數據顯示到前端

第一種:通過ModelAndView

public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//模型和視圖
ModelAndView mv = new ModelAndView();
//業務代碼,假設這裏處理了一個業務,返回的結果為result
String result = "HelloSpringMVC!";
//封裝對象,放在ModelAanView中,Model
mv.addObject("msg",result);
//視圖跳轉封裝要跳轉的視圖,放在ModelAndView中,view
mv.setViewName("hello"); // 自動拼接成:/WEB-INF/jsp/hello.jsp
return mv;
}
}

第二種:通過Model

@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
//在模型中添加 msg 和值,可以在jsp中取出並渲染
model.addAttribute("msg","Hello,SpringMVCAnnotation!");
return "hello"; // hello 會被視圖解析器處理
}
}

第三種:通過ModelMap

3.亂碼問題

1.自定義過濾器處理亂碼

創建一個過濾器

public class EncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setCharacterEncoding("utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() {
}
}

在web.xml中配置過濾器

<filter>
<filter-name>encoding</filter-name>
<filter-class>com.dzj.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2.可以把Post方法改成Get方法
3.配置SpringMVC的亂碼過濾器
<!--2.配置SpringMVC的亂碼過濾器-->
<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>/*</url-pattern>
</filter-mapping>

8.JSON

  • JSON是JavaScript對象的字符串錶示法,它使用文本錶示錶示一個JS對象的信息,本質是一個字符串。
var json = {"name":"鄧志江","age":3,"sex":"男"} //這是一個JSON字符串
var obj = {name: '鄧志江', age: 3, sex: '男'} //這是一個Javas對象
  • JSON 和 JavaScript對象的互轉
//JavaScript對象轉換JSON對象,使用 JSON.stringfy()方法
var json = JSON.stringify(user);
//JSON轉換成JavaScript對象,使用 JSON.parse()方法
var obj = JSON.parse(json);

9.Controller返回JSON數據

1.使用 jackson 方式

1.導入依賴

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>

2.JSON亂碼配置問題

<mvc:annotation-driven>
<mvc:message-converters>
<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.實現對象轉換為 JSON 字符串

//@Controller
@RestController //如果在類上標注了@RestController,就不會走視圖解析器
public class UserController {
@RequestMapping("/j1")
//@ResponseBody //加了這個注解,就不會走仕途解析器,會直接返回一個字符串,配合@Controller使用
public String json1() throws JsonProcessingException {
//jackson裏有一個ObjectMapper對象,可以把user對象轉換成json字符串
ObjectMapper mapper = new ObjectMapper();
User user = new User("鄧志江", 22, "男");
String str = mapper.writeValueAsString(user);// 把user對象轉換為JSON字符串
return str;
}
}

4.實現集合類型轉換為 JSON 字符串

@RequestMapping("/j2")
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List<User> userList = new ArrayList<User>();
User user1 = new User("鄧志江1號", 22, "男");
User user2 = new User("鄧志江2號", 22, "男");
User user3 = new User("鄧志江3號", 22, "男");
User user4 = new User("鄧志江4號", 22, "男");
User user5 = new User("鄧志江5號", 22, "男");
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
userList.add(user5);
String str = mapper.writeValueAsString(userList);// 把user對象轉換為JSON字符串
return str;
}

5.實現日期類型轉換為 JSON 字符串

@RequestMapping("/j3")
public String json3() throws JsonProcessingException {
Date date = new Date();
//把時間按照一定的格式顯示
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//ObjectMapper將時間解析後的格式為:timestamp,時間戳
return new ObjectMapper().writeValueAsString(sdf.format(date));
}

6.源碼思想

方法的重載,方法名相同,根據參數的不同調用不同的方法

public static String getJson(Object object){
return getJson(object,"yyyy-MM-dd HH:mm:ss");
}
public static String getJson(Object object, String dateFormat){
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
//把時間按照一定的格式顯示
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
mapper.setDateFormat(sdf);
try {
String str = mapper.writeValueAsString(object);
return str;
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}

2.使用fastjson方式

1.添加 fastjson 依賴

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

2.直接使用 JSON.toJSONString()實現轉換

@RequestMapping("/j4")
public String json4(){
List<User> userList = new ArrayList<User>();
User user1 = new User("鄧志江1號", 22, "男");
User user2 = new User("鄧志江2號", 22, "男");
User user3 = new User("鄧志江3號", 22, "男");
User user4 = new User("鄧志江4號", 22, "男");
User user5 = new User("鄧志江5號", 22, "男");
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
userList.add(user5);
return JSON.toJSONString(userList); //把集合轉化為JSON字符串
}

10.SpringMVC:Ajax技術

10.1 簡介

10.2 偽造Ajax

1. 新建一個Moudule

新建一個Moudule:springmvc-06-ajax,導入web支持

2. 編寫一個test.html

編寫一個test.html 使用 iframe 測試,感受頁面無刷新效果

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>iframe測試體驗頁面無刷新</title>
<script type=text/javascript>
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" value="https://www.baidu.com/" />
<input type="button" value="提交" onclick="go()"/>
</p>
</div>
<div>
<iframe id="iframe1" style="width: 100%;height: 500px"></iframe>
</div>
</body>
</html>

10.3 實現Ajax

1. 下載並導入jQuery
2. 添加靜態資源過濾

在applicationContext.xml中添加靜態資源過濾

<!--靜態資源過濾-->
<mvc:default-servlet-handler/>
3. 編寫一個前端頁面

實現:當失去焦點的時候,發起一個請求

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<%--引入jQuery--%>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
<script>
function a() {
//通過post方式向後臺發起請求
$.post({
url:"${pageContext.request.contextPath}/a1", //請求地址
data:{"name":$("#username").val()}, //傳遞的數據
success:function (data,status) { //請求之後的回調函數,返回數據,data接受返回的數據
console.log("data="+data);
console.log("status="+status);// status 錶示請求的狀態 200 300 400 500
})
}
</script>
</head>
<body>
<%--失去焦點的時候,發起一個請求--%>
用戶名:<input type="text" id="username" onblur="a()">
</body>
</html>
4. 後臺接受數據返回結果

注意:方法中的參數要和前端ajax中傳遞的參數名一致

data:{"name":$("#username").val()}
@RestController
public class AjaxController {
@RequestMapping("/a1")
public void a1(String name, HttpServletResponse response) throws IOException {
System.out.println("a=>"+name);
if("kuangshen".equals(name)){
response.getWriter().print("true");
}else {
response.getWriter().print("false");
}
}
}

小結:根據Ajax的地址,後臺接收數據,並返回結果,並沒有進行重定向或者轉發的操作,因此就不會刷新頁面,實現了前端頁面的局部更新。

10.4 Ajax异步加載數據

1. 創建一個User類

注意:使用注解的話,記記得添加 lombok 依賴,並且把jar包添加到 lib 目錄中

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private int age;
private String sex;
}
2. 創建前端頁面
body>
<input id="btn" type="button" value="加載數據" />
<table>
<tr>
<td>名稱</td>
<td>年齡</td>
<td>性別</td>
</tr>
<tbody id="content">
</tbody>
</table>
</body>
3. 通過Ajax想後臺發起請求
<%-- 引入 jQuery --%>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
<script>
window.onload=function(){
$("#btn").click(function () {
console.log("成功了沒??");
/*
簡寫的方式:$.post(url, param[可省略] , success)
*/
$.post("${pageContext.request.contextPath}/a2",function (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>
4. 後臺實現數據返回到前端
@RequestMapping("/a2")
public List<User> a2(){
// 創建幾個對象,添加到集合中返回到前端
List<User> userList = new ArrayList<User>();
userList.add(new User("前端",1,"女"));
userList.add(new User("後端",2,"男"));
userList.add(new User("運維",3,"男"));
return userList;
}

小結:前端通過 Ajax 先向後端發起請求,後臺處理請求,並把結果返回到前端,前端把接收到的數據進行處理,顯示到頁面中。

10.5 Ajax驗證用戶信息體驗

1. 創建前端頁面login.jsp
<body>
<p>
用戶名:<input type="text" id="userName" onblur="a1()">
<span id="userId"></span>
</p>
<p>
密碼:<input type="text" id="passWord" onblur="a2()">
<span id="passWordId"></span>
</p>
</body>
2. 通過Ajax想後臺發起請求
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
<script>
function a1() {
$.get({
url:"${pageContext.request.contextPath}/a3",
data:{"name":$("#userName").val()},
success:function (data) {
console.log(data);
if(data.toString()==='ok'){
$("#userId").css("color","green");
}else{
$("#userId").css("color","red");
}
$("#userId").html(data);
}
})
}
function a2() {
$.get({
url:"${pageContext.request.contextPath}/a3",
data:{"password":$("#passWord").val()},
success:function (data) {
console.log(data);
if(data.toString()==='ok'){
$("#passWordId").css("color","green");
}else{
$("#passWordId").css("color","red");
}
$("#passWordId").html(data);
}
})
}
</script>
3. 後臺實現數據返回前端
@RequestMapping("/a3")
public String a3(String name,String password){
String msg = "";
if(name!=null){
if("admin".equals(name)){
msg = "ok";
}else{
msg = "用戶名有誤!";
}
}
if(password!=null){
if("123456".equals(password)){
msg = "ok";
}else{
msg = "密碼有誤!";
}
}
return msg;
}

11.攔截器

11.1 簡單實用攔截器

1.創建一個控制器
@RestController
public class TestController {
@GetMapping("/t1")
public String test1(){
System.out.println("執行成功了");
return "ok";
}
}
  1. 創建一個攔截器
public class MyInterceptor implements HandlerInterceptor {
//return true ,執行下一個攔截器,放行
//return false ,不執行下一個攔截器
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("*************處理前*************");
return false;
}
//下面兩個方法可寫可不寫,主要用於日志返回
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("*************處理後*************");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("*************清理*************");
}
}
3. 配置攔截器
<!--攔截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--包括這個請求下面的所有請求-->
<mvc:mapping path="/**"/>
<bean class="com.dzj.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

11.2 登錄判斷驗證

1. 入口
<body>
<h1>
<a href="${pageContext.request.contextPath}/user/goLogin">登錄頁面</a>
<a href="${pageContext.request.contextPath}/user/main">首頁</a>
</h1>
</body>
2. 登錄頁
<body>
<%-- 在web-inf下面所有的頁面或者資源,只能通過controller或者servlet進行訪問--%>
<h1>登錄頁面</h1>
<form action="${pageContext.request.contextPath}/user/login" method="post">
用戶名:<input type="text" name="username">
密碼:<input type="text" name="password">
<input type="submit" value="提交">
</form>
</body>
3. 首頁
<body>
<h1>首頁</h1>
<span>${username}</span>
<p>
<a href="${pageContext.request.contextPath}/user/goOut">注銷</a>
</p>
</body>
4. 新建控制器
@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("usernameInfo",username);
model.addAttribute("username",username);
return "main";
}
@RequestMapping("/goOut")
public String goOut(HttpSession session){
//移除節點
session.removeAttribute("usernameInfo");
return "main";
}
}
5. 創建攔截器
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
// 放行,判斷什麼情况下登錄
//登錄頁面也會放行
if(request.getRequestURI().contains("goLogin")){
return true;
}
//說明我在提交登錄
if(request.getRequestURI().contains("login")){
return true;
}
//注銷登錄
if(request.getRequestURI().contains("goOut")){
return true;
}
//第一次登錄也是沒有session的
if((session.getAttribute("userLoginInfo")!=null)&&(request.getRequestURI().contains("main"))){
return true;
}
//判斷什麼情况下沒有登陸
request.getRequestDispatcher("/WEB-INF/jsp/Login.jsp").forward(request,response);
return false;
}
}
6. 配置攔截器
<mvc:interceptor>
<!--包括user這個請求下面的所有請求-->
<mvc:mapping path="/user/**"/>
<bean class="com.dzj.config.LoginInterceptor"/>
</mvc:interceptor>

12.SpringMVC:文件上傳和下載

12.1 准備工作

12.2 文件上傳

1. 導入文件上傳的jar包

導入文件上傳的jar包,commons-fileupload,Maven會自動幫我們導入他的依賴包commons-io

<!-- 文件上傳-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!-- servlet-api導入高版本的 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
2. 配置bean:multipartResolver

注意:這個 bean 的 id 必須為:multipartResolver,否則上傳文件會報404的錯誤!

<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 請求的編碼格式,必須和jSP的pageEncoding屬性一致,以便正確讀取錶單的內容,默認為ISO-8859-1 -->
<property name="defaultEncoding" value="UTF-8"/>
<!-- 上傳文件大小上限,單比特為字節(10MB) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
3. 編寫前端頁面
<body>
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload"/>
</form>
<a href="${pageContext.request.contextPath}/statics/1.png">下載圖片</a>
</body>

四、創建後臺控制器

@RestController
public class FileController {
//@RequestParam("file") 將name=file控件得到的文件封裝成ConmmonsMultipartFile對象
//批量上傳CommonsMultipartFile則為數組即可
/*
采用file.Transto 來保存上傳的文件
*/
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file")CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//上傳保存路徑設置
String path = request.getServletContext().getRealPath("/upload");
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";
}
}

12.3 文件下載

文件下載的步驟:

  • 設置 response 響應頭
  • 讀取文件 -- InputStream
  • 寫出文件 -- OutputStream
  • 執行操作
  • 關閉流(先開後關)
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response,HttpServletRequest request) throws Exception {
//要下載的圖片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "1.png";
//1.設置response相應頭
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);
//2.讀取文件--輸入流
InputStream input = new FileInputStream(file);
//3.寫出文件--輸出流
OutputStream out = response.getOutputStream();
byte[] buff = new byte[1024];
int index = 0;
//4.執行 寫出操作
while((index = input.read(buff))!=-1){
out.write(buff,0,index);
out.flush();
}
out.close();
input.close();
return null;
}
直接前端這樣也行
<a href="${pageContext.request.contextPath}/statics/1.png">下載圖片</a>
版权声明:本文为[小公羊]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/09/20210920000719954u.html