日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Java学习笔记13-1——SpringMVC

發(fā)布時(shí)間:2023/12/10 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java学习笔记13-1——SpringMVC 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 1.什么是MVC
    • 回顧Servlet
  • 2.什么是SpringMVC
    • 概述
    • 中心控制器
    • SpringMVC執(zhí)行原理
  • 3.第一個(gè)SpringMVC 程序
    • 使用XML配置實(shí)現(xiàn)
    • 使用注解實(shí)現(xiàn)
  • 4.控制器和RestFul風(fēng)格
    • 控制器Controller
      • 實(shí)現(xiàn)Controller接口
      • 使用注解@Controller
      • RequestMapping
    • RestFul 風(fēng)格
    • 擴(kuò)展:小黃鴨調(diào)試法
  • 5.結(jié)果跳轉(zhuǎn)方式
    • ModelAndView
    • ServletAPI
    • SpringMVC
  • 6.數(shù)據(jù)處理
    • 處理提交數(shù)據(jù)
      • 參數(shù)名一致
      • 參數(shù)名不一致
      • 提交的是一個(gè)對(duì)象
    • 數(shù)據(jù)顯示到前端
      • 第一種 : 通過(guò)ModelAndView
      • 第二種 : 通過(guò)ModelMap
      • 第三種 : 通過(guò)Model
      • 對(duì)比
  • 7.亂碼問(wèn)題
  • 8.JSON交互處理
    • 什么是JSON?
    • JSON解析工具Jackson的使用
    • JSON亂碼問(wèn)題
    • 輸出JSON集合
    • 輸出時(shí)間對(duì)象
      • 抽取為工具類
    • JSON解析工具FastJson的使用
  • 9.AJAX
    • 簡(jiǎn)介
    • 偽造Ajax
    • jQuery.ajax
  • 10.攔截器
  • 11.文件上傳和下載

1.什么是MVC

  • MVC是模型(Model)、視圖(View)、控制器(Controller)的簡(jiǎn)寫,是一種軟件設(shè)計(jì)規(guī)范。是將業(yè)務(wù)邏輯、數(shù)據(jù)、顯示分離的方法來(lái)組織代碼。
  • MVC主要作用是降低了視圖與業(yè)務(wù)邏輯間的雙向偶合。
  • MVC不是一種設(shè)計(jì)模式,MVC是一種架構(gòu)模式。當(dāng)然不同的MVC存在差異。

Model(模型):數(shù)據(jù)模型,提供要展示的數(shù)據(jù),因此包含數(shù)據(jù)和行為,可以認(rèn)為是領(lǐng)域模型或JavaBean組件(包含數(shù)據(jù)和行為),不過(guò)現(xiàn)在一般都分離開(kāi)來(lái):Value Object(數(shù)據(jù)Dao) 和 服務(wù)層(行為Service)。也就是模型提供了模型數(shù)據(jù)查詢和模型數(shù)據(jù)的狀態(tài)更新等功能,包括數(shù)據(jù)和業(yè)務(wù)。

View(視圖):負(fù)責(zé)進(jìn)行模型的展示,一般就是我們見(jiàn)到的用戶界面,客戶想看到的東西。

Controller(控制器):接收用戶請(qǐng)求,委托給模型進(jìn)行處理(狀態(tài)改變),處理完畢后把返回的模型數(shù)據(jù)返回給視圖,由視圖負(fù)責(zé)展示。也就是說(shuō)控制器做了個(gè)調(diào)度員的工作。

最典型的MVC就是JSP + Servlet + Java Bean的模式

職責(zé)分析:

Controller:控制器

  • 取得表單數(shù)據(jù)
  • 調(diào)用業(yè)務(wù)邏輯
  • 轉(zhuǎn)向指定的頁(yè)面

Model:模型

  • 業(yè)務(wù)邏輯
  • 保存數(shù)據(jù)的狀態(tài)

View:視圖

  • 顯示頁(yè)面

回顧Servlet

1、新建一個(gè)Maven工程當(dāng)做父工程,導(dǎo)入依賴

<dependencies><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> </dependencies>

2、編寫一個(gè)Servlet類,用來(lái)處理用戶的請(qǐng)求

//實(shí)現(xiàn)Servlet接口 public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//取得參數(shù)String method = req.getParameter("method");if (method.equals("add")){req.getSession().setAttribute("msg","執(zhí)行了add方法");}if (method.equals("delete")){req.getSession().setAttribute("msg","執(zhí)行了delete方法");}//業(yè)務(wù)邏輯//視圖跳轉(zhuǎn)req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);} }

3、編寫Hello.jsp,在WEB-INF目錄下新建一個(gè)jsp的文件夾,新建hello.jsp

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

4、在web.xml中注冊(cè)Servlet

<?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>HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>HelloServlet</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping> </web-app>

5、配置Tomcat,并啟動(dòng)測(cè)試
localhost:8080/user?method=add
localhost:8080/user?method=delete

MVC框架要做哪些事情

  • 將url映射到j(luò)ava類或java類的方法
  • 封裝用戶提交的數(shù)據(jù)
  • 處理請(qǐng)求–調(diào)用相關(guān)的業(yè)務(wù)處理–封裝響應(yīng)數(shù)據(jù)
  • 將響應(yīng)的數(shù)據(jù)進(jìn)行渲染 . jsp / html 等表示層數(shù)據(jù)

說(shuō)明:

? 常見(jiàn)的服務(wù)器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF;常見(jiàn)前端MVC框架:vue、angularjs、react、backbone;由MVC演化出了另外一些模式如:MVP、MVVM 等等…

2.什么是SpringMVC

概述

Spring MVC是Spring Framework的一部分,是基于Java實(shí)現(xiàn)MVC的輕量級(jí)Web框架。

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

我們?yōu)槭裁匆獙W(xué)習(xí)SpringMVC呢?

Spring MVC的特點(diǎn):

  • 輕量級(jí),簡(jiǎn)單易學(xué)
  • 高效 , 基于請(qǐng)求響應(yīng)的MVC框架
  • 與Spring兼容性好,無(wú)縫結(jié)合
  • 約定優(yōu)于配置
  • 功能強(qiáng)大:RESTful、數(shù)據(jù)驗(yàn)證、格式化、本地化、主題等
  • 簡(jiǎn)潔靈活

Spring的web框架圍繞DispatcherServlet [ 調(diào)度Servlet ] 設(shè)計(jì)。

DispatcherServlet的作用是將請(qǐng)求分發(fā)到不同的處理器。從Spring 2.5開(kāi)始,使用Java 5或者以上版本的用戶可以采用基于注解形式進(jìn)行開(kāi)發(fā),十分簡(jiǎn)潔;

正因?yàn)镾pringMVC好,簡(jiǎn)單,便捷,易學(xué),天生和Spring無(wú)縫集成(使用SpringIoC和AOP),使用約定優(yōu)于配置。能夠進(jìn)行簡(jiǎn)單的junit測(cè)試。支持Restful風(fēng)格。異常處理,本地化,國(guó)際化,數(shù)據(jù)驗(yàn)證,類型轉(zhuǎn)換,攔截器等等,所以我們要學(xué)習(xí)。

最重要的一點(diǎn)還是用的人多,使用的公司多。

