SpringMVC
本文學自b站狂神:B站狂神–SpringMVC篇
參考文檔
一、概述
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的特點:
- 輕量級,簡單易學
- 高效 , 基於請求響應的MVC框架
- 與Spring兼容性好,無縫結合
- 約定優於配置
- 功能強大:RESTful、數據驗證、格式化、本地化、主題等
- 簡潔靈活
Spring的web框架圍繞DispatcherServlet [ 調度Servlet ] 設計。
DispatcherServlet的作用是將請求分發到不同的處理器。從Spring 2.5開始,使用Java 5或者以上版本的用戶可以採用基於註解形式進行開發,十分簡潔;
正因爲SpringMVC好 , 簡單 , 便捷 , 易學 , 天生和Spring無縫集成(使用SpringIoC和Aop) , 使用約定優於配置 . 能夠進行簡單的junit測試 . 支持Restful風格 .異常處理 , 本地化 , 國際化 , 數據驗證 , 類型轉換 , 攔截器 等等…所以我們要學習 .
最重要的一點還是用的人多 , 使用的公司多 .
二、第一個SpringMVC項目
2.1新建一個父項目:20200531-MySpringMVC,將src目錄刪除
在父項目中導入maven依賴:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.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>
2.2、新建一個Moudle,springmvc-02-hello-annotation 。添加web支持!
2.3配置文件:
- 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">
<!--配置DispatchServlet:這個是springMVC的核心:請求分發器,前端控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--DispathcServlet要綁定Spring的配置文件-->
<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>
<!--
攔截映射
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- spring-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">
<!--處理器映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--處理器適配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--視圖解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前綴-->
<property name="prefix" value="/WEB-INF/jsp/" />
<!--後綴-->
<property name="suffix" value=".jsp" />
</bean>
<bean id="/hello" class="com.lxf.controller.HelloController"/>
</beans>
2.4測試
- 新建一個com.lxf.controller包,包下new一個HelloController類:
package com.lxf.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv=new ModelAndView();
//業務代碼
String result="HelloSpringMVC";
mv.addObject("msg",result);
//視圖跳轉
mv.setViewName("test");
return mv;
}
}
- WEB-INF下新建一個jsp包,包下new一個test.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
2.5錯誤總結
- 查看控制檯輸出,看一下是不是缺少了什麼jar包。
- 如果jar包存在,顯示無法輸出,就在IDEA的項目發佈中,添加lib依賴!
- File–>Project Structure–>Artifacts–>
- 點擊本項目–>在WEB-INF下建一個lib文件夾–>點擊WEB-INF上的+號
- 點擊Library Files,將Project Libraries下的jar全部選中,點擊OK就好了
- 重啓Tomcat 即可解決!
三、註解開發SpringMVC
3.1、新建一個Moudle,springmvc-03-hello-annotation 。添加web支持!
3.2、由於Maven可能存在資源過濾的問題,我們將03的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>
3.3、在pom.xml文件引入相關的依賴:主要有Spring框架核心庫、Spring MVC、servlet , JSTL等。我們在父依賴中已經引入了!
3.4、配置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">
<!--1.註冊servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通過初始化參數指定SpringMVC配置文件的位置,進行關聯-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 啓動順序,數字越小,啓動越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有請求都會被springmvc攔截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--配置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>
</web-app>
注意:
/ 和 /* 的區別:< url-pattern > / </ url-pattern > 不會匹配到.jsp, 只針對我們編寫的請求;即:.jsp 不會進入spring的 DispatcherServlet類 。< url-pattern > /* </ url-pattern > 會匹配 *.jsp,會出現返回 jsp視圖 時再次進入spring的DispatcherServlet 類,導致找不到對應的controller所以報404錯。
- 注意web.xml版本問題,要最新版!
- 註冊DispatcherServlet
- 關聯SpringMVC的配置文件
- 啓動級別爲1
- 映射路徑爲 / 【不要用/*,會404】
3.5、添加Spring MVC配置文件
在resource目錄下添加springmvc-servlet.xml配置文件,配置的形式與Spring容器配置基本類似,爲了支持基於註解的IOC,設置了自動掃描包的功能,具體配置信息如下:
<?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.lxf.controller"/>
<!--
讓Spring MVC不處理靜態資源
靜態資源過濾 :HTML . JS . CSS . 圖片 , 視頻 .....
-->
<mvc:default-servlet-handler/>
<!--
支持mvc註解驅動
在spring中一般採用@RequestMapping註解來完成映射關係
要想使@RequestMapping註解生效
必須向上下文中註冊DefaultAnnotationHandlerMapping
和一個AnnotationMethodHandlerAdapter實例
這兩個實例分別在類級別和方法級別處理。
而annotation-driven配置幫助我們自動完成上述兩個實例的注入。
-->
<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>
**注意:**在視圖解析器中我們把所有的視圖都存放在/WEB-INF/目錄下,這樣可以保證視圖安全,因爲這個目錄下的文件,客戶端不能直接訪問。
3.6、創建Controller
-
package com.lxf.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { @RequestMapping("/hello") public String sayHello(Model model){ //向模型中添加msg與值可以在JSP頁面中取出並渲染 model.addAttribute("msg","hello,SpringMVC"); return "hello"; } }
- @Controller是爲了讓Spring IOC容器初始化時自動掃描到;
- @RequestMapping是爲了映射請求路徑,這裏因爲類與方法上都有映射所以訪問時應該是/HelloController/hello;
- 方法中聲明Model類型的參數是爲了把Action中的數據帶到視圖中;
- 方法返回的結果是視圖的名稱hello,加上配置文件中的前後綴變成WEB-INF/jsp/hello.jsp。
3.7、創建視圖層
在WEB-INF/ jsp目錄中創建hello.jsp , 視圖可以直接取出並展示從Controller帶回的信息;
可以通過EL表示取出Model中存放的值,或者對象;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
3.8、配置Tomcat運行
配置Tomcat , 開啓服務器 , 訪問 對應的請求路徑!
3.9、小結
實現步驟:
- 新建一個web項目
- 導入相關jar包
- 編寫web.xml , 註冊DispatcherServlet
- 編寫springmvc配置文件
- 接下來就是去創建對應的控制類 , controller
- 最後完善前端視圖和controller之間的對應
- 測試運行調試.
使用springMVC必須配置的三大件:
處理器映射器、處理器適配器、視圖解析器
通常,我們只需要手動配置視圖解析器,而處理器映射器和處理器適配器只需要開啓註解驅動即可,而省去了大段的xml配置
四、原理
- 原理圖
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-994HN839-1591961903052)(E:\typoraPic\640)]
-
步驟:
(1).DispatherServlet表示前置控制器,是整個SpringMVC的控制中心。用戶發出請求。DispatherServlet接收請求並攔截請求。
- 我們假設請求的url爲:http://localhost:8080/SpringMVC/hello
- 如上url拆分成三部分:
- http://localhost:8080服務器域名
- SpringMVC部署在服務器上的web站點
- hello表示控制器
- 通過分析,如上url表示爲:請求位於服務器localhost:8080上的SpringMVC站點的hello控制器。
(2).HandlerMappering爲處理器映射。DispatherServlet調用HandlerMappering,HandlerMapping根據請求url查找Handler.
(3).HandlerExecution表示具體的Handler,其主要作用是根據url查找控制器,如上url被查找的控制器爲:hello.
(4).HandlerExecution將解析後的信息傳遞給DispatherServlet.如:解析控制器映射等等。
(5).HandlerAdapter表示處理器適配器,其按照特定的規則去執行Handler。
(6).Handler讓具體的Controller執行
五、註解詳細解釋
5.1註冊類
@Controller--Contoller層(RestController--用於json傳輸)
@Service--Service層
@Repository--dao層
@Component--其它層,如:pojo(entity)等
//目前來說這四個除了名字不一樣,效果是沒有區別的,可以通用
5.2控制器映射
@RequestMapping("/t1")//get和post方式,默認方式
@GetMapping("/t2")//get方式==(@RequestMapping("/t1"),RequestMethod.get)
@PostMapping("/t3")//post方式==(@RequestMapping("/t1"),RequestMethod.post)
@DeleteMapping("t4")//delete方式
@PutMapping("t5")//put方式
@PatchMapping("t6")//patch方式
@TypeMapping("t7")//type方式
//加在方法上直接訪問時/t*就可以了
//還可以同時在類寫那麼就是類上的+方法上的/t*/t*
5.3約束性註解
@ResponseBody//不會走視圖解析器,加在類上,一般處理json數據時使用
六、RestFul風格
@RequestMapping(value="/add/{a}/{b}")
//方法參數a,b是前端傳來的
//model是存儲數據和視圖的對象
//return的hello字符串會拼接訪問:WEB-INF/jsp/hello.jsp
public String test1(@PathVariable int a ,@PathVariable int b, Model model){
int res=a+b;
model.addAttribute("msg","結果爲"+res);
return "hello";
}
//注意:a不等於a,他的參數按順序賦值的,與你的方法參數名字無關
特點:
- 簡潔
- 高效
- 安全
七、重定向與轉發
7.1、方法一
//ServletAPI
//通過設置ServletAPI , 不需要視圖解析器 .
//1、通過HttpServletResponse進行輸出
//2、通過HttpServletResponse實現重定向
//3、通過HttpServletResponse實現轉發
@Controller
public class ResultGo {
@RequestMapping("/result/t1")
public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.getWriter().println("Hello,Spring BY servlet API");
}
@RequestMapping("/result/t2")
public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.sendRedirect("/index.jsp");
}
@RequestMapping("/result/t3")
public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
//轉發
req.setAttribute("msg","/result/t3");
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
}
}
7.2、方法二
//SpringMVC
//通過SpringMVC來實現轉發和重定向 - 無需視圖解析器;
//測試前,需要將視圖解析器註釋掉
@Controller
public class ResultSpringMVC {
@RequestMapping("/rsm/t1")
public String test1(){
//轉發
return "/index.jsp";
}
@RequestMapping("/rf/t2")
public String test2(){
//轉發二
return "forward:/index.jsp";
}
@RequestMapping("/rf/t3")
public String test3(){
//重定向
return "redirect:/index.jsp";
}
}
7.3、方法三
//通過SpringMVC來實現轉發和重定向 - 有視圖解析器;
//重定向 , 不需要視圖解析器 , 本質就是重新請求一個新地方嘛 , 所以注意路徑問題.
//可以重定向到另外一個請求實現 .
@Controller
public class ResultSpringMVC2 {
@RequestMapping("/rf/t1")
public String test1(){
//轉發
return "test";
}
@RequestMapping("/rf/t2")
public String test2(){
//重定向
return "redirect:/index.jsp";
//return "redirect:hello.do"; //hello.do爲另一個請求/
}
}
八、數據處理
8.1、獲取前端參數
8.1.1提交的域名稱和處理方法的參數名一致
提交數據 : http://localhost:8080/springmvc_03_hello_annotation_war_exploded/t1/name=lxf
@GetMapping("/t1")
public String test1(String name, Model model){
//1.接收前端參數
System.out.println("接收到前端的參數爲:"+name);
//2.將返回的結果傳遞給前端
model.addAttribute("msg",name);
//3.視圖跳轉
return "hello";
}
8.1.2提交的域名稱和處理方法的參數名不一致
提交數據 : http://localhost:8080/springmvc_03_hello_annotation_war_exploded/t1/username=lxf
@GetMapping("/t1")
public String test2(@RequestParam("username") String name, Model model){
//1.接收前端參數
System.out.println("接收到前端的參數爲:"+name);
//2.將返回的結果傳遞給前端
model.addAttribute("msg",name);
//3.視圖跳轉
return "hello";
}
8.1.3、提交的是一個對象
1、實體類:
package com.lxf.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private int age;
}
2、提交數據 : http://localhost:8080/springmvc_03_hello_annotation_war_exploded/t2/id=1&name=lxf&age=20
3、處理方法:
//前端接收的是一個對象:id,name,age
@GetMapping("/t2")
public String test2(User user){
System.out.println(user);
return "hello";
}
8.2、數據顯示到前端
8.2.1、 通過ModelAndView
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一個模型視圖對象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;
}
}
8.2.2、通過ModelMap
ModelMap
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
//封裝要顯示到視圖中的數據
//相當於req.setAttribute("name",name);
model.addAttribute("name",name);
System.out.println(name);
return "hello";
}
8.2.3、通過Model
Model
@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
//封裝要顯示到視圖中的數據
//相當於req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "test";
}
各種數據存儲對象的區別:
Model 精簡版(大部分情況下使用);
ModelMap 繼承了 LinkedMap ,除了實現了自身的一些方法,同樣的繼承 LinkedMap 的方法和特性;
ModelAndView 可以在儲存數據的同時,可以進行設置返回的邏輯視圖,進行控制展示層的跳轉。
//當然也有性能和優化的區別。
九、亂碼問題解決方法
測試步驟:
1、我們可以在WEB_INF下編寫一個提交的表單(form.jsp):
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/springmvc_03_hello_annotation_war_exploded/e/t1" method="post">
<input type="text" name="name" >
<input type="submit">
</form>
</body>
</html>
2、後臺編寫對應的處理類
package com.lxf.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class EncodingTest {
@PostMapping("/e/t1")
public String TestEncode(String name, Model model){
model.addAttribute("msg",name);
return "hello";
}
}
3、輸入中文測試,看是否出現亂碼
9.1、解決方法一
1.檢查idea的編碼設置
2.檢查tomcat編碼配置
3.將web.xml中的/改成/*
9.1、解決方法二
在web.xml下加上以下代碼:
<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>
但是在有些極端情況下.這個過濾器對get的支持不好 .
9.3、解決方法三
1、修改tomcat配置文件 :設置編碼!
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
2、自定義過濾器
package com.lxf.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* 解決get和post請求 全部亂碼的過濾器
*/
public class GenericEncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//處理response的字符編碼
HttpServletResponse myResponse=(HttpServletResponse) response;
myResponse.setContentType("text/html;charset=UTF-8");
// 轉型爲與協議相關對象
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 對request包裝增強
HttpServletRequest myrequest = new MyRequest(httpServletRequest);
chain.doFilter(myrequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
//自定義request對象,HttpServletRequest的包裝類
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
//是否編碼的標記
private boolean hasEncode;
//定義一個可以傳入HttpServletRequest對象的構造函數,以便對其進行裝飾
public MyRequest(HttpServletRequest request) {
super(request);// super必須寫
this.request = request;
}
// 對需要增強方法 進行覆蓋
@Override
public Map getParameterMap() {
// 先獲得請求方式
String method = request.getMethod();
if (method.equalsIgnoreCase("post")) {
// post請求
try {
// 處理post亂碼
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if (method.equalsIgnoreCase("get")) {
// get請求
Map<String, String[]> parameterMap = request.getParameterMap();
if (!hasEncode) { // 確保get手動編碼邏輯只運行一次
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
// 處理get亂碼
values[i] = new String(values[i]
.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
return parameterMap;
}
return super.getParameterMap();
}
//取一個值
@Override
public String getParameter(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0]; // 取回參數的第一個值
}
//取所有值
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}
這是網上的一些大神寫的,一般情況下,SpringMVC默認的亂碼處理就已經能夠很好的解決了!
然後在web.xml中配置這個過濾器即可!
亂碼問題,需要平時多注意,在儘可能能設置編碼的地方,都設置爲統一編碼 UTF-8!
還有種可能是瀏覽器的編碼格式的原因,哈哈哈
十、Jackson的使用
10.1、導入Jackson依賴:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<!--Jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
10.2、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
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.lxf.controller"/>
<!--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>
<!--
單獨解決一個類的亂碼問題,在此類上加上:
@RequestMapping(value="/j1",produces = "application/json;charset=utf-8")
-->
<!-- 讓Spring MVC不處理靜態資源 -->
<mvc:default-servlet-handler/>
<!--
支持mvc註解驅動
在spring中一般採用@RequestMapping註解來完成映射關係
要想使@RequestMapping註解生效
必須向上下文中註冊DefaultAnnotationHandlerMapping
和一個AnnotationMethodHandlerAdapter實例
這兩個實例分別在類級別和方法級別處理。
而annotation-driven配置幫助我們自動完成上述兩個實例的注入。
-->
<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>
10.3、測試
package com.lxf.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lxf.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class JacksonTest {
@RequestMapping(value="/j1",produces = "application/json;charset=utf-8")
@ResponseBody//不會走視圖解析器
public String json1() throws JsonProcessingException {
//jackon
ObjectMapper mapper=new ObjectMapper();
//創建一個對象
User user=new User(3,"劉一手",20);
String str=mapper.writeValueAsString(user);
return str;
}
}
另一種直接將整個類返回不走視圖解析器,在此類上加上@RestController
十一、攔截器
applicationContext.xml:
<!--攔截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--包括這個路徑下面的所有的請求-->
<mvc:mapping path="/**"/>
<bean class="com.lxf.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
執行攔截的類:
package com.lxf.config;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
//return true:執行下一個攔截器,放行
//return false:不執行下一個攔截器
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("================處理前====================");
return true;
}
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("===================清理====================");
}
}
十二、文件的上傳與下載
準備:
- 電腦有E盤
- 在E盤下新建一個downLoad文件夾,並在這文件夾下加一張圖片:1.png(注意大下,spring-mvc.xml文件配置中有限制)
spring-mvc.xml文件:
<!--注意!!!這個bean的id必須爲:multipartResolver , 否則上傳文件會報400的錯誤!-->
<!--文件上傳配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 請求的編碼格式,必須和jSP的pageEncoding屬性一致,以便正確讀取表單的內容,默認爲ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上傳文件大小上限,單位爲字節(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
前端頁面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file1"/>
<input type="submit" value="上傳文件">
</form>
<a href="${pageContext.request.contextPath}/download">下載文件</a>
</body>
</html>
文件上傳方式一:
/**
* 方式一
* @param file
* @param request
* @return
* @throws IOException
*/
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file1") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
//獲取文件名 : file.getOriginalFilename();
String uploadFileName = file.getOriginalFilename();
//如果文件名爲空,直接回到首頁!
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上傳文件名 : "+uploadFileName);
//上傳路徑保存設置
String path = "E:\\uploadTest";
//如果路徑不存在,創建一個
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上傳文件保存地址:"+path);
InputStream is = file.getInputStream(); //文件輸入流
OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件輸出流
//讀取寫出
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
文件上傳方式二:
/**
* 方式二
* 採用file.Transto 來保存上傳的文件
* @param file
* @param request
* @return
* @throws IOException
*/
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//上傳路徑保存設置
String path = "E:\\uploadTest";
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";
}
下載文件:
/**
* 下載文件
* @param response
* @param request
* @return
* @throws Exception
*/
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//要下載的圖片地址
String path = "E:\\downLoad\\";
String fileName="1.png";
File file=new File(path+fileName);
//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"));
//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;
}