創(chuàng)建web初始化類
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
//創(chuàng)建spring容器
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
//創(chuàng)建springMvc容器
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
//配置前端控制器的攔截路徑
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
配置編碼過濾器,解決中文亂碼問題
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
// characterEncodingFilter.setForceResponseEncoding(true);
return new Filter[]{characterEncodingFilter};
}
關(guān)于請(qǐng)求參數(shù)與控制器方法參數(shù)
1.請(qǐng)求參數(shù)與控制器方法參數(shù)一致時(shí),可以直接使用
http://localhost:8080/requestParam1?username=jack&age=18
@RequestMapping("/requestParam1")
@ResponseBody
public String add(String username,Integer age){
System.out.println("username = " + username);
System.out.println("age = " + age);
return "{'"+username+"':'"+age+"'}";
}
2.請(qǐng)求參數(shù)與控制器方法參數(shù)不一致時(shí),需要用注解@RequestParam標(biāo)識(shí)映射關(guān)系
@RequestParam注解的屬性:
- required 為true時(shí),要求請(qǐng)求必須攜帶此參數(shù)
- default 若請(qǐng)求中沒有攜帶此參數(shù),那自動(dòng)賦上默認(rèn)值
http://localhost:8080/requestParam2?name=jack&age=18
@RequestMapping("/requestParam2")
@ResponseBody
public String testParam2(@RequestParam("name") String username, Integer age){
System.out.println("username = " + username);
System.out.println("age = " + age);
return "{'"+username+"':'"+age+"'}";
}
3.當(dāng)控制器方法參數(shù)為實(shí)體類,請(qǐng)求參數(shù)與實(shí)體類屬性一致時(shí),會(huì)自動(dòng)映射
http://localhost:8080/requestParam2?name=武志偉&age=18
@RequestMapping("/requestParam3")
@ResponseBody
public String testParam3(User user){
System.out.println("username = " + user.getName());
System.out.println("age = " + user.getAge());
return "{'"+user.getName()+"':'"+user.getAge()+"'}";
}
4.當(dāng)控制器方法參數(shù)為實(shí)體類,且屬性中有其他引用類型的情況,請(qǐng)求參數(shù)如何傳參
http://localhost:8080/requestParam4?name=哥哥&age=18&address.province=北京&address.city=北京&address.addr=回龍觀
@RequestMapping("/requestParam4")
@ResponseBody
public String testParam4(User user){
System.out.println(user);
return "{'"+user.getName()+"':'"+user.getAge()+"'}";
}
5.當(dāng)請(qǐng)求參數(shù)存在多個(gè)相同的參數(shù)名時(shí),控制器方法可以用String數(shù)組接收
http://localhost:8080/requestParam5?hobby=java&hobby=c++&hobby=dance
@RequestMapping("/requestParam5")
@ResponseBody
public String testParam5(String[] hobby){
System.out.println(Arrays.toString(hobby));
return "success";
}
6.當(dāng)請(qǐng)求參數(shù)存在多個(gè)相同的參數(shù)名時(shí),控制器方法可以用List集合接收
http://localhost:8080/requestParam5?hobby=java&hobby=c++&hobby=dance
@RequestMapping("/requestParam6")
@ResponseBody
public String testParam6(List<String> hobby){
System.out.println(hobby);
return "success";
}
獲取請(qǐng)求體中的json數(shù)據(jù)
- 導(dǎo)入json數(shù)據(jù)轉(zhuǎn)換相關(guān)坐標(biāo)
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
- @EnableWebMvc 標(biāo)識(shí)SpringConfig配置類開啟json數(shù)據(jù)轉(zhuǎn)換
@Configuration
@ComponentScan("com.itheima.controller")
//開啟json數(shù)據(jù)類型自動(dòng)轉(zhuǎn)換
@EnableWebMvc
public class SpringMvcConfig {
}
- @RequestBody 將請(qǐng)求體數(shù)據(jù)賦值給控制器方法參數(shù)
1.請(qǐng)求體中數(shù)據(jù)為json對(duì)象 控制器參數(shù)為實(shí)體類對(duì)象
http://localhost:8080/requestParam8
@RequestMapping("/requestParam8")
@ResponseBody
public String testParam8(@RequestBody User user){
System.out.println(user);
return "success";
}
2.請(qǐng)求體中數(shù)據(jù)為json數(shù)組 控制器參數(shù)為list集合
@RequestMapping("/requestParam7")
@ResponseBody
public String testParam7(@RequestBody List<String> hobby){
System.out.println(hobby);
return "success";
}
3.請(qǐng)求體中數(shù)據(jù)為json數(shù)組,元素為json對(duì)象 控制器參數(shù)為list集合,泛型為實(shí)體類
@RequestMapping("/requestParam9")
@ResponseBody
public String testParam9(@RequestBody List<User> users){
System.out.println(users);
return "success";
}
@RequestBody與@RequestParam區(qū)別
- 區(qū)別
@RequestParam用于接收url地址傳參,表單傳參【application/x-www-form-urlencoded】
@RequestBody用于接收json數(shù)據(jù)【application/json】 - 應(yīng)用
后期開發(fā)中,發(fā)送json格式數(shù)據(jù)為主桩了,@RequestBody應(yīng)用較廣
如果發(fā)送非json格式數(shù)據(jù)踱侣,選用@RequestParam接收請(qǐng)求參數(shù)
請(qǐng)求參數(shù)中的日期
springmvc中默認(rèn)格式為yyyy/MM/dd
如果請(qǐng)求參數(shù)格式不一致,可以使用
- @DateTimeFormat(pattern = "yyyy-MM-dd")進(jìn)行格式轉(zhuǎn)換
http://localhost:8080/requestParam10?date=2018/08/08&date1=2019-09-09
@RequestMapping("/requestParam10")
@ResponseBody
public String testParam10(Date date,@DateTimeFormat(pattern = "yyyy-MM-dd") Date date1){
System.out.println(date);
System.out.println(date1);
return "success";
}
傳遞日期類型參數(shù)必須在配置類上使用@EnableWebMvc注解。其功能之一:根據(jù)類型匹配對(duì)應(yīng)的類型轉(zhuǎn)換器趟畏。
響應(yīng)json數(shù)據(jù)
需要添加jackson-databind依賴以及在SpringMvcConfig配置類上添加@EnableWebMvc注解,使得響應(yīng)數(shù)據(jù)變?yōu)閖son數(shù)據(jù)
1.響應(yīng)實(shí)體類對(duì)象變?yōu)閖son對(duì)象
http://localhost:8080/requestParam11
@RequestMapping("/requestParam11")
@ResponseBody
public User testParam10(){
User user = new User();
user.setName("bob");
user.setAge(18);
return user;
}
2.響應(yīng)實(shí)體類集合變?yōu)閖son數(shù)組
http://localhost:8080/requestParam12
@RequestMapping("/requestParam12")
@ResponseBody
public List<User> testParam12(){
User user = new User();
user.setName("bob");
user.setAge(18);
User user1 = new User();
user1.setName("alice");
user1.setAge(20);
ArrayList<User> list = new ArrayList<>();
list.add(user);
list.add(user1);
return list;
}
Restful風(fēng)格
表面層資源狀態(tài)轉(zhuǎn)移
因?yàn)闉g覽器只支持解析post和get請(qǐng)求,所以如何發(fā)送delete和put請(qǐng)求?
HiddenHttpMethodFilter 實(shí)現(xiàn)put和delete請(qǐng)求
要求1:必須以post請(qǐng)求提交數(shù)據(jù)
要求2:請(qǐng)求參數(shù)中傳遞以"_method"為參數(shù),值為PUT/DELETE/Patch三者之一.
底層會(huì)使用包裝模式,重寫getMethod方法,將包裝的wrapperRequest放進(jìn)doFilter方法放行.
當(dāng)HiddenHttpMethodFilter 與 CharacterEncodingFilter共存時(shí),需要將編碼過濾器放到最前,要在所有獲取請(qǐng)求參數(shù)之前執(zhí)行.
開啟靜態(tài)資源訪問
方式一:
開啟靜態(tài)資源訪問標(biāo)簽<mvc:default-servlet-handler/> 或在springMvc配置類中重寫configureDefaultServletHandling方法
@Configuration
//掃描組件
@ComponentScan("com.atguigu.mvc.controller")
//開啟MVC注解驅(qū)動(dòng)
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
//使用默認(rèn)的servlet處理靜態(tài)資源
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
當(dāng)前端控制器處理請(qǐng)求找不到靜態(tài)資源對(duì)應(yīng)的handler時(shí),就會(huì)交由默認(rèn)的serlet處理去尋找靜態(tài)資源.
方式二:
此類為controller層的一個(gè)配置類組件
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**")
.addResourceLocations("/pages/");
registry.addResourceHandler("/css/**")
.addResourceLocations("/css/");
registry.addResourceHandler("/js/**")
.addResourceLocations("/js/");
registry.addResourceHandler("/plugins/**")
.addResourceLocations("/plugins/");
}
}
異常處理器
異常處理器的原理是AOP思想中的afterThrowing通知類型
//@ControllerAdvice將當(dāng)前類標(biāo)識(shí)為異常處理的組件
@ControllerAdvice
public class ExceptionController {
//@ExceptionHandler用于設(shè)置所標(biāo)識(shí)方法處理的異常
@ExceptionHandler(ArithmeticException.class)
//ex表示當(dāng)前請(qǐng)求處理中出現(xiàn)的異常對(duì)象
public String handleArithmeticException(Exception ex, Model model){
model.addAttribute("ex", ex);
return "error";
}
}
攔截器
實(shí)現(xiàn)自定義攔截器需要實(shí)現(xiàn)HandlerInterceptor接口,然后在springmvc中進(jìn)行配置
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("第一攔截器preHandle方法執(zhí)行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("第一攔截器postHandle方法執(zhí)行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("第一攔截器afterCompletion方法執(zhí)行");
}
}
攔截器的三個(gè)抽象方法
preHandle:控制器方法執(zhí)行之前執(zhí)行preHandle()贡歧,其boolean類型的返回值表示是否攔截或放行,返回true為放行赋秀,即調(diào)用控制器方法利朵;返回false表示攔截,即不調(diào)用控制器方法
postHandle:控制器方法執(zhí)行之后執(zhí)行postHandle(),相當(dāng)于aop的正常返回通知.
afterComplation:處理完視圖和模型數(shù)據(jù)猎莲,渲染視圖完畢之后執(zhí)行afterComplation()
攔截器的執(zhí)行順序
在所有攔截器都正常返回true的情況下,prehandle方法按攔截器的注冊(cè)順序正序執(zhí)行,后面兩個(gè)方法倒序執(zhí)行;
若有攔截器的返回false,則從此攔截器的前一個(gè)攔截器開始,倒序執(zhí)行afterCompletion方法.
攔截器和過濾器的區(qū)別
1)攔截器是基于java的反射機(jī)制的绍弟,而過濾器是基于函數(shù)回調(diào)。
2)攔截器不依賴與servlet容器著洼,過濾器依賴與servlet容器樟遣。
3)Filter 不能夠使用 Spring 容器資源,攔截器是一個(gè)Spring的組件身笤,歸Spring管理豹悬,配置在Spring文件中,因此能使用Spring里的任何資源
4)Filter 定義在 web.xml 中
Spring的Interceptor(攔截器)與Servlet的Filter有相似之處液荸,比如二者是AOP編程思想的體現(xiàn)瞻佛,都能實(shí)現(xiàn)權(quán)限檢查、日志記錄等娇钱。
Servlet中的過濾器Filter是實(shí)現(xiàn)了javax.servlet.Filter接口的服務(wù)器端程序伤柄,主要的用途是設(shè)置字符集涡尘、控制權(quán)限、控制轉(zhuǎn)向响迂。攔截器可以加載用戶信息考抄,判斷用戶的訪問權(quán)限。