中心控制器

Spring的web框架圍繞DispatcherServlet設(shè)計(jì)。DispatcherServlet的作用是將請(qǐng)求分發(fā)到不同的處理器。

DispatcherServlet一級(jí)一級(jí)繼承,最終繼承的是Servlet,所以DispatcherServlet本質(zhì)也是在處理一些響應(yīng)和請(qǐng)求。如下圖所示,這樣多加一層的架構(gòu)好處是不用針對(duì)單個(gè)Servlet一個(gè)個(gè)去配置,現(xiàn)在可以統(tǒng)一配置并順帶管理。

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

SpringMVC的原理如下圖所示:

當(dāng)發(fā)起請(qǐng)求時(shí)被前置的控制器攔截到請(qǐng)求,根據(jù)請(qǐng)求參數(shù)生成代理請(qǐng)求,找到請(qǐng)求對(duì)應(yīng)的實(shí)際控制器,控制器處理請(qǐng)求,創(chuàng)建數(shù)據(jù)模型,訪問(wèn)數(shù)據(jù)庫(kù),將模型響應(yīng)給中心控制器,控制器使用模型與視圖渲染視圖結(jié)果,將結(jié)果返回給中心控制器,再將結(jié)果返回給請(qǐng)求者。

SpringMVC執(zhí)行原理


圖為SpringMVC的一個(gè)較完整的流程圖,實(shí)線表示SpringMVC框架提供的技術(shù),不需要開(kāi)發(fā)者實(shí)現(xiàn),虛線表示需要開(kāi)發(fā)者實(shí)現(xiàn)。

簡(jiǎn)要分析執(zhí)行流程

1、DispatcherServlet表示前置控制器,是整個(gè)SpringMVC的控制中心。用戶發(fā)出請(qǐng)求,

  • DispatcherServlet接收請(qǐng)求并攔截請(qǐng)求。
  • 我們假設(shè)請(qǐng)求的url為 : http://localhost:8080/SpringMVC/hello
  • 如上url拆分成三部分:
  • http://localhost:8080 ------> 服務(wù)器域名
  • SpringMVC ------> 部署在服務(wù)器上的web站點(diǎn)
  • hello ------> 表示控制器
  • 通過(guò)分析,如上url表示為:請(qǐng)求位于服務(wù)器localhost:8080上的SpringMVC站點(diǎn)的hello控制器。

2、HandlerMapping為處理器映射。DispatcherServlet調(diào)用HandlerMapping,HandlerMapping根據(jù)請(qǐng)求url查找Handler。
3、HandlerExecution表示具體的Handler,其主要作用是根據(jù)url查找控制器,如上url被查找控制器為:hello。
4、HandlerExecution將解析后的信息傳遞給DispatcherServlet,如解析控制器映射等。
5、HandlerAdapter表示處理器適配器,其按照特定的規(guī)則去執(zhí)行Handler。
6、Handler讓具體的Controller執(zhí)行。
7、Controller將具體的執(zhí)行信息返回給HandlerAdapter,如ModelAndView。
8、HandlerAdapter將視圖邏輯名或模型傳遞給DispatcherServlet。
9、DispatcherServlet調(diào)用視圖解析器(ViewResolver)來(lái)解析HandlerAdapter傳遞的邏輯視圖名。
10、視圖解析器將解析的邏輯視圖名傳給DispatcherServlet。
11、DispatcherServlet根據(jù)視圖解析器解析的視圖結(jié)果,調(diào)用具體的視圖。
12、最終視圖呈現(xiàn)給用戶。

3.第一個(gè)SpringMVC 程序

使用XML配置實(shí)現(xiàn)

1、新建一個(gè)子Moudle,springmvc-02-hello,添加web的支持

2、確定導(dǎo)入了SpringMVC 的依賴

