Spring mvc 介紹
Spring Web MVC是一種基于Java的實(shí)現(xiàn)了Web MVC設(shè)計(jì)模式的請(qǐng)求驅(qū)動(dòng)類(lèi)型的輕量級(jí)Web框架澳眷,即使用了MVC架構(gòu)模式的思想胡嘿,將web層進(jìn)行職責(zé)解耦,基于請(qǐng)求驅(qū)動(dòng)指的就是使用請(qǐng)求-響應(yīng)模型钳踊,框架的目的就是幫助我們簡(jiǎn)化開(kāi)發(fā)衷敌,Spring Web MVC也是要簡(jiǎn)化我們?nèi)粘eb開(kāi)發(fā)
spring mvc 常用注解詳解
@Controller
在SpringMVC 中,控制器Controller 負(fù)責(zé)處理由DispatcherServlet 分發(fā)的請(qǐng)求拓瞪,它把用戶(hù)請(qǐng)求的數(shù)據(jù)經(jīng)過(guò)業(yè)務(wù)處理層處理之后封裝成一個(gè)Model 缴罗,然后再把該Model 返回給對(duì)應(yīng)的View 進(jìn)行展示。在SpringMVC 中提供了一個(gè)非常簡(jiǎn)便的定義Controller 的方法祭埂,你無(wú)需繼承特定的類(lèi)或?qū)崿F(xiàn)特定的接口面氓,只需使用@Controller 標(biāo)記一個(gè)類(lèi)是Controller ,然后使用@RequestMapping 等一些注解用以定義請(qǐng)求URL 請(qǐng)求和Controller 方法之間的映射蛆橡,這樣的Controller 就能被外界訪問(wèn)到舌界。其標(biāo)記在一個(gè)類(lèi)上,使用它標(biāo)記的類(lèi)就是一個(gè)SpringMVC Controller 對(duì)象泰演。分發(fā)處理器將會(huì)掃描使用了該注解的類(lèi)的方法呻拌,并檢測(cè)該方法是否使用@RequestMapping 注解。@Controller 只是定義了一個(gè)控制器類(lèi)睦焕,而使用@RequestMapping 注解的方法才是真正處理請(qǐng)求的處理器柏锄。此外我們還需要將controller注冊(cè)到spring里
@RequestMapping
RequestMapping是一個(gè)用來(lái)處理請(qǐng)求地址映射的注解,可用于類(lèi)或方法上复亏。用于類(lèi)上趾娃,表示類(lèi)中的所有響應(yīng)請(qǐng)求的方法都是以該地址作為父路徑,作用于方法上缔御,表明該處理器的請(qǐng)求地址=父路徑+方法上url+method抬闷,其擁有6個(gè)屬性
1、 value, method笤成;定義處理器訪問(wèn)的具體體質(zhì)
value: 指定請(qǐng)求的實(shí)際地址评架,指定的地址可以是URI Template 模式;
method: 指定請(qǐng)求的method類(lèi)型炕泳, GET纵诞、POST、PUT培遵、DELETE等浙芙;
2、consumes籽腕,produces 定義處理器內(nèi)容類(lèi)型
consumes: 指定處理請(qǐng)求的提交內(nèi)容類(lèi)型(Content-Type)嗡呼,例如application/json, text/html;
produces: 指定返回的內(nèi)容類(lèi)型,僅當(dāng)request請(qǐng)求頭中的(Accept)類(lèi)型中包含該指定類(lèi)型才返回皇耗;
3南窗、params,headers 定義處理器處理類(lèi)型
params: 指定request中必須包含某些參數(shù)值郎楼,才讓該方法處理万伤!
headers: 指定request中必須包含某些指定的header值,才能讓該方法處理請(qǐng)求呜袁。
@PathVariable
用于將請(qǐng)求URL中的模板變量映射到功能處理方法的參數(shù)上壕翩,即取出uri模板中的變量作為參數(shù)。如:
@Controller
public class TestController {
@RequestMapping(value="/user/{userId}/roles/{roleId}",method = RequestMethod.GET)
public String getLogin(@PathVariable("userId") String userId,
@PathVariable("roleId") String roleId){
System.out.println("取出請(qǐng)求路徑攜帶的參數(shù)->User Id : " + userId);
System.out.println("取出請(qǐng)求路徑攜帶的參數(shù)->Role Id : " + roleId);
return "hello";
}
}
@requestParam
@requestParam主要用于在SpringMVC后臺(tái)控制層獲取參數(shù)傅寡,類(lèi)似一種是request.getParameter("name")放妈,它有三個(gè)常用參數(shù):defaultValue = "0", required = false, value = "isApp";defaultValue 表示設(shè)置默認(rèn)值荐操,required 銅過(guò)boolean設(shè)置是否是必須要傳入的參數(shù)芜抒,value 值表示接受的傳入的參數(shù)類(lèi)型。
@ResponseBody
作用: 該注解用于將Controller的方法返回的對(duì)象托启,通過(guò)適當(dāng)?shù)腍ttpMessageConverter轉(zhuǎn)換為指定格式后宅倒,寫(xiě)入到Response對(duì)象的body數(shù)據(jù)區(qū)。使用時(shí)機(jī):返回的數(shù)據(jù)不是html標(biāo)簽的頁(yè)面屯耸,而是其他某種格式的數(shù)據(jù)時(shí)(如json等)使用拐迁;
@RequestBody
該注解常用來(lái)處理Content-Type: 不是application/x-www-form-urlencoded編碼的內(nèi)容,例如application/json, application/xml等疗绣;它是通過(guò)使用HandlerAdapter 配置的HttpMessageConverters來(lái)解析post data body线召,然后綁定到相應(yīng)的bean上的。
@RequestMapping(value = "/something", method = RequestMethod.PUT)
public void handle(@RequestBody String body, Writer writer) throws IOException {
writer.write(body);
}
spring mvc 攔截器配置
preHandle:預(yù)處理回調(diào)方法多矮,返回值:true表示繼續(xù)流程缓淹,false表示流程中斷(如登錄檢查失敼颉),不會(huì)繼續(xù)續(xù)調(diào)用其他的攔截器或處理器讯壶,此時(shí)我們需要通過(guò)response來(lái)產(chǎn)生響應(yīng)料仗;
postHandle:后處理回調(diào)方法,實(shí)現(xiàn)處理器的后處理(但在渲染視圖之前)伏蚊,此時(shí)我們可以通過(guò)modelAndView(模型和視圖對(duì)象)對(duì)模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理立轧,modelAndView也可能為null。
afterCompletion:整個(gè)請(qǐng)求處理完畢回調(diào)方法躏吊,即在視圖渲染完畢時(shí)回調(diào)氛改,如性能監(jiān)控中我們可以在此記錄結(jié)束時(shí)間并輸出消耗時(shí)間,還可以進(jìn)行一些資源清理颜阐,類(lèi)似于try-catch-finally中的finally,但僅調(diào)用處理器執(zhí)行鏈中preHandle返回true的攔截器的afterCompletion吓肋。
public class Login implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest httpRequest,
HttpServletResponse httpResponse, Object arg2, Exception arg3)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object object) throws Exception {
/*HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;*/
String urlString = request.getRequestURI();
///olForum/forumList.html模擬登錄頁(yè)
if(urlString.endsWith("forumList.html")){
return true;
}
//請(qǐng)求的路徑
String contextPath=request.getContextPath();
/*httpRequest.getRequestDispatcher("/olForum/forumList").forward(httpRequest, httpResponse);*/
/*response.sendRedirect(contextPath+"/olForum/forumList.html");*/
response.sendRedirect(contextPath + "/olForum/forumList.html?login=aaa");
return false;
/*httpResponse.sendRedirect(httpRequest.getContextPath()+"/olForum/forumList.html");
return;*/
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 掃描controller(controller層注入) -->
<context:component-scan base-package="com.bybo.aca.web.controller"/>
<mvc:interceptors>
<!-- 使用bean定義一個(gè)Interceptor凳怨,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請(qǐng)求 -->
<!-- <bean class="com.bybo.aca.web.interceptor.Login"/> -->
<mvc:interceptor>
<!-- 進(jìn)行攔截:/**表示攔截所有controller -->
<mvc:mapping path="/**" />
<!-- 不進(jìn)行攔截 -->
<mvc:exclude-mapping path="/index.html"/>
<bean class="com.bybo.aca.web.interceptor.Login"/>
</mvc:interceptor>
</mvc:interceptors>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/views/" p:suffix=".jsp"/>
</beans>
spring mvc 靜態(tài)資源放問(wèn)配置
<!-- 視圖解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前綴 -->
<property name="prefix" value="/WEB-INF/CraCoreHtml/"></property>
<!-- 后綴 -->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 解決靜態(tài)資源被攔截的問(wèn)題 -->
<mvc:default-servlet-handler/>
spring mvc 文件上傳
<!-- SpringMVC上傳文件時(shí),需要配置MultipartResolver處理器 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8" />
<!-- 指定所上傳文件的總大小,單位字節(jié)是鬼。注意maxUploadSize屬性的限制不是針對(duì)單個(gè)文件肤舞,而是所有文件的容量之和 -->
<property name="maxUploadSize" value="10240000" />
</bean>
前端
<form action="/shop/auth/photoUpload" method="post" enctype="multipart/form-data">
選擇文件:<input type="file" name="file">
<input type="submit" value="上傳">
</form>
后端
@RequestMapping(value = "taskUpload", produces = "text/html;charset=UTF-8", method = RequestMethod.POST)
public ResponseEntity<String> taskUpload(@Validated Task task, HttpServletRequest request) throws Exception {
if (StringUtils.isNotBlank(task.getAnnouncement())) {
String type = task.getType();
return Optional.ofNullable(taskService.saveSelective(task))
.filter((value) -> value > 0)
.map(result -> new ResponseEntity<>(type + "公告發(fā)布成功", HttpStatus.OK))
.orElse(ResponseEntity.status(HttpStatus.NOT_FOUND).body("公告發(fā)布失敗"));
}
File newFile = null;
try {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
request.getSession().getServletContext());
if (request instanceof MultipartHttpServletRequest) {
// 將request變成多部分request
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
Iterator<String> iter = multiRequest.getFileNames();
// 檢查form中是否有enctype="multipart/form-data"
if (multipartResolver.isMultipart(request) && iter.hasNext()) {
// 獲取multiRequest 中所有的文件名
while (iter.hasNext()) {
List<MultipartFile> fileRows = multiRequest.getFiles(iter.next().toString());
if (fileRows != null && fileRows.size() != 0) {
for (MultipartFile file : fileRows) {
if (file != null && !file.isEmpty()) {
// 文件新路徑
String filePath = getFilePath(request, file.getOriginalFilename());
newFile = new File(filePath);
// 寫(xiě)文件到磁盤(pán)
file.transferTo(newFile);
String type = task.getType();
if (newFile.exists()) {
CraFile craFile = new CraFile();
craFile.setFilePath(filePath);
craFile.setFileType(task.getType());
Integer integer = fileService.saveSelective(craFile);
if (integer > 0) {
task.setFileId(craFile.getId());
return Optional.ofNullable(taskService.saveSelective(task))
.filter((value) -> value > 0)
.map(result -> new ResponseEntity<>(type + "上傳成功", HttpStatus.OK))
.orElse(ResponseEntity.status(HttpStatus.NOT_FOUND).body("上傳失敗"));
}
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("上傳失敗");
}
}else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("未能檢測(cè)到上傳文件");
}
}
}
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
if (newFile != null) {
if (newFile.exists()) {
newFile.delete();
}
}
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("上傳失敗");
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("服務(wù)器繁忙");
}
spring mvc 工作流程詳解
1、 用戶(hù)發(fā)送請(qǐng)求至前端控制器DispatcherServlet均蜜。
2李剖、 DispatcherServlet收到請(qǐng)求調(diào)用HandlerMapping處理器映射器。
3囤耳、 處理器映射器找到具體的處理器(可以根據(jù)xml配置篙顺、注解進(jìn)行查找),生成處理器對(duì)象及處理器攔截器(如果有則生成)一并返回給DispatcherServlet充择。
4德玫、 DispatcherServlet調(diào)用HandlerAdapter處理器適配器。
5椎麦、 HandlerAdapter經(jīng)過(guò)適配調(diào)用具體的處理器(Controller宰僧,也叫后端控制器)。
6观挎、 Controller執(zhí)行完成返回ModelAndView琴儿。
7、 HandlerAdapter將controller執(zhí)行結(jié)果ModelAndView返回給DispatcherServlet嘁捷。
8造成、 DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器。
9雄嚣、 ViewReslover解析后返回具體View谜疤。
10、DispatcherServlet根據(jù)View進(jìn)行渲染視圖(即將模型數(shù)據(jù)填充至視圖中)。
11夷磕、 DispatcherServlet響應(yīng)用戶(hù)履肃。