springmvc 響應,同步-頁面跳轉,異步-網絡請求返回數據 ; ajax異步交互; restful前後端分離開發風格;
異常統一處理;攔截器
一.SpringMVC的響應:
(1)頁面跳轉=====轉發
方式一:簡單方式
方式 二: forward關鍵字:
此關鍵字的底層就是:request.getRequestDispatcher("跳轉路徑").forward(req,resp);
此關鍵字在使用後,不在經過視圖解析器進行字符串的拼接...
@RequestMapping("/quick")
public String quick(){
// return "success"; //方式一
// int i=1/0;
return "forward:/WEB-INF/pages/success.jsp"; //方式二
}
方式三:servlet原生API
轉發攜帶數據:(request域)
方式一:ServletAPI
@RequestMapping("/requestApiData") //
public void requestApiData(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException{
request.setAttribute("message","requestApiData==方式四轉發攜帶數據:");
request.getRequestDispatcher("/WEB-INF/pages/successData.jsp").forward(request,response);
}
方式二:ModelAndView對象
@RequestMapping("/modelAndView")
public ModelAndView modelAndView(ModelAndView modelAndView){
modelAndView.addObject("message","modelAndView==方式四轉發攜帶數據:");
modelAndView.setViewName("successData");
return modelAndView;
}
方式三:Model對象:
@RequestMapping("/quickModel")
public String quickModel(Model model){
model.addAttribute("message","quickModel==b不會收到的");
return "successData";
}
(2)頁面跳轉---重定向
方式一:redirect 關鍵字
此關鍵字的底層:response.sendRedirect("web項目地址+重定向地址");
而且還在此技術上進行了優化,我們不需要再去編寫web項目地址,直接編寫重定向地址.
//方式一
@RequestMapping("/redirect")
public String redirect(){
return "redirect:/index.jsp";
}
方式二:servlet原生API
@RequestMapping("/responseRedirect")
public void responseRedirect(HttpServletRequest request,HttpServletResponse response,HttpSession session) throws ServletException ,IOException{
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
二、ajax異步交互
需求:
發送$.ajax()
響應new ObjectMapper().writeValueAsString()
關於SpringMVC框架,ajax異步請求,後端響應json
在SpringMVC中,這個功能主要是通過兩個註解@RequestBody 和 @ResponseBody實現的
注意:
SpringMVC默認用MappingJackson2HttpMessageConverter對json數據進行轉換,需要加入jackson的包
<!--jsckson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
(1)RequestBody
用於接收前端傳遞的請求體中的json數據, 並可以自動轉換封裝進指定的對象中。
開啓靜態資源放行:
頁面引入jquery文件
編寫ajax代碼:
<button id="ajaxBtn">發送ajax請求</button>
<script>
$('#ajaxBtn').click(function () {
// alert(1)
/*
使用: $.ajax() 函數
規則:
1.ajax提交的數據必須是一個標準的json字符串
2.ajax提交的方式必須爲post,數據必須在請求體中
3.ajax提交的MIME類型必須爲:application/json;charset=utf-8
*/
$.ajax({
url: '${pageContext.request.contextPath}/ajaxRequest',
type: 'POST',
data: '{"username":"lucy","age":18}',
contentType:'application/json;charset=utf-8',
success: function (resp) {
}
});
})
</script>
編寫User實體類:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String username;
private Integer age;
}
獲取請求體的json數據
(2)@ResponseBody
用於將controller方法返回的對象通過轉換器轉換爲指定的格式(通常爲json)之後,寫入到response對象的響應體中。
總結:
@RequestBody:將請求體中的json字符串,轉爲指定類型的java對象
@ResponseBody:將java對象轉爲json字符串,再設置到響應體中,返回到瀏覽器(客戶端)
三.Restful設計風格
Restful是一種軟件架構風格、設計風格,而不是標準,只是提供了一組設計原則和約束條件。主要用於客戶端和服務器交互類的軟件,基於這個風格設計的軟件可以更簡潔,更有層次,更易於實現緩存機制等。
應用場景:前(html)後端(servlet)分離開發的架構中(ajax交互)
Restful規範了HTTP請求動作,使用四個詞語分別表示對資源的CRUD操作:
-
GET(獲取)、POST(新建)、PUT(更新)、DELETE(刪除)
模擬Restful風格代碼:ajax交互
/*@Controller
@ResponseBody*/
@RestController
public class RestFulController {
// 查詢所有
// @RequestMapping(value = "/user", method = RequestMethod.GET)
@GetMapping("/user")
// @ResponseBody // 就相當於 response.getWriter().write()
public String findAll() {
System.out.println("查詢所有");
return "findAll";
}
// 查詢一個
// @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
@GetMapping("/user/{id}")
// @ResponseBody
public String findById(@PathVariable Integer id) {
System.out.println("查詢一個");
return "findById:" + id;
}
// 新增
// @RequestMapping(value = "/user", method = RequestMethod.POST)
@PostMapping("/user")
// @ResponseBody
public String save(User user) {
System.out.println("新增");
return "save";
}
// 修改
// @RequestMapping(value = "/user", method = RequestMethod.PUT)
@PutMapping("/user")
// @ResponseBody
public String update(User user) {
System.out.println("新增");
return "update";
}
// 刪除
// @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
@DeleteMapping("/user/{id}")
// @ResponseBody
public String delete(@PathVariable Integer id) {
System.out.println("刪除");
return "delete:" + id;
}
}
測試:瀏覽器默認只能發送:get、post請求
進入公司,如何測試自己後端代碼?藉助於postman工具,它可以模擬瀏覽器發送請求(get、post、put、delete)等請求方式...
四.異常處理
java對於異常的處理一般有兩種方式:
-
一種是當前方法處理(try-catch),這種處理方式會造成業務代碼和異常處理代碼的耦合。
-
一種是當前方法不處理, 出現異常後直接拋給調用者處理。
使用Spring框架後,我們的代碼最終是由框架來調用的。也就是說,異常最終會拋到框架中, 然後由框架指定異常處理器來統一處理異常。
(1)自定義異常處理器:
編寫異常處理器類:
// 全局異常處理器
public class GlobalExceptionResolver implements HandlerExceptionResolver {
/**
*
* @param request 請求對象
* @param response 響應對象
* @param handler 處理器對象(某一個方法method對象)
* @param ex 異常對象
* @return ModelAndView
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 獲得異常信息
String message = ex.getMessage();
// 創建 ModelAndView
ModelAndView modelAndView = new ModelAndView();
// 將異常信息存儲到model中
modelAndView.addObject("message", message);
// 指定異常友情提示頁面
modelAndView.setViewName("forward:/error.jsp");
return modelAndView;
}
}
將對對象交給ioc容器:
<!--配置全局異常處理器-->
<bean id="globalExceptionResolver" class="com.wsl.web.exception.GlobalExceptionResolver"></bean>
注意:
全局異常處理器:
錯誤頁面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>error</title>
</head>
<body>
<h4>錯誤頁面...</h4>
<span>${message}</span>
</body>
</html>
(2)@ControllerAdvice
對所有的controller(控制器)進行異常捕獲的增強,捕獲什麼異常自己來定,方法自己寫...
/*
對所有controller進行異常增強,底層就是AOP
*/
@ControllerAdvice
public class GlobalControllerAdvie {
// 捕獲所有異常(如果沒有子異常捕獲,老大哥來兜底....)
@ExceptionHandler(Exception.class)
public String resolverHandler(Exception ex, Model model) {
model.addAttribute("message", "捕獲所有異常..");
return "forward:/error.jsp";
}
// 捕獲空指針異常
@ExceptionHandler(NullPointerException.class)
public String resolverNullPointHandler(NullPointerException npe, Model model) {
model.addAttribute("message", "捕獲空指針異常..");
return "forward:/error.jsp";
}
// 捕獲數學異常
// 捕獲數組越界異常
// 捕獲內存溢出異常
}
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class MyGlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String resolverHandler(Exception ex, Model model){
model.addAttribute("message","捕獲異常");
return "forward:/error.jsp";
}
@ExceptionHandler(NullPointerException.class)
public String resolverNullPointHandler(NullPointerException point,Model model){
model.addAttribute("message","空指針異常");
return "forward:/error.jsp";
}
@ExceptionHandler(ArithmeticException .class)
public String resolverNAttHandler(NullPointerException point,Model model){
model.addAttribute("message","算術異常");
return "forward:/error.jsp";
}
}
注意:這個只能捕獲SpringMVC的異常問題、
(3)Web.xml (tomcat提供異常處理) 使用web提供的異常機制:
<!--捕獲異常
error-code 錯誤狀態碼
location 出現錯誤後,跳轉的提示頁面
-->
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
</web-app>
五.攔截器
Spring MVC 的攔截器類似於 Servlet 開發中的過濾器 Filter,用於對處理器進行預處理和後處理。
(1)入門:
編寫目標資源(TargetController)
@Controller
public class TargetController {
@RequestMapping("/target")
public String target() {
System.out.println("目標方法執行了...");
return "success";
}
}
自定義攔截器:
// 自定義攔截器
public class MyIntercepter1 implements HandlerInterceptor {
/*
在controller目標方法執行之前,攔截
返回值:
true 放行
false 攔截
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("preHandle1...");
// request 轉發
// response 重定向
// handler 獲取目標方法的一切信息,進行增強...
return true;
}
}
定義攔截器攔截規則(spring-mvc.xml)
<!--配置攔截器-->
<mvc:interceptors>
<mvc:interceptor>
<!-- @RequestMapping("/target") -->
<mvc:mapping path="/target"/>
<bean class="com.wsl.web.intercept.MyIntercepter1"></bean>
</mvc:interceptor>
</mvc:interceptors>
測試:
(2)攔截器API介紹
// 自定義攔截器
public class MyIntercepter1 implements HandlerInterceptor {
/*
在controller目標方法執行之前,攔截
返回值:
true 放行
false 攔截
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("preHandle1...");
// request 轉發
// response 重定向
// handler 獲取目標方法的一切信息,進行增強...
return true;
}
/*
在controller目標方法執行之後,進行增強
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
System.out.println("postHandle1...");
}
/*
在視圖渲染完畢後,進行資源釋放
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("afterCompletion1....");
}
}
(3)攔截器鏈
開發中攔截器可以單獨使用,也可以同時使用多個攔截器形成一條攔截器鏈。
開發步驟和單個攔截器是一樣的,只不過註冊的時候註冊多個,注意這裏註冊的順序就代表攔截器執行的順序。
例子和入門案例一致,創建另外一個MyIntercepter2,對象
1.攔截器執行先後問題:mvc:interceptor 誰先聲明,誰先攔截
攔截器方法的執行順序:先進後出
六:配置文件:
Spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--開啓註解組件掃描-->
<context:component-scan base-package="com.wsl.web"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="5024000"></property>
</bean>
<!--配置攔截器-->
<!--攔截器的配置順序決定了攔截器的執行順序-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/target"/>
<bean class="com.wsl.web.interceptor.MyIntercepter01"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/target"/>
<bean class="com.wsl.web.interceptor.MyIntercepter"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!--配置錯誤頁面-->
<!--<bean id="globalExceptionResolver" class="com.wsl.web.execption.GobalExpectionResolver"></bean>-->
<!--開啓mvc註解支持-->
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:default-servlet-handler></mvc:default-servlet-handler>
</beans>
pom.xml
<dependencies>
<!--mysql驅動-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--druid連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.15</version>
</dependency>
<!--spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!--spring核心-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--spring整合junit-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<!--springMVC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!--jsp-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
</web-app>