3、配置web.xml,注冊(cè)DispatcherServlet

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!--注冊(cè)DispatcherServlet--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--關(guān)聯(lián)一個(gè)springmvc的配置文件:【servlet-name】-servlet.xml--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!--啟動(dòng)級(jí)別-1--><load-on-startup>1</load-on-startup></servlet><!-- / 為匹配所有的請(qǐng)求(不包括.jsp)--><!-- /* 為匹配所有的請(qǐng)求(包括.jsp)--><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>

4、編寫SpringMVC 的 配置文件!名稱:springmvc-servlet.xml : [servletname]-servlet.xml

說(shuō)明,這里的名稱要求是按照官方來(lái)的

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--添加處理映射器--><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/><!--添加處理器適配器--><bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/><!--視圖解析器:DispatcherServlet給他的ModelAndView--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"><!--前綴--><property name="prefix" value="/WEB-INF/jsp/"/><!--后綴--><property name="suffix" value=".jsp"/></bean><!--對(duì)寫好的類注冊(cè)bean--><bean id="/hello" class="com.cheng.controller.HelloController"/></beans>

5、編寫我們要操作業(yè)務(wù)Controller,要么實(shí)現(xiàn)Controller接口,要么增加注解;需要返回一個(gè)ModelAndView,裝數(shù)據(jù),封視圖

import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;//注意:這里我們先導(dǎo)入Controller接口 public class HelloController implements Controller {public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {//ModelAndView 模型和視圖ModelAndView mv = new ModelAndView();//封裝對(duì)象,放在ModelAndView中。Modelmv.addObject("msg","HelloSpringMVC!");//封裝要跳轉(zhuǎn)的視圖,放在ModelAndView中mv.setViewName("hello"); // 最終會(huì)被拼接成/WEB-INF/jsp/hello.jspreturn mv;} }

6、將自己的類交給SpringIOC容器,注冊(cè)bean

<!--對(duì)寫好的類注冊(cè)bean--><bean id="/hello" class="com.cheng.controller.HelloController"/>

7、寫要跳轉(zhuǎn)的jsp頁(yè)面,顯示ModelandView存放的數(shù)據(jù),以及我們的正常頁(yè)面

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

8、配置Tomcat,啟動(dòng)測(cè)試

可能遇到的問(wèn)題:訪問(wèn)出現(xiàn)404,排查步驟:

  • 查看控制臺(tái)輸出,看一下是不是缺少了什么jar包。

  • 如果jar包存在,顯示無(wú)法輸出,就在IDEA的項(xiàng)目發(fā)布中,添加lib依賴!

  • 重啟Tomcat 即可解決

我們來(lái)看個(gè)注解版實(shí)現(xiàn),這才是SpringMVC的精髓。

使用注解實(shí)現(xiàn)

1、新建一個(gè)Moudle,springmvc-03-annotation 。添加web支持

2、由于Maven可能存在資源過(guò)濾的問(wèn)題,我們將配置完善

<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、在pom.xml文件引入相關(guān)的依賴:主要有Spring框架核心庫(kù)、Spring MVC、servlet , JSTL等。我們?cè)诟敢蕾囍幸呀?jīng)引入了!

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"><!--注冊(cè)servlet--><servlet><servlet-name>SpringMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--初始化Spring配置文件的位置--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!--啟動(dòng)順序,數(shù)字越小,啟動(dòng)越早--><load-on-startup>1</load-on-startup></servlet><!--所有的請(qǐng)求都會(huì)被SpringMVC攔截--><servlet-mapping><servlet-name>SpringMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping> </web-app> <!--這是使用注解開(kāi)發(fā)時(shí)固定的配置-->

注意 / /* 的區(qū)別:

< url-pattern > / </ url-pattern > 不會(huì)匹配到.jsp, 只針對(duì)我們編寫的請(qǐng)求;即:.jsp 不會(huì)進(jìn)入spring的 DispatcherServlet類 。

< url-pattern > /* </ url-pattern > 會(huì)匹配 *.jsp,會(huì)出現(xiàn)返回 jsp視圖 時(shí)再次進(jìn)入spring的DispatcherServlet 類,導(dǎo)致找不到對(duì)應(yīng)的controller所以報(bào)404錯(cuò)。

  • 注意web.xml版本問(wèn)題,要最新版!4.0
  • 注冊(cè)DispatcherServlet
  • 關(guān)聯(lián)SpringMVC的配置文件
  • 啟動(dòng)級(jí)別為1
  • 映射路徑為 / 【不要用/*,會(huì)404】

5、添加SpringMVC配置文件

在resource目錄下添加springmvc-servlet.xml配置文件,配置的形式與Spring容器配置基本類似,為了支持基于注解的IOC,設(shè)置了自動(dòng)掃描包的功能,具體配置信息如下:

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 自動(dòng)掃描包,讓指定包下的注解生效,由IOC容器統(tǒng)一管理 --><context:component-scan base-package="com.cheng.controller"/><!-- 讓Spring MVC不處理靜態(tài)資源 --><mvc:default-servlet-handler /><!--支持mvc注解驅(qū)動(dòng)在spring中一般采用@RequestMapping注解來(lái)完成映射關(guān)系要想使@RequestMapping注解生效必須向上下文中注冊(cè)DefaultAnnotationHandlerMapping和一個(gè)AnnotationMethodHandlerAdapter實(shí)例這兩個(gè)實(shí)例分別在類級(jí)別和方法級(jí)別處理。而annotation-driven配置幫助我們自動(dòng)完成上述兩個(gè)實(shí)例的注入。--><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> <!--這也是固定配置,需要修改的只有需要注入IOC的包-->

在視圖解析器中我們把所有的視圖都存放在/WEB-INF/目錄下,這樣可以保證視圖安全,因?yàn)檫@個(gè)目錄下的文件,客戶端不能直接訪問(wèn)。

  • 讓IOC的注解生效
  • 靜態(tài)資源過(guò)濾 :HTML . JS . CSS . 圖片 , 視頻 …
  • MVC的注解驅(qū)動(dòng)
  • 配置視圖解析器

6、創(chuàng)建Controller

編寫一個(gè)Java控制類

import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping;@Controller @RequestMapping("/h1") public class HelloController {//類上注冊(cè)了@RequestMapping方法就自動(dòng)下移,實(shí)際地址:項(xiàng)目名/h1/hello@RequestMapping("/hello")public String sayHello(Model model){//向模型中添加屬性msg與值,可以在JSP頁(yè)面中取出并渲染model.addAttribute("msg","hello,SpringMVCAnnotation!");//web-inf/jsp/hello.jspreturn "hello";} }
  • @Controller是為了讓Spring IOC容器初始化時(shí)自動(dòng)掃描到;
  • @RequestMapping是為了映射請(qǐng)求路徑,這里因?yàn)轭惻c方法上都有映射所以訪問(wèn)時(shí)應(yīng)該是/h1/hello(一般規(guī)約是直接在方法上寫@RequestMapping("/h1/hello"),不建議在類上寫);
  • 方法中聲明Model類型的參數(shù)是為了把Action中的數(shù)據(jù)帶到視圖中;
  • 方法返回的結(jié)果是視圖的名稱hello,加上配置文件中的前后綴變成WEB-INF/jsp/hello.jsp

7、創(chuàng)建視圖層

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

在WEB-INF/ jsp目錄中創(chuàng)建hello.jsp , 視圖可以直接取出并展示從Controller帶回的信息;

可以通過(guò)EL表示取出Model中存放的值,或者對(duì)象;

8、配置Tomcat運(yùn)行

使用springMVC必須配置的三大件:

處理器映射器、處理器適配器、視圖解析器

通常,我們只需要手動(dòng)配置視圖解析器,而處理器映射器和處理器適配器只需要開(kāi)啟注解驅(qū)動(dòng)即可,而省去了大段的xml配置

再來(lái)回顧下原理吧~

4.控制器和RestFul風(fēng)格

控制器Controller

  • 控制器復(fù)雜提供訪問(wèn)應(yīng)用程序的行為,通常通過(guò)接口定義注解定義兩種方法實(shí)現(xiàn)。
  • 控制器負(fù)責(zé)解析用戶的請(qǐng)求并將其轉(zhuǎn)換為一個(gè)模型。
  • 在Spring MVC中一個(gè)控制器類可以包含多個(gè)方法
  • 在Spring MVC中,對(duì)于Controller的配置方式有很多種

實(shí)現(xiàn)Controller接口

Controller是一個(gè)接口,在org.springframework.web.servlet.mvc包下,接口中只有一個(gè)方法;

//實(shí)現(xiàn)該接口的類獲得控制器功能 public interface Controller {//處理請(qǐng)求且返回一個(gè)模型與視圖對(duì)象ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception; }

測(cè)試:

1、新建一個(gè)Moudle,springmvc-04-controller。將剛才的03 拷貝一份, 我們進(jìn)行操作!

2、刪掉HelloController。mvc的配置文件只留下視圖解析器!
3、編寫一個(gè)Controller類,ControllerTest

import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;//定義控制器 //注意點(diǎn):不要導(dǎo)錯(cuò)包,實(shí)現(xiàn)Controller接口,重寫方法; public class ControllerTest implements Controller {public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {//返回一個(gè)模型視圖對(duì)象ModelAndView mv = new ModelAndView();mv.addObject("msg","Test1Controller");mv.setViewName("hello");return mv;} }

4、編寫完畢后,去Spring配置文件中注冊(cè)請(qǐng)求的bean;name對(duì)應(yīng)請(qǐng)求路徑,class對(duì)應(yīng)處理請(qǐng)求的類

<bean name="/t1" class="com.cheng.controller.ControllerTest1"/>

5、編寫前端hello.jsp,注意在WEB-INF/jsp目錄下編寫,對(duì)應(yīng)我們的視圖解析器

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

6、配置Tomcat運(yùn)行測(cè)試

實(shí)現(xiàn)接口Controller定義控制器是較老的辦法,其缺點(diǎn)是:
一個(gè)控制器中只有一個(gè)方法,如果要多個(gè)方法則需要定義多個(gè)Controller;定義的方式比較麻煩;

使用注解@Controller

@Controller注解類型用于聲明Spring類的實(shí)例是一個(gè)控制器(在講IOC時(shí)還提到了另外3個(gè)注解);

Spring可以使用掃描機(jī)制來(lái)找到應(yīng)用程序中所有基于注解的控制器類,為了保證Spring能找到你的控制器,需要在配置文件中聲明組件掃描。

<!-- 自動(dòng)掃描指定的包,下面所有注解類交給IOC容器管理 --> <context:component-scan base-package="com.cheng.controller"/>

增加一個(gè)ControllerTest2類,使用注解實(shí)現(xiàn);

import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping;//@Controller注解的類會(huì)自動(dòng)添加到Spring上下文中 @Controller public class ControllerTest2{//映射訪問(wèn)路徑@RequestMapping("/t2")public String index(Model model){//Spring MVC會(huì)自動(dòng)實(shí)例化一個(gè)Model對(duì)象用于向視圖中傳值model.addAttribute("msg", "ControllerTest2");//返回視圖位置return "hello";} }

運(yùn)行tomcat測(cè)試

可以發(fā)現(xiàn),我們的兩個(gè)請(qǐng)求都可以指向一個(gè)視圖,但是頁(yè)面結(jié)果的結(jié)果是不一樣的,從這里可以看出視圖是被復(fù)用的,而控制器與視圖之間是弱偶合關(guān)系。

注解方式是平時(shí)使用的最多的方式!

RequestMapping

@RequestMapping注解用于映射url到控制器類或一個(gè)特定的處理程序方法。可用于類或方法上。用于類上,表示類中的所有響應(yīng)請(qǐng)求的方法都是以該地址作為父路徑。

只注解在方法上面

@Controller public class TestController {@RequestMapping("/h1")public String test(){return "test";} }

訪問(wèn)路徑:http://localhost:8080 / 項(xiàng)目名 / h1

同時(shí)注解類與方法

@Controller @RequestMapping("/admin") public class TestController {@RequestMapping("/h1")public String test(){return "test";} }

訪問(wèn)路徑:http://localhost:8080 / 項(xiàng)目名/ admin /h1 , 需要先指定類的路徑再指定方法的路徑;

RestFul 風(fēng)格

概念

Restful就是一個(gè)資源定位及資源操作的風(fēng)格。不是標(biāo)準(zhǔn)也不是協(xié)議,只是一種風(fēng)格。基于這個(gè)風(fēng)格設(shè)計(jì)的軟件可以更簡(jiǎn)潔,更有層次,更易于實(shí)現(xiàn)緩存等機(jī)制。

功能

資源:互聯(lián)網(wǎng)所有的事物都可以被抽象為資源

資源操作:使用POST、DELETE、PUT、GET,使用不同方法對(duì)資源進(jìn)行操作。

分別對(duì)應(yīng) 添加、 刪除、修改、查詢。

傳統(tǒng)方式操作資源 :通過(guò)不同的參數(shù)來(lái)實(shí)現(xiàn)不同的效果!方法單一,post 和 get

? http://127.0.0.1/item/queryItem.action?id=1 查詢,GET

? http://127.0.0.1/item/saveItem.action 新增,POST

? http://127.0.0.1/item/updateItem.action 更新,POST

? http://127.0.0.1/item/deleteItem.action?id=1 刪除,GET或POST

使用RESTful操作資源 :可以通過(guò)不同的請(qǐng)求方式來(lái)實(shí)現(xiàn)不同的效果!如下:請(qǐng)求地址一樣,但是功能可以不同!

? http://127.0.0.1/item/1 查詢,GET

? http://127.0.0.1/item 新增,POST

? http://127.0.0.1/item 更新,PUT

? http://127.0.0.1/item/1 刪除,DELETE

學(xué)習(xí)測(cè)試

1、在新建一個(gè)類 RestFulController

@Controller public class RestFulController { }

2、在Spring MVC中可以使用 @PathVariable 注解,讓方法參數(shù)的值對(duì)應(yīng)綁定到一個(gè)URI模板變量上。

@Controller public class RestFulController {//映射訪問(wèn)路徑@RequestMapping("/commit/{p1}/{p2}")public String index(@PathVariable int p1, @PathVariable int p2, Model model){int result = p1+p2;//Spring MVC會(huì)自動(dòng)實(shí)例化一個(gè)Model對(duì)象用于向視圖中傳值model.addAttribute("msg", "結(jié)果:"+result);//返回視圖位置return "hello"; } }

3、測(cè)試

4、思考:使用路徑變量的好處?

  • 使路徑變得更加簡(jiǎn)潔;
  • 獲得參數(shù)更加方便,框架會(huì)自動(dòng)進(jìn)行類型轉(zhuǎn)換。
  • 通過(guò)路徑變量的類型可以約束訪問(wèn)參數(shù),如果類型不一樣,則訪問(wèn)不到對(duì)應(yīng)的請(qǐng)求方法,如這里訪問(wèn)是的路徑是/commit/1/a,則路徑與方法不匹配,而不會(huì)是參數(shù)轉(zhuǎn)換失敗。

5、我們來(lái)修改下對(duì)應(yīng)的參數(shù)類型,再次測(cè)試

//映射訪問(wèn)路徑 @RequestMapping("/commit/{p1}/{p2}") public String index(@PathVariable int p1, @PathVariable String p2, Model model){String result = p1+p2;//Spring MVC會(huì)自動(dòng)實(shí)例化一個(gè)Model對(duì)象用于向視圖中傳值model.addAttribute("msg", "結(jié)果:"+result);//返回視圖位置return "hello"; }


Spring MVC 的 @RequestMapping 注解能夠處理 HTTP 請(qǐng)求的方法, 比如 GET, PUT, POST, DELETE 以及 PATCH。

所有的地址欄請(qǐng)求默認(rèn)都會(huì)是 HTTP GET 類型的。

方法級(jí)別的注解變體有如下幾個(gè):組合注解

@GetMapping @PostMapping @PutMapping @DeleteMapping @PatchMapping

@GetMapping 是一個(gè)組合注解,平時(shí)使用的會(huì)比較多!

它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一個(gè)快捷方式。

擴(kuò)展:小黃鴨調(diào)試法

場(chǎng)景一:我們都有過(guò)向別人(甚至可能向完全不會(huì)編程的人)提問(wèn)及解釋編程問(wèn)題的經(jīng)歷,但是很多時(shí)候就在我們解釋的過(guò)程中自己卻想到了問(wèn)題的解決方案,然后對(duì)方卻一臉茫然。

場(chǎng)景二:你的同行跑來(lái)問(wèn)你一個(gè)問(wèn)題,但是當(dāng)他自己把問(wèn)題說(shuō)完,或說(shuō)到一半的時(shí)候就想出答案走了,留下一臉茫然的你。

其實(shí)上面兩種場(chǎng)景現(xiàn)象就是所謂的小黃鴨調(diào)試法(Rubber Duck Debuging),又稱橡皮鴨調(diào)試法,它是我們軟件工程中最常使用調(diào)試方法之一。

此概念據(jù)說(shuō)來(lái)自《程序員修煉之道》書(shū)中的一個(gè)故事,傳說(shuō)程序大師隨身攜帶一只小黃鴨,在調(diào)試代碼的時(shí)候會(huì)在桌上放上這只小黃鴨,然后詳細(xì)地向鴨子解釋每行代碼,然后很快就將問(wèn)題定位修復(fù)了。

5.結(jié)果跳轉(zhuǎn)方式

ModelAndView

設(shè)置ModelAndView對(duì)象 , 根據(jù)view的名稱 , 和視圖解析器跳到指定的頁(yè)面 .

頁(yè)面 : {視圖解析器前綴} + viewName +{視圖解析器后綴}

<!-- 視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"id="internalResourceViewResolver"><!-- 前綴 --><property name="prefix" value="/WEB-INF/jsp/" /><!-- 后綴 --><property name="suffix" value=".jsp" /> </bean> public class ControllerTest implements Controller {public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {//返回一個(gè)模型視圖對(duì)象ModelAndView mv = new ModelAndView();mv.addObject("msg","Test1Controller");mv.setViewName("hello");return mv;} }

ServletAPI

通過(guò)設(shè)置ServletAPI , 不需要視圖解析器(去把視圖解析器注釋掉)

1、通過(guò)HttpServletResponse進(jìn)行輸出

2、通過(guò)HttpServletResponse實(shí)現(xiàn)重定向

3、通過(guò)HttpServletRequest實(shí)現(xiàn)請(qǐng)求轉(zhuǎn)發(fā)

@Controller public class ResultGo {@RequestMapping("/r/t1")public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {rsp.getWriter().println("Hello,Spring by servlet API");}@RequestMapping("/r/t2")public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {rsp.sendRedirect("/index.jsp"); // 重定向}@RequestMapping("/r/t3")public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {//轉(zhuǎn)發(fā)req.setAttribute("msg","/r/t3");req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,rsp); // 請(qǐng)求轉(zhuǎn)發(fā)} }

SpringMVC

1、無(wú)視圖解析器情況下通過(guò)SpringMVC來(lái)實(shí)現(xiàn)轉(zhuǎn)發(fā)和重定向。

測(cè)試前,需要將視圖解析器注釋掉

默認(rèn)為請(qǐng)求轉(zhuǎn)發(fā)forward(也可以加上)
重定向redirect需特別加

@Controller public class ResultSpringmvc {@RequestMapping("/rs/t1")public String test1(){//轉(zhuǎn)發(fā)一 此時(shí)在index.jsp,但URI為http://localhost:8080/rs/t1return "/index.jsp";}@RequestMapping("/rs/t2")public String test2(){//轉(zhuǎn)發(fā)二 此時(shí)在index.jsp,但URI為http://localhost:8080/rs/t2return "forward:/index.jsp";}@RequestMapping("/rs/t3")public String test3(){//重定向 此時(shí)URI為http://localhost:8080/index.jspreturn "redirect:/index.jsp";} }

2、有視圖解析器情況下通過(guò)SpringMVC來(lái)實(shí)現(xiàn)轉(zhuǎn)發(fā)和重定向。

首先配置好視圖解析器

重定向 , 不需要視圖解析器 , 本質(zhì)就是重新請(qǐng)求一個(gè)新地方嘛 , 所以注意路徑問(wèn)題.

可以重定向到另外一個(gè)請(qǐng)求實(shí)現(xiàn) .

默認(rèn)為forward轉(zhuǎn)發(fā)(不可以加上)
因?yàn)橛幸晥D解析器的存在,如果加上(即forward:/hello.jsp)會(huì)被解析成為/WEB-INF/jsp/forward:/hello.jsp.jsp
redirect轉(zhuǎn)發(fā)需特別加

@Controller public class ResultSpringmvc2 {@RequestMapping("/rs2/t1")public String test1(){//轉(zhuǎn)發(fā)return "hello";}@RequestMapping("/rs2/t2")public String test2(){//重定向return "redirect:/index.jsp";/*return "redirect:t1";// t1為另一個(gè)請(qǐng)求?;蛘呖梢詫懗蓃eturn "redirect:t1.do";*/} }

