一、@RequestMapping注解
1、位置规则
当作用于一个类时:设置映射请求的请求路径的初始信息
当作用于一个方法时:设置映射请求的请求路径的具体信息(包含于对应的初始信息中,换言之与文件访问的道理相似)
2、常用属性
(限制条件,请求只能满足这些属性才能成功被映射):value,method,params,headers
- value值为了一个String[],表示对应的方法可以映射多个请求。
- 这个属性是必须存在的,@RequestMapping其他任何属性都是在value匹配成功后再进行匹配 不匹配404
- method值为一个RequestMethod[],表示对应的方法可以映射多种请求方法,可以为get(请求拼接数据到了请求地址)或post(将值放到了请求体中,没有输出上限),这两种方法都name=value的方式传输数据。
- Spring提供了关于Method的派生注解有:
@GetMapping ,@PostMapping,@putMapping - 浏览器只支持get与post提交方式 不匹配405
- Spring提供了关于Method的派生注解有:
- params值为一个String[],表示请求需要同时满足字符串数组要求请求参数拥有的参数才能被映射。
- 一共有四种格式设置:
①只有name说明要求必须有这个参数
②!name要求不能有这个参数
③name==value要求参数需要等于指定值
④name!=value要求参数不等于指定值 - 请求参数默认为get方式传输,添加方式是直接在html页面请求地址后添加(name=value)的方式 不匹配400
- 一共有四种格式设置:
- headers(了解即可)值为String[],从请求头去指定需要匹配的信息,匹配方法与params相同。
- 不匹配404
3、@RequestMapping注解支持ant风格的路径
?表示任意的单个字符
*表示0个或者多个任意字符,
**表示任意层目录只能使用/**/
4、 SpringMVC支持路径中的占位符(重点)
原始方式:/test?id=1
rest方式:/test/1(这里相当于只传输数据,将如何接受的问题转移给了@RequestMapping来解决)
接受方式:value属性将路径中的值一一对应名称,就可以使用其保存为键值对,最后通过@PathVariable赋值给映射方法的参数
@RequestMapping("/test/{id}")
public String testRest(@PathVariable("id") Intrgat id){
}
二、SpringMVC获取请求参数
1、通过ServletAPI获取
原生的ServletAPI获取键值对方式的请求参数(尽量不用,太麻烦)
value==request.getParameter(name);
2、通过控制器方法的形参获取请求参数
通过控制器的形参来获取键值对方式的请求参数直接将name写入映射方法的形参中,SpringMVC会为请求参数中的name与形参名相同的形参自动赋值(支持多个同名的形参,可以使用String或者String[]来接受)
3、@RequestParam
当形参的名称与请求参数的名称不一致时,可以使用@RequestParam(name1)String name2,一样可以将name1对应的值赋给name2
@RequestParam注解中还有两个属性:required是否必须传输value对应的值,不匹配要求报400,defaultValue为没有值的参数赋默认值,
4、@RequestHeader
@RequestHeader注解获取请求头的信息,也包括value,required,defaultValue三个属性,用法一致
5、@CookieValue
@CookieValue("JSESSIONID")获取对应客户端会话ID
6、通过POJO获取请求参数
通过VO(实体类)获取请求参数,将形参为对象时,会自动为对象中的名称相同的字段赋值。
7、解决获取请求参数的乱码问题
get请求的乱码问题已经通过修改tomcat的servlet.xml配置文件URIEncoding解决
post请求出现乱码是因为请求加载时传入的参数编码与idea中的编码方式不同,所以我们需要在加载前使用过滤器来设置编码格式——在web.xml配置文件中增加下面配置
<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>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
三:域对象共享数据
1、使用serletAPI向request(请求)域对象共享数据
request.setAttribute(name,value);
2、使用ModelAndView向request域共享数据
ModelAndView是将模式与视图一体化的对象,首先addObject(name,value)共享数据,还可以通过setViewName(跳转页面)设置视图,使用该对象时,方法返回值为该对象用来获取其中封装的模型数据和视图。该种方式是其他方法实现向域共享数据的必经之路,也是SpringMVC中的推荐方式
3、使用Model向request域共享数据
Model对象中有addAttribute(name,value);方法可以完成该功能。
4、使用Map向request域共享数据
Map集合使用put(String,Object)方法完成该功能。
5、使用ModelMap向request域共享数据
ModelMap对象有addAttribute(name,value);方法可以完成该功能。
6、总结Model,Map,ModelMap之间的关系
首先它们三个本质实现都是通过BindingAwareModelMap类实现,而这个的类的父类ExtendedModel继承了ModelMap,实现了Model接口
ModelMap又是Map的一个实现类,
7、使用servletAPI向session(会话)域共享数据(推荐方式)
session.setAttribute(name,value);方法
8、使用servletAPI向application(应用)域共享数据
application.setAttribute(name,value);方法
application是ServletContext对象,可以通过session.getSerletContext()方法获取到。
四、SpringMVC的视图
视图的分类:ThymeleafView,转发视图,重定向视图
1、ThymeleafView
映射方法返回的字符串没有任何的前缀,就是通过Thymeleaf解析器解析的视图
2、转发视图(InternalResourceView)
映射方法返回的字符串以forward为前缀,就是通过创建InternalResourceView然后再将forward去除,进行剩余部分的转发(使用较少,毕竟我们可以直接去访问对应的请求,而且无法更新数据)
3、重定向视图(RedirectView)
映射方法返回的字符串以redirect为前缀,先创建RedirectView,然后再将Redirect去除,进行剩余部分的重定向(客户端会发送两次请求)
4、视图控制器view-controller
在映射方法返回的字符串没有任何的前缀时,可以在SpringMVC的xml配置文件中设置<mvc:view-controller> 标签,其中两个属性path来对应请求映射与view-name对应视图名称,在配置了这个标签后其他的控制器映射会失效,需要再配置一个<mvc:annotation-driven>注解驱动
五、RESTFul
1、RESTFul是什么
REST是表现层资源状态转移,Ful表示一种代码架构风格。
资源是服务器中的抽象概念,万物皆可以是资源,资源的表示格式就是资源的状态,状态转移指通过一系列间接操作完成对应资源的不同使用
2、RESTFul如何使用
HTTP协议中有四个操作动词:get(获取),post(新建),put(更新),delete(删除)
核心就是使用URL地址来表示名词对应的资源,用动词来表示要进行的操作
当method为PUT或DELETE时,因为浏览器不能识别这两个动词,所以我们使用过滤器进行操作首先在文件中配置:<hiddenHttpMethodFilter>,然后在表单中设置隐藏列_method的值为PUT或DELETE就可以使POST请求方法变成我们想要的请求方法。 过滤器之间的执行顺序的考虑,编码过滤器应该首先执行,再执行其他的。
实际中使用REST:实际操作
六、HttpMessageConverter(报文信息转换器)
作用:将请求报文转换为java对象,或将Java对象转换为响应报文
两个核心注解和类型,@RequestBody(获取请求体),@RespondBody(获取响应体),RequestEntity,RespondEntity用来实现其功能下
1、@RequestBody
面向方法参数作用
2、RequestEntity
请求报文对象,要使用时直接将该类型的对象作用形参就可以获取对应请求的请求体的信息包装的对象。其中有两个方法,getHeaders(),getBoby()。
3、@RespondBody
作用方法,将该方法的返回值作为响应报文的响应体(servletAPI方式返回对应的响应体使用respond.getWrite.print(value)方法)
4、SpringMVC处理json
当返回体为java中的自定义对象时,需要导入相应jar包开启注解驱动,使用json字符串将其转换为json对象
5、SpingMVC处理ajax
6、@RestController
相当于为类加上@Controller注解的同时为了类中每一个方法加上了@RespondBoby注解
7、RespondEntity
用来实现文件上传与下载
- 文件下载
通过创建一个RespondEntity对象,将它的请求体存放要下载的字节信息,请求头存放下载方式与下载文件的名字,以及状态码设置为ok,最后返回这个对象就可以实现服务器文件下载了(文件路径为了target中的文件路径)
@RequestMapping("/fileDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
//获取Servletcontent对象
ServletContext context = session.getServletContext();
// 获取服务器中文件的真实路径
String realPath = context.getRealPath("/static/img/02.jpg");
// 创建输入流
InputStream is = new FileInputStream(realPath);
// 创建字节数组用于接收读入
byte[] bytes = new byte[is.available()];
// 将流读到字节数组中
is.read(bytes);
// 创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition","attachment;filename=02.jpg");
//设置响应状态码
HttpStatus status = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity =
new ResponseEntity<byte[]>(bytes,headers,status);
//关闭输入流
is.close();
return responseEntity;
}
- 文件上传
a)创建表单,需要改变enctype属性,并且使用文本域存放文件。
b)添加文件下载所需依赖
c)使用MultipartFile类来接受文件(需要在XML配置文件中配置上传解析器,帮助封装)
d)通过该对象的方法完成对应的功能
常用方法有:getOriginalFilename()获取上传文件名、transferTo(new File(Path))文件转移器
ps:解决上传文件重名问题
让上传文件的名字永不相同即可,实现原理是先获取文件的后缀fileName.substring(fileName.lastIndexOf("."))
再将UUID(随机序列)作为文件前缀
UUID.randomUUID().toString();
最终组合成为了一个永不重名的文件名
@RequestMapping("/fileUpload")
@ResponseBody
public String fileUpLoad(MultipartFile photo,HttpSession session) throws IOException {
//获取上传的文件名
String filename = photo.getOriginalFilename();
// 截取文件后缀名
String suffixName = filename.substring(filename.lastIndexOf("."));
// 获取随机前缀
String uuid = UUID.randomUUID().toString();
// 随机前缀和文件后缀拼接为新随机名
filename = uuid + suffixName;
// 通过session获取ServletContent对象
ServletContext context = session.getServletContext();
// 通过ServletContent对象获取文件夹实际路径
String filePath = context.getRealPath("photo");
// 创建实际路径文件夹对象
File file = new File(filePath);
// 判断文件夹对象是否不存在,成立就创建
if(!file.exists()){
file.mkdir();
}
// 拼接文件的最终路径
String finalPath = filePath + File.separator + filename;
// 实现上传
photo.transferTo(new File(finalPath));
return "success";
}
七、拦截器
1、拦截器是什么
拦截器是执行在控制器执行的前后的类
2、拦截器如何创建
先创建一个普通的类,实现HandlerInterceptor接口,然后重写三个其中的三个方法(crtl+o快捷键重写),在XML配置文件中配置拦截器<mvc:interceptors>,在其中添加对应的bean,拦截器拦截规则设置,在配置拦截器中使用<mvc:interceptor>标签,
设置<mvc:mapping path="/**"/>表示拦截所有请求,<mvc:exclued-mapping path="/"/>表示不拦截映射请求路径为/的请求,再添加要使用这种规则的bean(拦截器)
3、拦截器的三个抽象方法
preHandle(方法执行之前),postHandle(方法执行完毕之后),afterCompletion(视图渲染完成之后),其中控制器方法是否放行(执行)由preHandler的返回值决定
4、多个拦截器的执行顺序规则
通过在配置文件中顺序来决定其在拦截器数组中的顺序,执行preHandle方法时,通过从0开始遍历数组执行方法,并且每通过一个方法,变量interceptorIndex就加一,当有方法返回为false,则循环方法结束,执行postHandle方法时,从数组长度-1开始反序遍历,执行到afterCompletion时,从interceptorIndex开始反序遍历拦截器数组
eg:1 2 3 4 5 preHandle:1 2 3 afterCompletion: 2 1
八、异常处理器
1.基于xml配置
2.基于注解配置
九、基于注解配置SpringMVC
使用配置类和注解代替web.xml和SpringMVC配置文件的功能
1、创建初始化类,代替web.xml
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* 指定spring的配置类
*
* @return
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
/**
* 指定SpringMVC的配置类
*
* @return
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
/**
* 指定DispatcherServlet的映射规则,即url-pattern
*
* @return
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
/**
* 添加过滤器
*
* @return
*/
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceRequestEncoding(true);
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{encodingFilter, hiddenHttpMethodFilter};
}
}
2、创建SpringConfig配置类,代替spring的配置文件
@Configuration
public class SpringConfig {
//ssm整合之后,spring的配置信息写在此类中
}
3、创建WebConfig配置类,代替SpringMVC的配置文件
@Configuration
//扫描组件
@ComponentScan("com.mg.mvc")
//开启MVC注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
//使用默认的servlet处理静态资源
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
//配置文件上传解析器
@Bean
public CommonsMultipartResolver multipartResolver(){
return new CommonsMultipartResolver();
}
//配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
FirstInterceptor firstInterceptor = new FirstInterceptor();
registry.addInterceptor(firstInterceptor).addPathPatterns("/*").excludePathPatterns("/");
}
//配置视图控制
/*@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}*/
//配置异常映射
/*@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
Properties prop = new Properties();
prop.setProperty("java.lang.ArithmeticException", "error");
//设置异常映射
exceptionResolver.setExceptionMappings(prop);
//设置共享异常信息的键
exceptionResolver.setExceptionAttribute("ex");
resolvers.add(exceptionResolver);
}*/
//配置生成模板解析器
@Bean
public ITemplateResolver templateResolver() {
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
// ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
ServletContextTemplateResolver templateResolver =
new ServletContextTemplateResolver(webApplicationContext.getServletContext());
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
//生成模板引擎并为模板引擎注入模板解析器
@Bean
public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
return templateEngine;
}
//生成视图解析器并为解析器注入模板引擎
@Bean
public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setCharacterEncoding("UTF-8");
viewResolver.setTemplateEngine(templateEngine);
return viewResolver;
}
}