springboot官網:https://spring.io
springboot的使用:eclipse+插件sts、直接官網下載STS編輯器、INteliJ Ide;
***使用STS編輯器開發:配置jdk(環境變量);配置maven(環境變量),在sts中preference-》搜索maven-〉installation-》add添加新的maven,然後打勾的切換一下代替內置的maven,userSeting中設置maven的setting.xml的路徑;
**src/main/resources:
static靜態資源(js css 圖片 音頻 視頻)
templates:模板(模板引擎freemarker,thymeleaf),默認不支持jsp
application.properties:配置文件(相當於application.yml);
可以在application.properties中配置端口;
pom.xml是maven的配置配置文件;
springBoot內置了tomcat,不需要打包成war包;
springBoot將各應用/三方框架設置成一個場景start,用到的時候只需要引入場景即可,springboot自動吧所有依賴全部注入。
在application.properties中加上debug=true執行程序就會吧自動開啓的自動裝配和沒開啓的自動裝配全部打印出來。
自動配置是基於約定的,但在配置文件中可以修改。
springBoot默認只認識兩個配置文件:application.properties和application.yml;這兩個功能一樣;
yml 規定冒號後面的值必須有空格;yml默認可以不寫引號,雙引號中的轉義符會轉義,單引號中不會轉義;
在yml文件中綁定屬性需要在類文件中添加註解@Component @ConfigurationProper(prefix="student"),student是yml文件中的
@Value("name")可以注入屬性值,但是需要在類中每一個屬性前注入;@ConfigurationProper(prefix="student")的優先級高於@value("name"),但是兩者沒有的可以互補。
@propertysource:默認會加載application.properties和application.yml文件,如果不用這兩個文件,就要用PropertySource(value={"classpath:conf.properties"})指定加載。但這種註解只能加載properties文件,不能加載yml。
@ImportResource:spring的配置文件 默認會被spring boot自動配置好;如果自己要寫配置文件,是不會被識別的。這時候就要使用這個註解指定配置文件的路徑,在入口程序的類中寫@ImportResource(locations={"classpath:spring.xml"})。但是不推薦自己寫配置文件,現在流行的是註解配置,創建一個配置類,需要加上@Configuration ,@Bean就相當於配置文件中的<bean>,方法名相當於id。
佔位符表達式::${random.int}隨機數
多環境切換:1.如果要切換,在properties文件中設置spring.profiles.active=test;springboot默認會讀取主配置文件application.properties;application-dev.properties;application-test.properties;
2.可以在yml中配置;
3.動態切換環境:方法一:通過命令行方式:Run Configuration-》argument->program argument下寫命令:--spring.profiles.active=dev;或者同構虛擬機VM設置-Dspring.profiles.active=dev;
配置文件的位置問題:application.properties和application.yml可以存放在以下幾個文件夾中:file:項目根目錄/config、file:項目根目錄、classpath:項目根目錄/config、classpath:項目根目錄。如果有衝突,則優先級從前往後,如果不衝突則互補。
項目外的配置文件:在application.properties中配置項目名,server.serverlet.context-parth=/boot;也可以在項目之外配置:方法是先在外部創建一個application.properties,然後Run Configuration-》argument->program argument下寫命令:--spring.config.location=文件存放的路徑;通過命令行調用外部配置文件:java -jar jar包地址 --spring.config.location=applications.properties的地址。項目運行參數:Run Configuration-》argument->program argument下寫命令:--server.port=8888 ;或者通過命令:java -jar jar包地址 --server.port=8888;
優先級:命令行參數》yml
springBoot日誌處理:日誌框架UCL、JUL、slf4j、logback、log4j;springboot默認支持的有slf4j、logback;
springboot默認幫我們配置好了,直接使用就可以了;
日誌的級別:TRACE<DEBUG<INFO<ERROR<FATAL<OFF
springboot默認的日誌級別是info,只打印info級別只之後的信息,也可以在配置文件中配置日誌級別logging.level.主配置類多所在的包=日誌級別;
吧日誌保存在文件中:要配置logging.file=保存日誌文件的位置,(相對於文件的根路徑),也可以設置絕對路徑.文件夾用logging.path=文件夾位置,並且默認的文件名叫spring.log;
修改日誌的格式:1.日誌顯示在控制檯,logging.pattern.console=%d{yyyy-MM-dd } [%thread] %-5level %logger{50} -%msg %n;2.日誌顯示在文件中,logging.pattern.file=%d{yyyy-MM-dd } [%thread] %-5level %logger{50} -%msg %n。
springboot處理Web靜態資源:
@RequestMapping("/請求的路徑")
請求的時候不需要寫項目名,如果要加項目名需要在配置文件中配置一下。
springboot是一個jar包,靜態資源就不是存放在webapps中,
WebMvcAutoConfiguration類指定靜態資源的存放位置,addResourceHandlers()指定springboot將靜態資源引入靜態資源,從webjars目錄開始,如localhost:8080.webjars/jquery。springboot將這寫靜態資源直接以jar文件的方式引入。spring boot
將一些目錄結構設置成靜態資源存放目錄,靜態資源直接放入這些目錄即可。classpath:/META-INF/resources、classpath:/resources、classpath:/static、classpath:/static。訪問的時候不需要寫前綴,直接寫靜態資源的文件名,就是不需要加resources、static、static。
也可以自己配置靜態資源路徑:spring.resources.static-locations=自定義的位置classpath:/res/,classpath:/myimge/,那麼靜態資源就可以放到自定義的位置了;自定義生效後,以前的約定就不能用了。
添加歡迎頁:welcomPageHandleMapping()---->getIndexHtml()-->location ;任意一個靜態資源目錄中的index.html就一個默認的歡迎頁。網頁標籤的logo是固定名字favicon.ico;吧這個ico文件放到任何一個靜態資源目錄中。
webjars.org網站有引入靜態資源的方式。
模板引擎thymeleaf:動態資源不支持jsp;推薦使用模板引擎;網頁=模板+數據;在maven中添加場景;
thymeleaf的代碼要寫在classpath:/templates/目錄中,只要文件的後置是.html的就可以了。
springBoot整合外置tomcat:如果要整合jsp,只能用war包,所以要需要外置的tomcat;在pom.xml中重新配置tomcat,<scope>provide</scope>;重新建立基本的web項目目錄結構,webapps/WEB-INF,webapps/inde.jsp;跟以前的部署tomcat
一樣。
下載地址:
https://docshome.gitbooks.io/springboot/content/
安裝springboot:https://www.cnblogs.com/sea-stream/p/11601100.html
springBoot=spring(項目管理)+springmvc(控制器)進一步封裝。
約定:src/main/java下面必須要有一個全局的入口類,要放在所有子包之上,Application全局入口類,只能出現一次。
在src/main/resource文件夾下要有application.yml文件,這個是springboot的配置文件。
springboot項目默認沒有應用名,如果需要在yml文件中可以指定應用名。
springboot默認內嵌有tomcat,不需要外部設置tomcat,默認端口8080,可能會衝突,在yml文件中修改。
*****微服務項目******
***MyBatis-Plus:
lombok插件的安裝:https://blog.csdn.net/lsqingfeng/article/details/89842258
lombok可以自動生成set、get、toString方法;使用前要安裝lombok插件,還要在pom.xml中引入。在類中加註解:@Data;
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
插入時自動更新字段:創建一個類實現MetaObjectHandler這個接口。
樂觀鎖:加一個字段version;
邏輯刪除(假刪),物理刪除(真刪除);加一個字段deleted;
條件構造器:在數據庫操作的時候,可以構造條件。
lamda表達式可以提升sql語句的優先級。
代碼生成器;
@RestController:相當於@Responsbody+@Controller;返回值都是jason;
****數據庫設計
數據庫優化的主要方式:sql優化,數據庫設計。
數據庫優化:微服務中分庫設計;分表(橫向分表:(id策略、hash id)主要解決單表數量過大的問題,縱向分表:()解決單表列多的問題,單列內容過多的問題,提升查詢效率);設計冗餘列:避免過多的表關聯;
58到家軍規,沈劍;阿里巴巴開發手冊;
dependencyManageement版本管理;dependency依賴;
跨域:瀏覽器從一個域名的網頁去請求另一個域名的資源,域名、端口、協議任何一個不一樣都是跨域。
跨域的解決方案:在Controller類上直接加上@CrossOrigin;
swagger配置文件:生成api;swaager訪問地址:http://localhost:8888/demo/swagger-ui.html demo是自己配置的路徑,默認的是http://localhost:8888/swagger-ui.html,端口是自己的。
有時候不讓訪問會彈出一個框提示一大段文字Unable to infer base url.。。。。。,在啓動類中加入@EnableSwagger2註解;
統一返回數據格式;sucess,code,message,data。
***配置日誌https://www.cnblogs.com/bigben0123/p/7895696.html
默認級別是INFO;application.properties中配置日誌級別:logging.level.root=WARN;
在resources包中創建logback-spring.xml就會自動被讀取到,這樣就不需要在application.properties中配置日誌級別了;
logback系統日誌的配置:安裝彩色日誌插件:grep-console;
默認的命名規則,並且放在 src/main/resources下;
如果你即想完全掌控日誌配置,但又不想用 logback.xml 作爲 Logback 配置的名字, application.yml 可以通過 logging.config 屬性指定自定義的名字:
logging.config=classpath:logging-config.xml
雖然一般並不需要改變配置文件的名字,但是如果你想針對不同運行時 Profile 使用不同的日誌配置,這個功能會很有用。
一般不需要這個屬性,而是直接在 logback-spring.xml 中使用 springProfile 配置,不需要 logging.config 指定不同環境使用不同配置文件。 springProfile 配置在下面介紹。
根節點包含的屬性:
scan:當此屬性設置爲 true 時,配置文件如果發生改變,將會被重新加載,默認值爲 true 。
scanPeriod:設置監測配置文件是否有修改的時間間隔,如果沒有給出時間單位,默認單位是毫秒。當 scan 爲 true 時,此屬性生效。默認的時間間隔爲1分鐘。
debug:當此屬性設置爲 true 時,將打印出 logback 內部日誌信息,實時查看 logback 運行狀態。默認值爲 false 。
根節點 <configuration> 有5個子節點:
子節點一 <root>
root節點是必選節點,用來指定最基礎的日誌輸出級別,只有一個level屬性。
level:用來設置打印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能設置爲INHERITED或者同義詞NULL。默認是DEBUG。
可以包含零個或多個元素,標識這個appender將會添加到這個loger。
子節點二: <contextName> 設置上下文名稱
每個logger都關聯到logger上下文,默認上下文名稱爲“default”。但可以使用設置成其他名字,用於區分不同應用程序的記錄。一旦設置,不能修改,可以通過 %contextName 來打印日誌上下文名稱,一般來說我們不用這個屬性,可有可無。
<contextName>logback</contextName>
子節點三: <property> 設置變量
用來定義變量值的標籤, 有兩個屬性,name和value;其中name的值是變量的名稱,value的值時變量定義的值。通過定義的值會被插入到logger上下文中。定義變量後,可以使“${}”來使用變量。
子節點四: <appender>
appender用來格式化日誌輸出節點,有倆個屬性name和class,class用來指定哪種輸出策略,常用就是控制檯輸出策略和文件輸出策略。
可以看到 layout 和 encoder ,都可以將事件轉換爲格式化後的日誌記錄,但是控制檯輸出使用 layout ,文件輸出使用 encoder 。
***springboot中的註解
@SpringBootAplication 標識入口類,將其所在包和其子包全部裝入spring容器中。只能出現一次。這個註解是許多個註解組合而成的。等價於@SpringBootConfiguration(標誌註解,標誌這是入口類)、@EnableAutoConfigration(核心註解,自動配置spring以及引入的第三方技術)、@ComponentScan(組件掃描註解,默認掃描秒入口類所在的包,以及他的子包)
元註解:就是修飾註解的註解,@Doucment、@Inherited、@Retention(指定註解的生效時機)、@Target(指定註解的修飾範)圍。
application中main函數的作用:啓動內嵌tomcat服務器,
springapplication.run(application.class,args)參數一:入口類的對象,目的是讓@EnableAutoConfigration自動配置print時將@ComponentScan掃描到註解創建對象一併放入工廠。參數二是main函數的參數,這個參數通過指定外部虛擬機參數形式覆蓋應用內部默認參數。
@RestController (相當於@controller和@responseBody的結合)用在類上,所有的控制器上,作用是將類中所有控制器方法的返回值轉換爲json並響應到前端。
@controller 表示控制器
@responseBody 將返回值轉換成json
***配置文件拆分:
將公共配置防止主配置文件中,將不同配置文件中放入不同環境的配置文件中;application.yml公共(在主配置文件中要激活響應的配置文件,spring:profiles:active:dev或者prod) application-dev.yml 開發 application-prod.yml 生產
SpringBoot banner:創建一個banner.txt
***spirng boot工廠特性之創建對象
單個自定義對象:@Component通用組件對象註解 @Service業務層註解 @Controller控制器註解 @Repository創建DAO組件
一次性創建多個組件對象把汗複雜對象:@Configuration 配置註解 修飾範圍:用在類上,作用相當於以前的spring.xml配置文件,管理對象的創建。
@Bean 相當於spring.xml中的Bean標籤,用來創建這個對象在工廠的一個實例。
@PathVariable是spring3.0的一個新功能:接收請求路徑中佔位符的值;通過 @PathVariable 可以將URL中佔位符參數{xxx}綁定到處理器類的方法形參中@PathVariable(“xxx“)
****springboot獲取前端參數的幾種常用註解
獲取參數的幾種常用註解:https://blog.csdn.net/qq_20957669/article/details/89227840
@PathVariable:一般我們使用URI template樣式映射使用,即url/{param}這種形式,也就是一般我們使用的GET,DELETE,PUT方法會使用到的,我們可以獲取URL後所跟的參數。
@RequestParam:一般我們使用該註解來獲取多個參數,在()內寫入需要獲取參數的參數名即可,一般在PUT,POST中比較常用。
@RequestBody:該註解和@RequestParam殊途同歸,我們使用該註解將所有參數轉換,在代碼部分在一個個取出來,也是目前我使用到最多的註解來獲取參數
@RequestHeader來獲取頭信息裏的值,
@CookieValue來獲取Cookie值。
@RequestHeader("mytoken")獲取請求頭中的mytoken信息。
******前後段發送和接收參數的方式
1.@RequestBody不能接受get請求, 請求頭需要指定爲json類型;
2.@RequestParam註解,默認會校驗入參,如果請求不帶入參則會報錯,可以通過設置屬性required=false解決,例如: @RequestParam(value="username", required=false) ,這樣就不會校驗入參;
注意:@RequestParam只能接收的請求頭格式爲:application/x-www-form-urlencoded
,post傳參的默認格式是json格式,所以纔會一直報錯。將json對象序列化爲URL形式的字符串,可以解決。
4.通過一個bean來接收,適用於GET 和 POST請求方式
5.通過HttpServletRequest接收,適用於GET 和 POST請求方式
6.使用@ModelAttribute註解獲取參數,適用於POST請求
7.直接接收參數,必須是GET請求;
8.HttpServletRequest request方式接收參數;
注意:使用post的時候,springcloud項目中使用request.getparameter讀取參數爲空
原因:使用@restcontroller導致,之前爲@controller。而通過requestbody註解封裝爲對象會自動映射參數。用httpServletRequest.getParameter接收post請求參數,發送端content Type必須設置爲application/x-www-form-urlencoded,否則接收不到;
/**
* application/x-www-form-urlencoded通過表單提交,在sevlet實現中,
* mutipart/form-data和application/x-www-form-urlencoded會被特殊處理,
* 請求參數將被放置於request.paramter,這是一個map。我們可以從map中獲取參數進行驗證,
* 或者其他攔截需求,map的獲取類似hibernate的延遲加載,當調用request.getparamter()方法,
* servlet纔會從請求流中讀取請求參數加載入map。InputStream也會存有這份數據,但如果這份數據被讀取,
* 那麼到了controller層將無法讀出數據,同樣,攔截之後到達controller層時請求數據已經被加載入了controller層方法實參,
* 實參對象需要有set方法,框架會以反射的方式調用屬性的set方法注入數據,數據只會被注入到已有的屬性。
* 當我們的content-type是application/x-www-form-urlencoded的時候,
* 前臺傳遞的參數是可以傳到後臺的@RequestParam和request.getParameter都可以,事實上,這兩種都是一樣的,
* 但是當我再前臺設置的content-type是application/json的時候,後臺就無法接收到參數,兩種都不行。
* 如果是二進制數據傳輸,像文件上傳等,需要設置content-Type multipart/form-data.
* */
***方式一 POST map接接收
// 發起登錄請求
this.$http.post('/login',{username:"lambo",password:"12345678"})
後端:
@RequestMapping("/login")
public R login(@RequestBody Map<String, String> person) { }
***方式二 POST person對象接收
loginform:{
username:'lambo000',
password:'12345678'
}
// 發起登錄請求
async login(){
var info=await this.$http.post('/login',this.loginform);
console.log(info);
}
@Data//自動生成get、set等方法
public class Person {
String username;
String password;
}
//這個一般用於前端傳遞的參數是json格式,這裏用Person對象接收參數
//@RequestHeader("mytoken")這個是從前臺獲取header中的參數
//注意這裏的Person參數前面不需要要加@RequestBody;當使用map接收參數的時候,需要加@RequestBody;
// @RequestMapping("/login")
// public User login( Person person,@RequestHeader("mytoken") String mytoken) {
//
// User user=new User();
// user.setAge(18);
// user.setName("lambo");
// System.out.println("username is:"+mytoken);
// System.out.println("username is:"+person.getUsername());
// return user;
//
// }
***方式三 GET
請求localhost:8888/demo/1/3
後臺接收url拼接的參數
@GetMapping("{page}/{limit}")
public R pageList(
@ApiParam(name="page",value="當前頁碼",required=true)
@PathVariable Long page,//將路徑中的佔位符映射到本處理器的方法中
@ApiParam(name="limit",value="每頁記錄數",required=true)
@PathVariable Long limit
){
Page<Teacher>pageParam=new Page<>(page,limit);
teacherService.page(pageParam,null);
List<Teacher> records=pageParam.getRecords();
long total=pageParam.getTotal();
return R.ok().data("total",total).data("rows",records);
}
***方式四 GET 或者POST 但是post前端傳參數要注意轉換成json字符串
quereyInfo:{
query:'ww',
pagenum:1,
pagesize:2
},
發起請求
async getUserlist(){
const rest=await this.$http.get('userlist',{params:this.quereyInfo})
console.log(rest.data.userlist)
}
後臺:
@RequestMapping("/userlist")
public R userlist(@RequestParam("query") String query) {
System.out.println("參數"+query);
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age", 18);
List<User> users=userMapper.selectList(queryWrapper);
return R.ok().data("userlist",users);
}
***方式五 POST 後臺用字符串接收,然後用JSONObject把字符串轉換成JSON對象;
請求:
const rest=await this.$http.post('userlist',{params:this.quereyInfo})
後臺:
@RequestMapping("/userlist")
public R userlist(@RequestBody String data) {
JSONObject jsonObject=JSONObject.fromObject(data);
System.out.println(jsonObject.get("params"));//獲取具體的參數
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age", 18);
List<User> users=userMapper.selectList(queryWrapper);
return R.ok().data("userlist",users);
}
注意:讀取字符串正常,解析的時候出錯的解決辦法:要把接收到的字符串處理成標準的json字符串格式。
public R selectUser0(@RequestBody String jsonObject) {
int i = jsonObject.indexOf("{");
jsonObject = jsonObject.substring(i);
JSONObject da=JSONObject.fromObject(jsonObject.trim());
System.out.println(da);
JSONObject js= da.getJSONObject("params");
String id= js.getString("id");
Long ids=Long.valueOf(id);
User user = userMapper.selectById(ids);
return R.ok().data("selectById",user);
}
或者直接用JSONObject接收也行;
public R userlist( HttpServletRequest request,@RequestBody JSONObject jsonObject) {
JSONObject js=(JSONObject) jsonObject.get("params");
String nameStr=js.getString("name")
System.out.println("更新"+jsonObject.get("params")+" ");
return R.ok().data("userlist","");
}
***方式六 GET 參數要以拼接的形式發送
發送請求:
quereyInfo:{
query:'wwss',
pagenum:1,
pagesize:3
},
const rest=await this.$http.get('userlist',{params:this.quereyInfo});
或者
const rest=await this.$http.get('userlist?query=qq&pagenum=1&pagesize=3')
後臺:
@RequestMapping("/userlist")
public R userlist(String query,String pagenum, String pagesize) {
System.out.println("傳過來的參數"+query+pagenum+pagesize);
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age", 18);
List<User> users=userMapper.selectList(queryWrapper);
return R.ok().data("userlist",users);
}
***方式七 GET POST
發送請求:
quereyInfo:{
query:'wwss',
pagenum:1,
pagesize:3
},
const rest=await this.$http.get('userlist',{params:this.quereyInfo});
注意:使用post請求的時候要加入{headers: {
'Content-type': 'application/json;charset=UTF-8'
}},{headers: {
'Content-type': 'application/application/x-www-form-urlencoded;charset=UTF-8'
}}否則後臺收到的數據爲null;
const res=await this.$http.post("editorUserbyid",{headers: {
'Content-type': 'application/json;charset=UTF-8'
}},{params:{id:1,name:this.editForm.name,age:this.editForm.age}})
後臺:
@RequestMapping("/userlist")
public R userlist(HttpServletRequest request) {
String query=request.getParameter("query");
String pagenum=request.getParameter("pagenum");
String pagesize=request.getParameter("pagesize");
System.out.println("傳過來的參數"+query+pagenum+pagesize);
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age", 18);
List<User> users=userMapper.selectList(queryWrapper);
return R.ok().data("userlist",users);
}
***圖片上傳前後端示意:
圖片上傳前端可以採用兩種方式:
- formData
- base64
*elementui上傳
相關屬性說明:https://segmentfault.com/a/1190000017297187?utm_source=tag-newest
1、action變量爲後端圖片接口的地址
2、beforeUpload方法是指的上傳之前觸發的函數,可以用來做前端文件格式判斷,文件大小判斷
3、on-change方法是指每次選擇文件都會觸發函數,可以用來前端刪除和添加照片
4、list-type屬性指的是照片picture-card展示的方式
5、name指的是上傳的文件字段名,這是後端確認文件流的字段名,可以隨便寫
6、data屬性指的是上傳時附帶的額外參數,這是指的其他參數
7、limit屬性指的是上傳文件的個數極限。
8、multiple屬性指的是可以每次多選文件,true爲多選,false爲單選
9、auto-upload屬性指的是自動上傳的,true爲可以自動上傳,false爲不可以自動上傳
10、on-preview方法指的是查看縮略圖的方法
11、on-remove方法指的是刪除文件的方法
12、ref綁定dom元素
<el-upload multipart class="upload-demo"
:multiple="true"
action="http://localhost:8889/demo/uploadimage" 請求的後臺地址
:on-preview="handlePreview"
:on-remove="handleRemove"
:file-list="filelists"
list-type="picture" 列表顯示的類型
:headers="headerObj" //圖片上傳組件的請求頭
ref="uploadref" //當前el-upload引用
:before-upload="beforeAvatarUpload"
:on-change="fileChange" //文件列表發生變化時調用
name="files"//這個是要傳的文件,和後臺對應@RequestParam("files") MultipartFile[] file
:data="externaldata" //額外傳遞的參數,後臺用@RequestParam Map<String,String> map接收
:auto-upload="false" //關閉自動上傳,改爲人爲上傳
>
<el-button size="small" type="primary">選取圖片</el-button>
<div slot="tip" class="el-upload__tip">只能上傳jpg/png文件,且不超過 500kb</div>
</el-upload>
<el-button size="small" type="primary" @click="uploadsubmit">點擊上傳</el-button>
<script type="text/javascript">
export default{
data(){
return {
externaldata: { age: 11 },}
},
created(){
},
methods:{
}
}
</script>
spring 後臺代碼接收elemnetui上傳的圖片文件和其他數據:
//上傳圖片----elementui傳遞的數據
@RequestMapping("/uploadimage")
// @ResponseBody
public R uploadimage(@RequestParam Map<String,String> map,@RequestParam("files") MultipartFile[] file,HttpServletRequest request) {
// /Users/HaokeMaster/Desktop/ncimage
try{
String age = map.get("age").toString();
System.out.println("額外的參數"+age);
}catch (Exception e){
}
MultipartFile fil=file[0];
if (fil.isEmpty()) {
System.out.println("文件爲空空");
}
String fileName = fil.getOriginalFilename(); // 文件名
String suffixName = fileName.substring(fileName.lastIndexOf(".")); // 後綴名
String filePath = "/Users/HaokeMaster/Desktop/ncimage/"; // 上傳後的路徑
fileName = UUID.randomUUID() + suffixName; // 新文件名
//創建新文件夾
File dest = new File(filePath + fileName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
fil.transferTo(dest);//把文件流保存到目標文件夾
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("上傳圖片傳過來的參數"+file+fileName);
//這裏還要把接收到文件新的存儲路徑存到數據庫表中
return R.ok().data("goodslist",1);
}
********elementui通過http-request覆蓋原來的上傳邏輯,用new FormData()攜帶數據;
<el-upload multipart class="upload-demo" :multiple="true" :on-preview="handlePreview" :on-remove="handleRemove" :file-list="filelists" list-type="picture" :headers="headerObj" ref="uploadref" :before-upload="beforeAvatarUpload" :on-change="fileChange" name="files" :data="externaldata" :auto-upload="false"
:http-request="uploadformdatafile" //覆蓋原來的上傳邏輯
>
<el-button size="small" type="primary">選取圖片</el-button>
<div slot="tip" class="el-upload__tip">只能上傳jpg/png文件,且不超過500kb</div>
</el-upload>
<el-button size="small" type="primary" @click="uploadsubmit">點擊上傳</el-button>
fileChange(file){
//當文件發生變化時執行此方法
console.log(file)
},
//提交請求
async uploadsubmit(file) {
console.log(file)
this.$refs.uploadref.submit();
},
//http-request覆蓋原來的請求邏輯
uploadformdatafile(params){
console.log(params.file)
let formData = new FormData();
// 向 formData 對象中添加文件
formData.append('file',params.file);
formData.append('age',11);
this.$http.post('uploadimage',formData,{headers:{'Content-type':'multipart/form-data'}})
},
springboot後臺:
//上傳圖片----使用formdata傳遞的數據
@RequestMapping("/uploadimage")
// @ResponseBody
public R uploadimage(@RequestParam Map<String,String> map,@RequestParam("files") MultipartFile[] file,HttpServletRequest request) {
// /Users/HaokeMaster/Desktop/ncimage
//獲取文件以外的數據
MultipartHttpServletRequest params=((MultipartHttpServletRequest) request);
String age=params.getParameter("age");
//獲取文件數據
List<MultipartFile> files = ((MultipartHttpServletRequest) request)
.getFiles("file");
MultipartFile fil = null;
BufferedOutputStream stream = null;
for (int i = 0; i < files.size(); ++i) {
fil = files.get(i);
String fileName = fil.getOriginalFilename(); // 文件名
String suffixName = fileName.substring(fileName.lastIndexOf(".")); // 後綴名
String filePath = "/Users/HaokeMaster/Desktop/ncimage/"; // 上傳後的路徑
fileName = UUID.randomUUID() + suffixName; // 新文件名
File dest = new File(filePath + fileName);//存儲文件的路徑
if (!fil.isEmpty()) {
try {
byte[] bytes = fil.getBytes();
stream = new BufferedOutputStream(new FileOutputStream(dest));
stream.write(bytes);
stream.close();
} catch (Exception e) {
stream = null;
}
} else {
}
}
System.out.println("上傳圖片傳過來的參數"+file+"其他參數"+age);
//這裏還要把接收到文件新的存儲路徑存到數據庫表中
return R.ok().data("goodslist",1);
}
*原始的input框上傳圖片
前端:
<form action="http://localhost:8889/demo/uploadimage" method="post" enctype="multipart/form-data">
<label>上傳圖片</label>
<input type="file" name="file"/>
<input type="submit" value="上傳"/>
</form>
方式一:springboot後臺代碼fil.transferTo(dest)的方式吧接收的流文件存儲到目標文件夾,
//上傳圖片
@RequestMapping("/uploadimage")
// @ResponseBody
public R uploadimage(@RequestParam Map<String,String> map,@RequestParam("file") MultipartFile[] file,HttpServletRequest request) {
// /Users/HaokeMaster/Desktop/ncimage
MultipartFile fil=file[0];
if (fil.isEmpty()) {
System.out.println("文件爲空空");
}
String fileName = fil.getOriginalFilename(); // 文件名
String suffixName = fileName.substring(fileName.lastIndexOf(".")); // 後綴名
String filePath = "/Users/HaokeMaster/Desktop/ncimage/"; // 上傳後的路徑,這裏舉例子上傳到本地的一個文件夾,實際運用中數據庫存路徑,實體數據存到服務器上的文件夾中
fileName = UUID.randomUUID() + suffixName; // 新文件名
//創建新文件夾
File dest = new File(filePath + fileName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
fil.transferTo(dest);//把文件流保存到目標文件夾
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("上傳圖片傳過來的參數"+file);
//這裏還要把文件的接收的文件存儲路徑保存到數據庫表中
return R.ok().data("goodslist",fileName);
}
方式二:springboot後臺用MultipartFile接收流文件並存儲到指定路徑,
//上傳圖片----base64上傳
@RequestMapping("/uploadimage")
// @ResponseBody
public R uploadimage(@RequestParam Map<String,String> map,@RequestParam("file") MultipartFile[] file,HttpServletRequest request) {
// /Users/HaokeMaster/Desktop/ncimage/
MultipartFile fil=file[0];
String fileName = fil.getOriginalFilename(); // 文件名
String suffixName = fileName.substring(fileName.lastIndexOf(".")); // 後綴名
String filePath = "/Users/HaokeMaster/Desktop/ncimage/"; // 上傳後的路徑
fileName = UUID.randomUUID() + suffixName; // 新文件名
File dest = new File(filePath + fileName);//存儲文件的路徑
if (!fil.isEmpty()) {
System.out.println("文件爲空空");
}
try {
//把fil寫入到指定路徑
BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream(dest));
out.write(fil.getBytes());
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("上傳圖片傳過來的參數"+file);
//這裏還要把接收到文件新的存儲路徑存到數據庫表中
return R.ok().data("goodslist",filePath + fileName);
}
方式三:用httprequest接收流
<form action="http://localhost:8889/demo/uploadimage" method="post" enctype="multipart/form-data" mutiple="multiple">
<label>上傳圖片</label>
<input type="file" name="file"/>
<input type="file" name="file"/>
<input type="submit" value="上傳"/>
</form>
//上傳圖片----表單文件上傳多文件
@RequestMapping("/uploadimage")
// @ResponseBody
public R uploadimage(HttpServletRequest request) {
// /Users/HaokeMaster/Desktop/ncimage
MultipartHttpServletRequest params=((MultipartHttpServletRequest) request);
List<MultipartFile> files = ((MultipartHttpServletRequest) request)
.getFiles("file");
// String name=params.getParameter("name");
// System.out.println("name:"+name);
// String id=params.getParameter("id");
// System.out.println("id:"+id);
System.out.println("傳過來的"+files.get(0).getOriginalFilename());
MultipartFile file = null;
BufferedOutputStream stream = null;
for (int i = 0; i < files.size(); ++i) {
file = files.get(i);
String fileName = file.getOriginalFilename(); // 文件名
String suffixName = fileName.substring(fileName.lastIndexOf(".")); // 後綴名
String filePath = "/Users/HaokeMaster/Desktop/ncimage/"; // 上傳後的路徑
fileName = UUID.randomUUID() + suffixName; // 新文件名
File dest = new File(filePath + fileName);//存儲文件的路徑
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
stream = new BufferedOutputStream(new FileOutputStream(dest));
stream.write(bytes);
stream.close();
} catch (Exception e) {
stream = null;
}
} else {
}
}
//這裏還要把接收到文件新的存儲路徑存到數據庫表中
return R.ok().data("goodslist",1);
}
方式四:springboot接收base64數據;
前端把文件數據轉成base64方法一:
<form> <input type="file" id="myImage" name="myImage"/>
<input type="button" οnclick="uploadFile();" value="上傳">
</form>
//通過FileReader.readAsDataURL獲取base64數據
function uploadFile(file){
var f = document.getElementById("myImage").files[0];
var reader = new FileReader(); //新建一個FileReader
reader.readAsDataURL(f); // 讀取文件base64數據
reader.onload = function(e){ //數據讀取完成產生onload事件
var data = e.target.result; //獲取數據
if (data.lastIndexOf('data:base64') != -1) {
data = data.replace('data:base64', 'data:image/jpeg;base64');
} else if (data.lastIndexOf('data:,') != -1) {
data = data.replace('data:,', 'data:image/jpeg;base64,');
}
if(isCanvasSupported()){
//這裏是上傳,發送網絡請求
}else{
alert("您的瀏覽器不支持");
}
};
reader.onerror = function(){
console.log("上傳失敗了 ");
}
}
可以使用 canvas的toDataUrl轉換成base64編碼的圖片數據進行上傳,具體獲取方式如下:
<canvas id="mycanvas"></canvas>
<img src="" id="img">
// 調用 convertImageToBase64(image的路徑地址)
function convertImageToBase64(image的路徑地址) {
var imgObj = new Image();
// 先設置圖片跨域屬性
imgObj.setAttribute("crossOrigin",'anonymous')
// 再給image賦值src屬性,先後順序不能顛倒
imgObj.src = image;
// 當圖片加載完成後,繪製圖片到canvas
imgObj.onload = function () {
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
//上面沒有canvas元素的話這裏也可以創建一個
// let canvas = document.createElement('canvas')
// 設置canvas寬高等於圖片實際寬高
canvas.width = this.width;
canvas.height = this.height;
ctx.drawImage(this, 0, 0);//這裏的this指的是當前imgObj對象
// 將圖片轉成base64格式
var img = canvas.toDataURL("image/jpeg", 0.5); // toDataUrl可以接收2個參數,參數一:圖片類型,參數二: 圖片質量0-1(不傳默認爲0.92)
document.getElementById('img').setAttribute("src", img) // 將base64格式圖片顯示到頁面上
}
}
springboot後臺接收base64字符串並解析:
//上傳圖片----接收base64字符串
@RequestMapping("/uploadimage")
// @ResponseBody
public R uploadimage(String base64Data) {
// /Users/HaokeMaster/Desktop/ncimage
String dataPrix = ""; //base64格式前頭
String data = "";//實體部分數據
if(base64Data==null||"".equals(base64Data)){
//數據爲空
}else {
String [] d = base64Data.split("base64,");//將字符串分成數組
if(d != null && d.length == 2){
dataPrix = d[0];
data = d[1];
}else {
// "上傳失敗,數據不合法","401"
}
}
String suffix = "";//圖片後綴,用以識別哪種格式數據
//data:image/jpeg;base64,base64編碼的jpeg圖片數據
if("data:image/jpeg;".equalsIgnoreCase(dataPrix)){
suffix = ".jpg";
}else if("data:image/x-icon;".equalsIgnoreCase(dataPrix)){
//data:image/x-icon;base64,base64編碼的icon圖片數據
suffix = ".ico";
}else if("data:image/gif;".equalsIgnoreCase(dataPrix)){
//data:image/gif;base64,base64編碼的gif圖片數據
suffix = ".gif";
}else if("data:image/png;".equalsIgnoreCase(dataPrix)){
//data:image/png;base64,base64編碼的png圖片數據
suffix = ".png";
}else {
}
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String tempFileName=uuid+suffix;
String imgFilePath = "/Users/HaokeMaster/Desktop/ncimage/"+tempFileName;//新生成的圖片
// BASE64Decoder decoder = new BASE64Decoder();//base64解析,這個需要導入框架
// byte[] b = decoder.decodeBuffer(data);
try {
//Base64解碼
byte[] b = Base64Utils.decodeFromString(data);//spring自帶的base64解析
for(int i=0;i<b.length;++i) {
if(b[i]<0) {
//調整異常數據
b[i]+=256;
}
}
OutputStream out = new FileOutputStream(imgFilePath);
out.write(b);
out.flush();
out.close();
}catch (Exception e) {
}
//這裏還要把接收到文件新的存儲路徑存到數據庫表中
return R.ok().data("goodslist",1);
}
方式五:前端傳遞的是new Formdata()類型的數據;
<form >
<label>上傳圖片</label>
<input type="file" @change="getFile($event)" name="files" />
<input type="file" @change="getFile1($event)" name="file1" />
<input type="submit" value="上傳" />
<button @click="submit($event)">提交</button>
</form>
<script type="text/javascript">
export default{
data(){
return {
file:{}//存儲上傳的文件數據
}
},
created(){
},
methods:{
}
}
</script>
//獲取上傳的文件
getFile(event) {
this.file = event.target.files[0];//這是取的第一個文件
console.log(this.file);
},
//提交發送給後臺
async submit(event) {
console.log(this.file)
event.preventDefault();//取消默認行爲
//創建 formData 對象
let formData = new FormData();
// 向 formData 對象中添加文件
formData.append('file',this.file);//文件數據
formData.append('age',11);//其他數據
發送請求的方法一:
// this.$http.post("uploadimage", formData)
// .then(function(reh){
// console.log('rehsdddddd===>>>', reh);
// })
// .catch(function(err){
// console.log('err=ssss=>>', err);
// })
發送請求的方法二:
const rest = await this.$http.post('uploadimage',formData)
},
springboot後臺:
//上傳圖片----使用formdata傳遞的數據
@RequestMapping("/uploadimage")
// @ResponseBody
public R uploadimage(@RequestParam Map<String,String> map,@RequestParam("files") MultipartFile[] file,HttpServletRequest request) {
// /Users/HaokeMaster/Desktop/ncimage
//獲取文件以外的數據
MultipartHttpServletRequest params=((MultipartHttpServletRequest) request);
String age=params.getParameter("age");
//獲取文件數據
List<MultipartFile> files = ((MultipartHttpServletRequest) request)
.getFiles("file");
MultipartFile fil = null;
BufferedOutputStream stream = null;
for (int i = 0; i < files.size(); ++i) {
fil = files.get(i);
String fileName = fil.getOriginalFilename(); // 文件名
String suffixName = fileName.substring(fileName.lastIndexOf(".")); // 後綴名
String filePath = "/Users/HaokeMaster/Desktop/ncimage/"; // 上傳後的路徑
fileName = UUID.randomUUID() + suffixName; // 新文件名
File dest = new File(filePath + fileName);//存儲文件的路徑
if (!fil.isEmpty()) {
try {
byte[] bytes = fil.getBytes();
stream = new BufferedOutputStream(new FileOutputStream(dest));
stream.write(bytes);
stream.close();
} catch (Exception e) {
stream = null;
}
} else {
}
}
System.out.println("上傳圖片傳過來的參數"+file+"其他參數"+age);
//這裏還要把接收到文件新的存儲路徑存到數據庫表中
return R.ok().data("goodslist",1);
}
***視頻上傳和圖片上傳是一個道理,
springboot中上傳文件大小限制:在application.properties中加入:
#單個文件最大大小
spring.servlet.multipart.max-file-size=200MB
#所有上傳文件最大大小
spring.servlet.multipart.max-request-size=200MB