6.數(shù)據(jù)處理

處理提交數(shù)據(jù)

參數(shù)名一致

@Controller public class DataHandle {@RequestMapping("/hello")public String hello(String name){System.out.println(name);return "hello";} }

提交數(shù)據(jù) : http://localhost:8080/hello?name=cheng

后臺(tái)輸出 : cheng

參數(shù)名不一致

提交的域名稱和處理方法的

//@RequestParam("username") : username提交的域的名稱 . @RequestMapping("/hello2") public String hello(@RequestParam("username") String name){System.out.println(name);return "hello"; }

提交數(shù)據(jù) : http://localhost:8080/hello?username=cheng
后臺(tái)輸出 : cheng

提交的是一個(gè)對(duì)象

要求提交的表單域和對(duì)象的屬性名一致 , 參數(shù)使用對(duì)象即可

public class User {private int id;private String name;private int age;//構(gòu)造//get/set//toString() } @RequestMapping("/u") public String user(User user){System.out.println(user);return "hello"; }

提交數(shù)據(jù) : http://localhost:8080/u/user?name=zxc&id=1&age=5
后臺(tái)輸出 : User { id=1, name=‘zxc’, age=15 }

說(shuō)明:如果使用對(duì)象的話,前端傳遞的參數(shù)名和對(duì)象名必須一致,否則就是null。

數(shù)據(jù)顯示到前端

第一種 : 通過(guò)ModelAndView

我們前面一直都是如此。就不過(guò)多解釋

第二種 : 通過(guò)ModelMap

ModelMap

@Controller public class DataDisplay {@RequestMapping("/dis")public String hello(@RequestParam("username") String name, ModelMap model){//封裝要顯示到視圖中的數(shù)據(jù)//相當(dāng)于req.setAttribute("name",name);model.addAttribute("msg",name);System.out.println(name);return "hello";} }

http://localhost:8080/dis?username=qwe

第三種 : 通過(guò)Model

Model

@RequestMapping("/dis2")public String hello(@RequestParam("username") String name, Model model){//封裝要顯示到視圖中的數(shù)據(jù)//相當(dāng)于req.setAttribute("name",name);model.addAttribute("msg",name);System.out.println(name);return "hello";}

http://localhost:8080/dis2?username=qwe

對(duì)比

就對(duì)于新手而言簡(jiǎn)單來(lái)說(shuō)使用區(qū)別就是:

Model 只有寥寥幾個(gè)方法只適合用于儲(chǔ)存數(shù)據(jù),簡(jiǎn)化了新手對(duì)于Model對(duì)象的操作和理解;ModelMap 繼承了 LinkedMap ,除了實(shí)現(xiàn)了自身的一些方法,同樣的繼承 LinkedMap 的方法和特性;ModelAndView 可以在儲(chǔ)存數(shù)據(jù)的同時(shí),可以進(jìn)行設(shè)置返回的邏輯視圖,進(jìn)行控制展示層的跳轉(zhuǎn)。 當(dāng)然更多的以后開(kāi)發(fā)考慮的更多的是性能和優(yōu)化,就不能單單僅限于此的了解。

請(qǐng)使用80%的時(shí)間打好扎實(shí)的基礎(chǔ),剩下18%的時(shí)間研究框架,2%的時(shí)間去學(xué)點(diǎn)英文,框架的官方文檔永遠(yuǎn)是最好的教程。

7.亂碼問(wèn)題

測(cè)試步驟:

1、我們可以在首頁(yè)編寫一個(gè)提交的表單

<form action="/e/t" method="post"><input type="text" name="name"><input type="submit"> </form>

2、后臺(tái)編寫對(duì)應(yīng)的處理類

@Controller public class Encoding {@RequestMapping("/e/t")public String test(Model model,String name){model.addAttribute("msg",name); //獲取表單提交的值return "hello"; //跳轉(zhuǎn)到test頁(yè)面顯示輸入的值} }

3、輸入中文測(cè)試,發(fā)現(xiàn)亂碼

不得不說(shuō),亂碼問(wèn)題是在我們開(kāi)發(fā)中十分常見(jiàn)的問(wèn)題,也是讓我們比較頭大的問(wèn)題。

以前亂碼問(wèn)題通過(guò)過(guò)濾器解決 , 而SpringMVC給我們提供了一個(gè)過(guò)濾器 , 可以在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>

修改了xml文件需要重啟服務(wù)器。

注意/是過(guò)濾所有請(qǐng)求,/*包括jsp頁(yè)面也會(huì)過(guò)濾,因?yàn)閬y碼是顯示問(wèn)題,所以jsp也要加入到過(guò)濾當(dāng)中。


但是我們發(fā)現(xiàn),有些極端情況下,這個(gè)過(guò)濾器對(duì)get方法并不能解決亂碼問(wèn)題。

處理方法 :

1、修改tomcat配置文件 :設(shè)置編碼!

<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />

2、使用通用編碼過(guò)濾器類,見(jiàn)我另一篇文章

3、查看是不是客戶端顯示編碼有問(wèn)題。(如瀏覽器中右鍵-編碼-選擇Unicode(UTF-8))

8.JSON交互處理

什么是JSON?

  • JSON(JavaScript Object Notation, JS 對(duì)象標(biāo)記) 是一種輕量級(jí)的數(shù)據(jù)交換格式,目前使用特別廣泛。
  • 采用完全獨(dú)立于編程語(yǔ)言的文本格式來(lái)存儲(chǔ)和表示數(shù)據(jù)。
  • 簡(jiǎn)潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語(yǔ)言。
  • 易于人閱讀和編寫,同時(shí)也易于機(jī)器解析和生成,并有效地提升網(wǎng)絡(luò)傳輸效率。
  • 在 JavaScript 語(yǔ)言中,一切都是對(duì)象。因此,任何JavaScript 支持的類型都可以通過(guò) JSON
    來(lái)表示,例如字符串、數(shù)字、對(duì)象、數(shù)組等??纯此囊蠛驼Z(yǔ)法格式:
    對(duì)象表示為鍵值對(duì),數(shù)據(jù)由逗號(hào)分隔
    花括號(hào)保存對(duì)象
    方括號(hào)保存數(shù)組

JSON 鍵值對(duì)是用來(lái)保存 JavaScript 對(duì)象的一種方式,和 JavaScript 對(duì)象的寫法也大同小異,鍵/值對(duì)組合中的鍵名寫在前面并用雙引號(hào) “” 包裹,使用冒號(hào) : 分隔,然后緊接著值:

{"name": "QinJiang"} {"age": "3"} {"sex": "男"}

很多人搞不清楚 JSON 和 JavaScript 對(duì)象的關(guān)系,甚至連誰(shuí)是誰(shuí)都不清楚。其實(shí),可以這么理解:

JSON 是 JavaScript 對(duì)象的字符串表示法,它使用文本表示一個(gè) JS 對(duì)象的信息,本質(zhì)是一個(gè)字符串。

var obj = {a: 'Hello', b: 'World'}; //這是一個(gè)對(duì)象,注意鍵名也是可以使用引號(hào)包裹的 var json = '{"a": "Hello", "b": "World"}'; //這是一個(gè) JSON 字符串,本質(zhì)是一個(gè)字符串

JSON 和 JavaScript 對(duì)象互轉(zhuǎn)

要實(shí)現(xiàn)從JSON字符串轉(zhuǎn)換為JavaScript 對(duì)象,使用 JSON.parse() 方法:

var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //結(jié)果是 {a: 'Hello', b: 'World'}

要實(shí)現(xiàn)從JavaScript 對(duì)象轉(zhuǎn)換為JSON字符串,使用 JSON.stringify() 方法:

var json = JSON.stringify({a: 'Hello', b: 'World'}); //結(jié)果是 '{"a": "Hello", "b": "World"}'

代碼測(cè)試

1、新建一個(gè)module ,springmvc-05-json , 添加web的支持

2、在web目錄下新建一個(gè) json-1.html , 編寫測(cè)試內(nèi)容

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>JSON_test</title> </head> <body><script type="text/javascript">//編寫一個(gè)js的對(duì)象var user = {name:"張三",age:3,sex:"男"};//將js對(duì)象轉(zhuǎn)換成json字符串var str = JSON.stringify(user);console.log(str);//將json字符串轉(zhuǎn)換為js對(duì)象var user2 = JSON.parse(str);console.log(user2.age,user2.name,user2.sex);</script> </body> </html>

3、在IDEA中使用瀏覽器打開(kāi),查看控制臺(tái)輸出!

JSON解析工具Jackson的使用

Jackson應(yīng)該是目前比較好的json解析工具了
當(dāng)然工具不止這一個(gè),比如還有阿里巴巴的 fastjson 等等。

1、導(dǎo)入它的jar包。

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.8</version> </dependency>

2、將上一項(xiàng)目的web.xml的內(nèi)容和springmvc-servlet.xml文件拷過(guò)來(lái)。springmvc-servlet.xml內(nèi)容稍作修改

3、編寫一個(gè)User的實(shí)體類

4、編寫我們的測(cè)試Controller。這里我們需要兩個(gè)新東西,一個(gè)是 @ResponseBody,一個(gè)是ObjectMapper對(duì)象,我們看下具體的用法

@Controller public class UserController {@RequestMapping("/json")@ResponseBodypublic String json1() throws JsonProcessingException {//創(chuàng)建一個(gè)jackson的對(duì)象映射器,用來(lái)解析數(shù)據(jù)ObjectMapper mapper = new ObjectMapper();//創(chuàng)建一個(gè)對(duì)象User user = new User("長(zhǎng)江123", 3, "男");//將我們的對(duì)象解析成為json格式String str = mapper.writeValueAsString(user);//由于@ResponseBody注解,這里會(huì)將str轉(zhuǎn)成json格式返回;十分方便return str;} }

配置Tomcat , 啟動(dòng)測(cè)試,發(fā)現(xiàn)出現(xiàn)亂碼

我們需要設(shè)置一下他的編碼格式為utf-8,以及它返回的類型。

通過(guò)@RequestMaping的produces屬性來(lái)實(shí)現(xiàn),修改下代碼

//produces:指定響應(yīng)體返回類型和編碼 @RequestMapping(value = "/json",produces = "application/json;charset=utf-8")

亂碼問(wèn)題解決

JSON亂碼問(wèn)題

亂碼統(tǒng)一解決

上一種方法比較麻煩,如果項(xiàng)目中有許多請(qǐng)求則每一個(gè)都要添加,可以通過(guò)Spring配置統(tǒng)一指定,這樣就不用每次都去處理了!

我們可以在springmvc的配置文件上添加一段消息StringHttpMessageConverter轉(zhuǎn)換配置!

<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>

統(tǒng)一解決返回的JSON字符串亂碼問(wèn)題

類上直接使用 @RestController ,這樣子,里面所有的方法都只會(huì)返回 json 字符串了,不用再每一個(gè)都添加@ResponseBody 。我們?cè)谇昂蠖朔蛛x開(kāi)發(fā)中,一般都使用 @RestController ,十分便捷。

@RestController public class UserController {@RequestMapping(value = "/json")public String json1() throws JsonProcessingException {//創(chuàng)建一個(gè)jackson的對(duì)象映射器,用來(lái)解析數(shù)據(jù)ObjectMapper mapper = new ObjectMapper();//創(chuàng)建一個(gè)對(duì)象User user = new User("長(zhǎng)江123", 3, "男");//將我們的對(duì)象解析成為json格式String str = mapper.writeValueAsString(user);//由于@ResponseBody注解,這里會(huì)將str轉(zhuǎn)成json格式返回;十分方便return str;} }

輸出JSON集合

增加一個(gè)新的方法

@RequestMapping("/json2") public String json2() throws JsonProcessingException {//創(chuàng)建一個(gè)jackson的對(duì)象映射器,用來(lái)解析數(shù)據(jù)ObjectMapper mapper = new ObjectMapper();//創(chuàng)建一個(gè)對(duì)象User user1 = new User("自行車1號(hào)", 3, "男");User user2 = new User("自行車2號(hào)", 3, "男");User user3 = new User("自行車3號(hào)", 3, "男");User user4 = new User("自行車4號(hào)", 3, "男");List<User> list = new ArrayList<User>();list.add(user1);list.add(user2);list.add(user3);list.add(user4);//將我們的對(duì)象解析成為json格式String str = mapper.writeValueAsString(list);return str; }

輸出時(shí)間對(duì)象

增加一個(gè)新的方法

@RequestMapping("/json3") public String json3() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();//創(chuàng)建時(shí)間一個(gè)對(duì)象,java.util.DateDate date = new Date();//將我們的對(duì)象解析成為json格式String str = mapper.writeValueAsString(date);return str; }


默認(rèn)日期格式會(huì)變成一個(gè)數(shù)字,是1970年1月1日到當(dāng)前日期的毫秒數(shù)

Jackson 默認(rèn)是會(huì)把時(shí)間轉(zhuǎn)成timestamps形式

解決方案:取消timestamps形式 , 自定義時(shí)間格式

@RequestMapping("/json4") public String json4() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();//不使用時(shí)間戳的方式mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);//自定義日期格式對(duì)象SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//指定日期格式mapper.setDateFormat(sdf);Date date = new Date();String str = mapper.writeValueAsString(date);return str; }

運(yùn)行結(jié)果 : 成功的輸出了時(shí)間

抽取為工具類

如果要經(jīng)常使用的話,這樣是比較麻煩的,我們可以將這些代碼封裝到一個(gè)工具類中;我們?nèi)ゾ帉懴?/p> package com.cheng.utils;import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature;import java.text.SimpleDateFormat;public class JsonUtils {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();//不使用時(shí)間差的方式mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);//自定義日期格式對(duì)象SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);//指定日期格式mapper.setDateFormat(sdf);try {return mapper.writeValueAsString(object);} catch (JsonProcessingException e) {e.printStackTrace();}return null;} }

我們使用工具類,代碼就更加簡(jiǎn)潔了!

@RequestMapping("/json4") public String json4() throws JsonProcessingException {Date date = new Date();String json = JsonUtils.getJson(date);return json; }

JSON解析工具FastJson的使用

fastjson.jar是阿里開(kāi)發(fā)的一款專門用于Java開(kāi)發(fā)的包,可以方便的實(shí)現(xiàn)json對(duì)象與JavaBean對(duì)象的轉(zhuǎn)換,實(shí)現(xiàn)JavaBean對(duì)象與json字符串的轉(zhuǎn)換,實(shí)現(xiàn)json對(duì)象與json字符串的轉(zhuǎn)換。實(shí)現(xiàn)json的轉(zhuǎn)換方法很多,最后的實(shí)現(xiàn)結(jié)果都是一樣的。

fastjson 的 pom依賴!

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

Fastjson 三個(gè)主要的類:

JSONObject 代表 json 對(duì)象

  • JSON Object實(shí)現(xiàn)了Map接口, 猜想 JSONObject底層操作是由Map實(shí)現(xiàn)的。

  • JSONObject對(duì)應(yīng)json對(duì)象,通過(guò)各種形式的get()方法可以獲取json對(duì)象中的數(shù)據(jù),也可利用諸如size(),isEmpty()等方法獲取"鍵:值"對(duì)的個(gè)數(shù)和判斷是否為空。其本質(zhì)是通過(guò)實(shí)現(xiàn)Map接口并調(diào)用接口中的方法完成的。

JSONArray 代表 json 對(duì)象數(shù)組

  • 內(nèi)部是有List接口中的方法來(lái)完成操作的。

JSON代表 JSONObject和JSONArray的轉(zhuǎn)化

  • JSON類源碼分析與使用
  • 仔細(xì)觀察這些方法,主要是實(shí)現(xiàn)json對(duì)象,json對(duì)象數(shù)組,javabean對(duì)象,json字符串之間的相互轉(zhuǎn)化。

代碼測(cè)試,我們新建一個(gè)FastJsonDemo 類

package com.cheng.controller;import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.cheng.pojo.User;import java.util.ArrayList; import java.util.List;public class FastJsonDemo {public static void main(String[] args) {//創(chuàng)建一個(gè)對(duì)象User user1 = new User("1號(hào)", 3, "男");User user2 = new User("2號(hào)", 3, "男");User user3 = new User("3號(hào)", 3, "男");User user4 = new User("4號(hào)", 3, "男");List<User> list = new ArrayList<User>();list.add(user1);list.add(user2);list.add(user3);list.add(user4);System.out.println("*******Java對(duì)象 轉(zhuǎn) JSON字符串*******");String str1 = JSON.toJSONString(list);System.out.println("JSON.toJSONString(list)==>"+str1);String str2 = JSON.toJSONString(user1);System.out.println("JSON.toJSONString(user1)==>"+str2);System.out.println("\n****** JSON字符串 轉(zhuǎn) Java對(duì)象*******");User jp_user1=JSON.parseObject(str2,User.class);System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);System.out.println("\n****** Java對(duì)象 轉(zhuǎn) JSON對(duì)象 ******");JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));System.out.println("\n****** JSON對(duì)象 轉(zhuǎn) Java對(duì)象 ******");User to_java_user = JSON.toJavaObject(jsonObject1, User.class);System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);} }

輸出:

*******Java對(duì)象 轉(zhuǎn) JSON字符串******* JSON.toJSONString(list)==>[{"age":3,"name":"1號(hào)","sex":"男"},{"age":3,"name":"2號(hào)","sex":"男"},{"age":3,"name":"3號(hào)","sex":"男"},{"age":3,"name":"4號(hào)","sex":"男"}] JSON.toJSONString(user1)==>{"age":3,"name":"1號(hào)","sex":"男"}****** JSON字符串 轉(zhuǎn) Java對(duì)象******* JSON.parseObject(str2,User.class)==>User{name='1號(hào)', age=3, sex='男'}****** Java對(duì)象 轉(zhuǎn) JSON對(duì)象 ****** (JSONObject) JSON.toJSON(user2)==>2號(hào)****** JSON對(duì)象 轉(zhuǎn) Java對(duì)象 ****** JSON.toJavaObject(jsonObject1, User.class)==>User{name='2號(hào)', age=3, sex='男'}Process finished with exit code 0

這種工具類,我們只需要掌握使用就好了,在使用的時(shí)候在根據(jù)具體的業(yè)務(wù)去找對(duì)應(yīng)的實(shí)現(xiàn)。和以前的commons-io那種工具包一樣,拿來(lái)用就好了。

Json在我們數(shù)據(jù)傳輸中十分重要,一定要學(xué)會(huì)使用!

9.AJAX

簡(jiǎn)介

  • AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。
  • AJAX 是一種在無(wú)需重新加載整個(gè)網(wǎng)頁(yè)的情況下,能夠更新部分網(wǎng)頁(yè)的技術(shù)。
  • Ajax 不是一種新的編程語(yǔ)言,而是一種用于創(chuàng)建更好更快以及交互性更強(qiáng)的Web應(yīng)用程序的技術(shù)。
  • 在 2005 年,Google 通過(guò)其 Google Suggest 使 AJAX 變得流行起來(lái)。Google
    Suggest能夠自動(dòng)幫你完成搜索單詞。
  • Google Suggest 使用 AJAX 創(chuàng)造出動(dòng)態(tài)性極強(qiáng)的 web 界面:當(dāng)您在谷歌的搜索框輸入關(guān)鍵字時(shí),JavaScript會(huì)把這些字符發(fā)送到服務(wù)器,然后服務(wù)器會(huì)返回一個(gè)搜索建議的列表。就和國(guó)內(nèi)百度的搜索框一樣!
  • 傳統(tǒng)的網(wǎng)頁(yè)(即不用ajax技術(shù)的網(wǎng)頁(yè)),想要更新內(nèi)容或者提交一個(gè)表單,都需要重新加載整個(gè)網(wǎng)頁(yè)。
  • 使用ajax技術(shù)的網(wǎng)頁(yè),通過(guò)在后臺(tái)服務(wù)器進(jìn)行少量的數(shù)據(jù)交換,就可以實(shí)現(xiàn)異步局部更新。
  • 使用Ajax,用戶可以創(chuàng)建接近本地桌面應(yīng)用的直接、高可用、更豐富、更動(dòng)態(tài)的Web用戶界面。

偽造Ajax

我們可以使用前端的一個(gè)標(biāo)簽來(lái)偽造一個(gè)ajax的樣子。iframe標(biāo)簽

1、新建一個(gè)module :springmvc-06-ajax , 導(dǎo)入web支持

2、編寫一個(gè) ajax-frame.html 使用 iframe 測(cè)試,感受下效果

<!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8"><title>ajax-demo</title> </head> <body><script type="text/javascript">window.onload = function(){var myDate = new Date();document.getElementById('currentTime').innerText = myDate.getTime();};function LoadPage(){var targetUrl = document.getElementById('url').value;console.log(targetUrl);document.getElementById("iframePosition").src = targetUrl;}</script><div><p>請(qǐng)輸入要加載的地址:<span id="currentTime"></span></p><p><input id="url" type="text" value="https://www.baidu.com/"/><input type="button" value="提交" onclick="LoadPage()"></p> </div><div><h3>加載頁(yè)面位置:</h3><iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe> </div></body> </html>

3、使用IDEA開(kāi)瀏覽器測(cè)試一下!

利用AJAX可以做:

  • 注冊(cè)時(shí),輸入用戶名自動(dòng)檢測(cè)用戶是否已經(jīng)存在。
  • 登陸時(shí),提示用戶名密碼錯(cuò)誤
  • 刪除數(shù)據(jù)行時(shí),將行ID發(fā)送到后臺(tái),后臺(tái)在數(shù)據(jù)庫(kù)中刪除,數(shù)據(jù)庫(kù)刪除成功后,在頁(yè)面DOM中將數(shù)據(jù)行也刪除。

jQuery.ajax

純JS原生實(shí)現(xiàn)Ajax我們不去講解這里,直接使用jquery提供的,方便學(xué)習(xí)和使用,避免重復(fù)造輪子,有興趣的同學(xué)可以去了解下JS原生XMLHttpRequest !

Ajax的核心是XMLHttpRequest對(duì)象(XHR)。XHR為向服務(wù)器發(fā)送請(qǐng)求和解析服務(wù)器響應(yīng)提供了接口。能夠以異步方式從服務(wù)器獲取新數(shù)據(jù)。

jQuery 提供多個(gè)與 AJAX 有關(guān)的方法。

通過(guò) jQuery AJAX 方法,您能夠使用 HTTP Get 和 HTTP Post 從遠(yuǎn)程服務(wù)器上請(qǐng)求文本、HTML、XML 或 JSON – 同時(shí)您能夠把這些外部數(shù)據(jù)直接載入網(wǎng)頁(yè)的被選元素中。

jQuery 不是生產(chǎn)者,而是大自然搬運(yùn)工。

jQuery Ajax本質(zhì)就是 XMLHttpRequest,對(duì)他進(jìn)行了封裝,方便調(diào)用!

jQuery.ajax(...)部分參數(shù):url:請(qǐng)求地址type:請(qǐng)求方式,GET、POST(1.9.0之后用method)headers:請(qǐng)求頭data:要發(fā)送的數(shù)據(jù)contentType:即將發(fā)送信息至服務(wù)器的內(nèi)容編碼類型(默認(rèn): "application/x-www-form-urlencoded; charset=UTF-8")async:是否異步timeout:設(shè)置請(qǐng)求超時(shí)時(shí)間(毫秒)beforeSend:發(fā)送請(qǐng)求前執(zhí)行的函數(shù)(全局)complete:完成之后執(zhí)行的回調(diào)函數(shù)(全局)success:成功之后執(zhí)行的回調(diào)函數(shù)(全局)error:失敗之后執(zhí)行的回調(diào)函數(shù)(全局)accepts:通過(guò)請(qǐng)求頭發(fā)送給服務(wù)器,告訴服務(wù)器當(dāng)前客戶端可接受的數(shù)據(jù)類型dataType:將服務(wù)器端返回的數(shù)據(jù)轉(zhuǎn)換成指定類型"xml": 將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成xml格式"text": 將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成普通文本格式"html": 將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成普通文本格式,在插入DOM中時(shí),如果包含JavaScript標(biāo)簽,則會(huì)嘗試去執(zhí)行。"script": 嘗試將返回值當(dāng)作JavaScript去執(zhí)行,然后再將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成普通文本格式"json": 將服務(wù)器端返回的內(nèi)容轉(zhuǎn)換成相應(yīng)的JavaScript對(duì)象"jsonp": JSONP 格式使用 JSONP 形式調(diào)用函數(shù)時(shí),如 "myurl?callback=?" jQuery 將自動(dòng)替換 ? 為正確的函數(shù)名,以執(zhí)行回調(diào)函數(shù)

我們來(lái)個(gè)簡(jiǎn)單的測(cè)試,使用最原始的HttpServletResponse處理。最簡(jiǎn)單 , 最通用

10.攔截器

11.文件上傳和下載

總結(jié)

以上是生活随笔為你收集整理的Java学习笔记13-1——SpringMVC的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。