文章目錄
一、今日內容
1、ModelAttribute和SessionAttribute註解的使用
2、RestFul風格
3、控制器方法的返回值
4、交互JSON數據
5、springMVC實現文件上傳
6、springMVC異常處理
二、ModelAttribute和SessionAttribute註解的使用
ModelAttribute
a. @ModelAttribute註解標記在方法上
特點:當執行控制器中任何一個方法時,都會先執行@ModelAttribute標記的方法
缺點:慎重使用,因爲執行控制器中任何一個方法時,都會先執行@ModelAttribute標記的方法, 效率太低
適用於專門更新或查詢的控制器(方法比較少 且單一):
UserUpdateController
UserQueryController
b. 應用舉例:提供空缺參數值的默認值 (寫法2:map寫法 略)
/**
* 模擬根據id查詢用戶
*/
@ModelAttribute
public User findById(Integer id){
User user = new User();
user.setUsername("王五");
user.setSex("女");
return user;//會彌補下面user對象中殘缺的值 使得其不至於被清空
}
/**
* 更新時的sql語句一般這麼寫 update user set username=?,sex=? where id=? 萬一性別無需修改而沒有傳遞值 就麻煩了 此時用到@ModelAttribute
* @param user
* @return
*/
@RequestMapping(value = "/testUpdate",method = RequestMethod.POST)
public String testUpdate(User user){
System.out.println(user);//先執行的@ModelAttribute:findById 返回一個user彌補此user的空缺屬性
System.out.println("更新");
return "show";
}
SessionAttribute
c. 註解@SessionAttributes:在session範圍內存儲對象
1) @SessionAttributes({"username","password"}) 在類上標記該註解
表示在session範圍內可以存儲這兩個變量名(username和password)
2) /**
* 把用戶名和密碼存入到Session範圍內
*/
@RequestMapping("/testPut")
public void testPut(Model model){
model.addAttribute("username","zhangsan");
model.addAttribute("password","123456");
}
3) /**
* 獲取session範圍內的對象
*/
@RequestMapping("/testGet")
public void testGet(ModelMap modelMap){
Object username = modelMap.get("username");
System.out.println(username);
Object password = modelMap.get("password");
System.out.println(password);
}
4)
/**
* 清空session
* @param sessionStatus
*/
@RequestMapping("/testClear")
public void testClear(SessionStatus sessionStatus){
sessionStatus.setComplete();
}
Demo
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
</dependencies>
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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--掃描包-->
<context:component-scan base-package="cn.ahpu"></context:component-scan>
<!--視圖解析器 內部資源視圖解析 簡化return-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--引入註解驅動-->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--編碼過濾器 處理post請求亂碼 get請求亂碼tomcat內配-->
<filter>
<filter-name>CharacterEncoding</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>CharacterEncoding</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:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern><!--攔截所有資源 請求+靜態資源-->
</servlet-mapping>
</web-app>
User.java
@Data
public class User {
private Integer id;
private String username;
private String sex;
}
UserController.java
package cn.ahpu.controller;
import cn.ahpu.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
/**
* @author 寒面銀槍
* @create 2020-04-26 17:41
*/
@Controller
@RequestMapping("/user")
@SessionAttributes({"username","password"})
public class UserController {
//將用戶名密碼存到session內
@RequestMapping("/testPut")
public void testPut(Model model){//往session內存 框架指定的參數 model
model.addAttribute("username","張三");
model.addAttribute("password","123");
}
//獲取session範圍內的對象
@RequestMapping("/testGet")
public void testGet(ModelMap modelMap){//從session中取 框架指定參數 modelMap (存的時候也可以用modelmap)
Object username = modelMap.get("username");
System.out.println(username);
Object password = modelMap.get("password");
System.out.println(password);
}
//清空session
@RequestMapping("/testClear")
public void testClear(SessionStatus sessionStatus){//設置一下會話狀態即可清除session值
sessionStatus.setComplete();
}
@ModelAttribute
public void print(){
System.out.println("執行了");
}
@RequestMapping("/testModelAttribute")
public String testModelAttribute(){
System.out.println("test方法執行了...");
return "show";
}
@RequestMapping("/testModelAttribute2")
public String testModelAttribute2(){
System.out.println("test2方法執行了...");
return "show";
}
/**
* 模擬根據id查詢用戶
*/
@ModelAttribute
public User findById(Integer id){
User user = new User();
user.setUsername("王五");
user.setSex("女");
return user;//會彌補下面user對象中殘缺的值 使得其不至於被清空
}
/**
* 更新時的sql語句一般這麼寫 update user set username=?,sex=? where id=? 萬一性別無需修改而沒有傳遞值 就麻煩了 此時用到@ModelAttribute
* @param user
* @return
*/
@RequestMapping(value = "/testUpdate",method = RequestMethod.POST)
public String testUpdate(User user){
System.out.println(user);//先執行的@ModelAttribute:findById 返回一個user彌補此user的空缺屬性
System.out.println("更新");
return "show";
}
}
index.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2020/4/26
Time: 17:45
To change this template use File | Settings | File Templates.
--%>
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>4</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/user/testModelAttribute">testModelAttribute</a><br>
<a href="${pageContext.request.contextPath}/user/testModelAttribute2">testModelAttribute2</a><br>
<hr>
<form action="${pageContext.request.contextPath}/user/testUpdate" method="post">
<input type="hidden" name="id" value="1">
姓名:<input type="text" name="username"> <br>
<%--性別:<input type="text" name="sex"><br>--%>
<input type="submit" value="提交">
</form>
<hr>
<a href="${pageContext.request.contextPath}/user/testPut">testPut Session</a><br>
<a href="${pageContext.request.contextPath}/user/testGet">testGet Session</a><br>
<a href="${pageContext.request.contextPath}/user/testClear">testClear Session</a><br>
</body>
</html>
三、RestFul風格(目前並不常用)
根據請求方式不同,最終執行的方法不同
a. rest 是一種編程風格
b. 滿足了rest風格的網站就是restful風格
c. 只是一種規範,不是規則
d. eg:根據id獲取一個用戶: /user/findById?id=1 restful風格:/user/operate/1 使用get方式提交
根據id刪除一個用戶:/user/delById?id=1 restful風格:/user/operate/1 使用delete方式提交
更新一個用戶:/user/update?id=1&username=zzz restful風格:/user/operate/1 使用put方式提
添加一個用戶:/user/save?id=1&username=zzz restful風格:/user/operate 使用post方式提交
根據請求方式不同,最終執行的方法不同
e. 根據id獲取
頁面
http://localhost:8080/user/operate/1
方法
/**
* 根據id查詢
* @param id
* @return
*/
@RequestMapping(value = "/operate/{id}",method = RequestMethod.GET)
public String findById(@PathVariable("id") Integer id){
System.out.println("findById:"+id);
return "show";
}
f. 添加一個用戶
頁面
<%--請求保存用戶--%>
<form action="${pageContext.request.contextPath}/user/operate/1" method="post">
<input type="submit" value="提交">
</form>
方法
/**
* 保存用戶
* @param id
* @return
*/
@RequestMapping(value = "/operate/{id}" , method = RequestMethod.POST)
public String save(@PathVariable("id") Integer id){
System.out.println("save:" + id);
return "show";
}
h. 更新用戶
頁面:
<%--請求更新用戶--%>
<form action="${pageContext.request.contextPath}/user/operate/1" method="post">
<%--要使用put,delete提交方式
1) 在web.xml開啓put和delete提交方式
2) 表單的提交方式必須post
3) 表單中必須設置一個隱藏域 name=_method value=PUT
4) 請求的方法返回值必須以流的形式返回,在方法上標記註解:@ResponseBody
流的形式返回: response.getWriter().print()
--%>
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="更新">
</form>
方法
/**
* 更新用戶
* @param id
* @return
*/
@RequestMapping(value = "/operate/{id}" , method = RequestMethod.PUT)
@ResponseBody
public String update(@PathVariable("id") Integer id){
System.out.println("update:" + id);
return "show";
}
i. 刪除用戶
頁面
<%--請求刪除用戶--%>
<form action="${pageContext.request.contextPath}/user/operate/1" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="刪除">
</form>
方法
/**
* 刪除用戶
* @param id
* @return
*/
@RequestMapping(value = "/operate/{id}" , method = RequestMethod.DELETE)
@ResponseBody
public String delById(@PathVariable("id") Integer id){
System.out.println("delById:" + id);
return "show";
}
j, web.xml
<!--開啓另外兩種提交方式:put, delete-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
index.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2020/4/26
Time: 17:45
To change this template use File | Settings | File Templates.
--%>
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>4</title>
</head>
<body>
請求保存用戶(post):
<form action="${pageContext.request.contextPath}/user/save" method="post">
<input type="text" name="id" value="1">
<input type="submit" value="提交">
</form>
findById(get):
<a href="${pageContext.request.contextPath}/user/findById?id=1">findById(get):</a>
<hr>
resful風格提交(4個請求路徑完全一樣,就是提交方式不同導致執行不同方法):<br>
請求保存用戶(post):
<form action="${pageContext.request.contextPath}/user/operate/1" method="post">
<input type="submit" value="保存">
</form>
findById(get):
<a href="${pageContext.request.contextPath}/user/operate/1">findById(get):</a>
<%--1)先在web.xml中開啓put和delete提交方式
2)表單提交方法必須是post
3)表單中必須設置一個隱藏域: name=_method value=PUT
4)請求的方法返回值必須以流的形式返回,即在方法上標記註解:@ResponseBody
--%>
請求更新用戶(put) 先在web.xml中開啓put和delete提交方式:
<form action="${pageContext.request.contextPath}/user/operate/1" method="post">
<input type="hidden" name="_method" value="PUT">
<input type="submit" value="更新">
</form>
請求刪除用戶(delete) 先在web.xml中開啓put和delete提交方式:
<form action="${pageContext.request.contextPath}/user/operate/1" method="post">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="刪除">
</form>
</body>
</html>
web.xml
UserController.java
@Controller
@RequestMapping("/user")
@SessionAttributes({"username","password"})
public class UserController {
//普通寫法
/*@RequestMapping(value = "/findById",method = RequestMethod.GET)
public String findById(Integer id){
System.out.println("findById:"+id);
return "show";
}
@RequestMapping(value = "/save",method = RequestMethod.POST)
public String save(Integer id){
System.out.println("save:"+id);
return "show";
}*/
@RequestMapping(value = "/operate/{idx}",method = RequestMethod.GET)
public String findById(@PathVariable("idx") Integer id){
System.out.println("findById:"+id);
return "show";
}
@RequestMapping(value = "/operate/{id}",method = RequestMethod.POST)
public String save(@PathVariable("id") Integer id){
System.out.println("save:"+id);
return "show";
}
//web.xml中配置新的filter
//更新用戶 put
@RequestMapping(value = "/operate/{id}",method = RequestMethod.PUT)
@ResponseBody
public String update(@PathVariable("id") Integer id){
System.out.println("update:"+id);
return "show";
}
//刪除用戶 delete
@RequestMapping(value = "/operate/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String del(@PathVariable("id") Integer id){
System.out.println("del:"+id);
return "show";
}
}
四、控制器方法的返回值
1、返回值爲void類型
a. 方法一:
@RequestMapping("/testVoid")
public void testVoid(){
System.out.println("測試沒有返回值");
//沒有指定返回值頁面,會自動截取請求路徑,進入視圖解析器(xml內配置的),拼接完整路徑
//1.對應路徑下創建對應jsp /WEB-INF/user/testVoid.jsp
}
b. 方法二:response重定向
@RequestMapping("/testVoid2")
public void testVoid2(HttpServletResponse response){
System.out.println("測試沒有返回值");
//手動重定向
try {
//重定向不能進入WEB-INF 轉發可以進入
response.sendRedirect("/show2.jsp");
} catch (IOException e) {
e.printStackTrace();
}
}
c. 方法三:servlet轉發
@RequestMapping("/testVoid3")
public void testVoid3(HttpServletResponse response, HttpServletRequest request){
System.out.println("測試沒有返回值3");
//手動轉發
try {
request.getRequestDispatcher("/WEB-INF/show.jsp").forward(request,response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
2、返回值爲String類型(常用)
a. 默認的情況:(return 一個路徑)轉發請求,返回值直接進入視圖解析器,拼接前綴和後綴,完整的路徑
//方法返回值爲string
@RequestMapping("/testString")
public String testString(){
System.out.println("返回值string");
return "show";
}
b. 請求重定向
/**
* 可以重定向到一個controller
* eg;save----redirect:findAll
*
* 方法返回值爲string
* 返回值直接進入視圖解析器 拼接前後綴 形成完整路徑
* redirect:添加了redirect後,則是重定向,則不會進入視圖解析器,需要配置完整路徑
*/
@RequestMapping("/testString2")
public String testString2(){
System.out.println("返回值string 重定向");
return "redirect:/show2.jsp";
}
c. 請求轉發 (不進入視圖解析器拼接)
/**
* 不使用視圖解析器轉發(不拼接 直接轉發到寫的路徑)
* forward:轉發 不會進入視圖解析器,需要配置完整的路徑
* @return
*/
@RequestMapping("/testString3")
public String testString3(){
System.out.println("返回值string 不使用視圖解析器轉發");
return "forward:/show2.jsp";
}
3、返回值爲ModelAndView類型(常用 ★ 超級好用)
a. ModelAndView: Model 模型:封裝數據 view 視圖: 指定頁面 ---> 模型和視圖
b. eg:
//返回值類型爲ModelAndView:包含數據和視圖頁面 ★太牛
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
//準備數據 數據庫查詢
List<User> userList=new ArrayList<User>();
User user1 = new User(); user1.setSex("男");user1.setUsername("張三");user1.setId(1);
User user2 = new User(); user2.setSex("女");user2.setUsername("李四");user2.setId(2);
userList.add(user1);userList.add(user2);
ModelAndView modelAndView = new ModelAndView();
//添加數據
modelAndView.addObject("userList",userList);
//指定頁面
modelAndView.setViewName("show");//視圖解析器仍然起作用
return modelAndView;
}
五、交互JSON數據
注意: idea映入壓縮版的min.js時寫$()會報錯(不影響運行) 引入開發版的js就行了
springmvc的前端控制器將所有靜態資源也都攔截了,一定在spring-mvc.xml中放行
<mvc:resources mapping="/js/*" location="/js/"></mvc:resources>
pom.xml裏引入3個json的jar包
1. 引入依賴 pom.xml
<!--引入json依賴 3個jar-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
2. 前端jsp
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>TestJson</title>
<%--web.xml裏前端控制器攔截所有資源 js靜態資源也攔截了 一定要在覈心xml內放行--%>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
</head>
<script type="text/javascript">
//window.οnlοad=function (ev) { alert("hello") }
/*$(function () {
alert("jquery");
$("#btn").click(
function () {
alert("btn click")
}
);
});*/
function excute() {
alert("提交");
$.ajax({
url:"${pageContext.request.contextPath}/user/testRequestJson2",
data:{"username":"張三","age":20},
success:function (data) {
alert(data);
},
dataType:"json",
type:"post"
});
}
</script>
<body>
<input id="btn" type="button" value="提交" onclick="excute()">
</body>
</html>
測試responseBody時改成
function excute() {
alert("提交");
$.ajax({
<%--url:"${pageContext.request.contextPath}/user/testRequestJson2",--%>
url:"${pageContext.request.contextPath}/user/testResponseBody",
/*data:{"username":"zangsan","age":20},*/
success:function (data) {
/*alert(data[0].username);
alert(data[1].username);*/
//直接遍歷 這個方法好記 而且不論data類型如何都可遍歷
$.each(data,function () {
alert(this.username+"|"+this.sex+"|"+this.id);
})
},
dataType:"json",
type:"post"
});
}
3、 @ReqeustBody註解(爛註解 直接參數解析最好)
/**
* 自動解析前端json格式數據 ★★ ★★ 與@ReqeustBody註解無關
*/
@RequestMapping("/testRequestJson")
public void testRequestJson(String username,Integer age){//前端json格式也可以直接幫你封裝到參數裏
System.out.println(username);
System.out.println(age);
}
//所有參數轉換爲一個字符串
@RequestMapping("/testRequestJson2")
public void testRequestJson2(@RequestBody String body){//
System.out.println(body);
//輸出:username=zangsan&age=20
}
4、ResponseBody註解 (★ 一個註解解決json格式轉換問題)
/**
* @ResponseBody註解標記的方法,數據會以流的形式返回(字符串流也就是json格式數據)
* ★ 多好 一個註解就解決了返回json格式轉換的問題 牛★★
* @return
*/
@RequestMapping("/testResponseBody")
@ResponseBody
public List<User> testResponseBody(){
//準備數據 數據庫查詢
List<User> userList=new ArrayList<User>();
User user1 = new User(); user1.setSex("男");user1.setUsername("張三");user1.setId(1);
User user2 = new User(); user2.setSex("女");user2.setUsername("李四");user2.setId(2);
userList.add(user1);userList.add(user2);
return userList;//會自動轉json
}
六、SpringMVC實現文件上傳
1、文件上傳
a、引入依賴
引入fileUpload會自動依賴commons-io
<!--文件上傳依賴-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
b、spring-mvc.xml 配置文件
建議複製 無需記憶
<!-- 配置文件上傳解析器 -->
<!-- id的值是固定的 直接複製 不要記憶-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 設置上傳文件的最大尺寸爲5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
c、頁面配置
<%--上傳文件的表單前提
1) 提交方式必須post (get只能提交少量數據 post提交大量數據)
2) 表單類型必須:enctype="multipart/form-data" 多功能表單數據
3) 必須有一個type=file的表單元素
--%>
<form action="" method="post" enctype="multipart/form-data">
<input type="text" name="username"><br>
<input type="file" name="upload"><br>
<input type="submit" value="上傳">
</form>
d、controller代碼
@RequestMapping("/upload")
public String upload(String username, MultipartFile upload,HttpServletRequest request){
/*System.out.println(username);
System.out.println(upload);*/
//1.目標路徑
//1.1 獲取項目運行的真實路徑(創建子目錄upload)
String realPath = request.getSession().getServletContext().getRealPath("/upload");
System.out.println("真實路徑:"+realPath);
//1.2 判斷路徑是否存在 不存在創建
File realFile=new File(realPath);
if(!realFile.exists()){
realFile.mkdirs();
}
//2.獲取唯一的文件名稱(包含拓展名)
String uuidName= UUID.randomUUID().toString().replace("-","");
//2.1獲取真實文件名
String originalFilename = upload.getOriginalFilename();
System.out.println(originalFilename);
//2.2獲取拓展名
int n = originalFilename.lastIndexOf(".");//找到最後一個點
String extendName = originalFilename.substring(n);//從最後一個.開始往後截取即可 包括.
System.out.println(extendName);//.txt .jpg
//2.3生成唯一文件名
String fileName=uuidName+extendName;
System.out.println("唯一文件名:"+fileName);
//3.文件上傳 非常簡單
//transferTo:執行文件上傳
//參數file:目標文件 路徑+文件名
try {
upload.transferTo(new File(realFile,fileName));//路徑和文件名
} catch (IOException e) {
e.printStackTrace();
}
return "show";
}
2、跨服上傳
a、引入依賴
<!--引入jersey服務器的包 跨服上傳-->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.1</version>
</dependency>
b、修改tomcat配置
1. tomcat默認不能跨服上傳的
2. tomcat/conf/web.xml
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<!--需要添加的-->
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
c、配置圖片服務器
1. 創建一個web項目
2. 配置一個tomcat,與原來tomcat端口號不一致
3. 在新項目的webapp目錄下創建一個upload目錄,空的文件夾不會編譯(否則以上傳就報錯),需要在upload目錄添加(任意)一個文件
d、修改controller代碼
//跨服務器上傳
@RequestMapping("/uploadServer")
public String uploadServer(String username, MultipartFile upload,HttpServletRequest request){
//1.配置圖片服務器路徑
String serverPath="http://localhost:9090/img_server/upload/";
//2.獲取唯一的文件名稱(包含拓展名)
String uuidName= UUID.randomUUID().toString().replace("-","");
//2.1獲取真實文件名
String originalFilename = upload.getOriginalFilename();
//2.2獲取拓展名
int n = originalFilename.lastIndexOf(".");//找到最後一個點
String extendName = originalFilename.substring(n);//從最後一個.開始往後截取即可 包括.
//2.3生成唯一文件名
String fileName=uuidName+extendName;
//3.獲取jersey服務器客戶端
Client client=Client.create();
//配置上傳路徑的資源對象
WebResource resource = client.resource(serverPath + fileName);
//4.上傳
//參數: 資源的類型 文件的字節內容
try {//String.class:字符串路徑
resource.put(String.class, upload.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("上傳完畢!");
return "show";
}
七、SpringMVC的統一異常處理
1. 自定義異常類 (也可以沒有)
CustomerException.java
@Data
public class CustomerException extends Exception {
private String message;
public CustomerException(String message) {
super(message);
this.message = message;
}
}
2. 定義異常的統一處理對象-實現接口HandlerExceptionResolver
(該類只要創建了(存在於容器中) 就會生效 不需要其他多餘的配置)
MyExceptionResolver.java
//創建該類對象就生效了 一旦發生異常就自動轉到這來了
@Component
public class MyExceptionResolver implements HandlerExceptionResolver {
/**
* 解析異常
* @param request
* @param response
* @param handler
* @param e 別處傳過來的異常對象
* @return
*/
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
ModelAndView modelAndView = new ModelAndView();
//添加數據
if(e instanceof CustomerException){//instanceof 實例類型判斷運算符
//若是自定義異常類型
CustomerException customerException= (CustomerException) e;
modelAndView.addObject("message",customerException.getMessage());
}else{
modelAndView.addObject("message","系統錯誤,請聯繫管理員!");
}
//指定跳轉頁面
modelAndView.setViewName("error");//視圖解析器起作用
return modelAndView;
}
}
3. 錯誤頁面
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${message}
</body>
</html>
4、異常測試controller
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/print")
public String print(){
System.out.println(1/0);
return "show";
}
}
八、小結
1. @ModelAttribute ,@SessionAttribute
2. restful
3. 控制器方法的返回值
void :
String :
ModelAndView: 視圖和模型
4. json數據的交互
@RequestBody:
@ResponseBody:
5. 文件上傳: upload.trsansferTo(new File("path"))
6. 跨服上傳文件:
7. 統一處理異常: