1. Spring 集成 Web 环境
弊端: 应用上下文对象是通过 new ClasspathXmlApplicationContext
方式获取的,但是每次从容器中获得 Bean 时都要编写 ,这样的弊端是配置文件加载多次,应用上下文对象创建多次
解决: 在 Web 项目中,可以使用 servletcontextlistener 监听 Web 应用的启动,我们可以在 Web 应用启动时,就加载 Spring 的配置文件,创建应用上下文对象 ApplicationContext ,在将其存储到最大的域 ServletContext 域中,这样就可以在任意位置从域中获得应用上下文 ApplicationContext 对象了
故我们需要获取 IOC 容器中的 Bean 时,仅需进行:
- 配置 ContextLoaderListener 监听器
- 使用 WebApplicationContextUtils 获得应用上下文
2. SpringMVC 组件解析
2.1 执行流程
- 用户发送请求至前端控制器
dispatcherServlet
dispatcherServlet
收到请求调用HandlerMapping
处理器映射器- 处理器映射器找到具体的处理器(可以根据 Xml 配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给
dispatcherServlet
dispatcherServlet
调用HandlerAdapter
处理器适配器HandlerAdapter
经过适配调用具体的处理器(后端控制器 Controller)Controller
执行完成返回ModelAndView
HandlerAdapter
将Controller
执行结果ModelAndView
返回给dispatcherServlet
dispatcherServlet
将ModelAndView
传给ViewReslover
视图解析器ViewReslover
解析后返回具体View
dispatcherServlet
根据View
进行渲染视图(即将模型数据填充至视图中),dispatcherServlet
响应用户
2.2 组件解析
- 前端控制器:
dispatcherServlet
- 处理器映射器:
HandlerMapping
- 处理器适配器:
HandlerAdapter
HandlerAdapter
的作用是根据映射器找到的处理器Handler
信息,按照特定的规则去执行相关的处理器Handler
- 处理器:
Handler
- 视图解析器:
ViewResolver
2.3 注解解析
@RequestMapping
位置:
- 类上,请求 URL 的第一级访问目录。此处不写的话,就相当于应用的根目录
- 方法上,请求 URL 的第二级访问目录,与类上的使用
@ReqquestMapping
标注的一级目录一起组成访问虚拟路径
参数:
- value:用于指定请求的 URL
- method:用于指定请求的方式
- params:用于指定限制请求参数的条件
使用 SpringMVC 注解配置需要引入 mvc 命名空间,同时由于 SpringMVC 基于spring容器,所以在进行 SpringMVC 操作时,需要将 Controller 存储到 Spring 容器中(Spring 容器与 SpringMVC 容器为父子容器关系,SpringMVC 能访问 Spring 容器内资源,反之不行)
<context:component-scan base-package=“com.example.controller"/>
2.4 XML配置解析
视图解析器:修改前后缀
- prefix:前缀
- suffix:后缀
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
3. SpringMVC 数据响应
3.1 数据响应方式
3.2 页面跳转
直接返回字符串: 此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转
返回 ModelAndView 对象:
@RequestMapping("/test")
public ModelAndView testMethod(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("redirect:index.jsp");
return modelAndView;
}
@RequestMapping("/test")
public ModelAndView testMethod(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("forward:/WEB-INF/views/index.jsp");
return modelAndView;
}
除了 new ModelAndView
还可以在参数种添加 ModelAndView 让 SpringMVC 自动注入
向 request 域存储数据:
-
通过 SpringMVC 框架注入的 request 对象
setAttribute()
方法设置@RequestMapping("/test") public String testMethod(HttpServletRequest request){ request.setAttribute("name","zhangsan"); return "index"; }
-
通过 ModelAndView 的
addobject()
方法设置@RequestMapping("/test") public ModelAndView testMethod(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("forward:/WEB-INF/views/index.jsp"); modelAndView.addobject("name","lisi"); return modelAndView; }
3.3 回写数据
使用 Response 对象:
通过 SpringMVC 框架注入的 response 对象,使用 response.getWriter().print(“hello world”)
回写数据,此时不需要视图跳转,业务方法返回值为 void
@RequestMapping("/test")
public void testMethod(HttpServletResponse response) throws IOException {
response.getWriter().print("Hello World");
}
直接返回字符串:
将需要回写的字符串直接返回,但此时需要通过 @ResponseBody
注解告知 SpringMVC 框架,方法返回的字符串不是跳转是直接在 http 响应体中返回
@RequestMapping("/test")
@ResponseBody
public String testMethod() throws IOException {
return "Hello SpringMVC";
}
返回对象或集合:
如果我们需要返回一个POJO,我们一般习惯于字符串返回 Json 格式的字符串,此时我们需要使用 jackson 工具进行转换
通过 SpringMVC 帮助我们对对象或集合进行 json字符串的转换并回写,为处理器适配器配置消息转换参数,指定使用 jackson 进行对象或集合的转换,因此需要在 spring-mvc.xml 中进行如下配置:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
配置之后我们只需要这样就可以返回 json 字符串了:
@RequestMapping("/test")
@ResponseBody public User testMethod() throws IOException {
User user = new User();
user.setUsername("思思不羡仙");
user.setAge(18);
return user;
}
在方法上添加 @ResponseBody
就可以返回 json 格式的字符串,但是这样配置比较麻烦,配置的代码比较多,因此,我们可以使用 mvc 的注解驱动代替上述配置:
<mvc:annotation-driven/>
4. SpringMVC 获取请求数据
客户端请求参数的格式是:name=value&name=value&name=value
服务器端要获得请求的参数,有时还需要进行数据的封装,SpringMVC 可以接收如下类型的参数:
- 基本类型参数
- POJO类型参数
- 数组类型参数
- 集合类型参数
4.1 获取基本类型参数
Controller 中的业务方法的参数名称要与请求参数的 name 一致,参数值会自动映射匹配
@RequestMapping("/test")
@ResponseBody
public void testMethod(String username,int age) throws IOException {
System.out.println(username);
System.out.println(age);
}
4.2 获取POJO类型参数
Controller 中的业务方法的 POJO 参数的属性名与请求参数的 name 一致,参数值会自动映射匹配
// 请求地址:http://localhost:8080/test?username=apple&age=18
@Data
public class User {
private String username;
private int age;
}
@RequestMapping("/test")
@ResponseBody
public void testMethod(User user) throws IOException {
System.out.println(user);
}
4.3 获取数组类型参数
Controller 中的业务方法数组名称与请求参数的 name 一致,参数值会自动映射匹配
// 请求地址:http://localhost:8080/test?strs=111&strs=222&strs=333
@RequestMapping("/test")
@ResponseBody
public void testMethod(String[] strs) throws IOException {
System.out.println(Arrays.asList(strs));
}
4.4 获取集合类型参数
获得集合参数时,需要包装到一个 POJO 中才可以,即创建一个 VO 对象,内部有 List<User> userList
成员变量,表单可如下:
<form action="${pageContext.request.contextpath}/test" method="post">
<input type="text" name="userList[0].username"><br>
<input type="text" name="userList[0].age"><br>
<input type="text" name="userList[1].username"><br>
<input type="text" name="userList[1].age"><br>
<input type="submit" value="提交"><br>
</form>
当使用 ajax 提交时,可以指定 contentType 为 json 形式,那么在方法参数位置使用 @RequestBody
可以直接接收集合数据而无需使用 POJO 进行包装
@RequestMapping("/test")
@ResponseBody
public void testMethod(@RequestBody List<User> userList) throws IOException {
System.out.println(userList);
}
释放指定资源:
没有加载到 jquery 文件,原因是 SpringMVC 的前端控制器 dispatcherServlet 的 url-pattern 配置的是 / ,代表对所有的资源都进行过滤操作,我们可以通过以下两种方式指定放行静态资源:
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:default-servlet-handler/>
上述第一种方式需要注意:
4.5 请求数据乱码问题
当 post 请求时,数据会出现乱码,我们可以设置一个过滤器来进行编码的过滤
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4.6 参数绑定注解
当请求的参数名称与 Controller 的业务方法参数名称不一致时,就需要通过 @RequestParam
注解显示的绑定
<form action="${pageContext.request.contextpath}/test" method="post">
<input type="text" name="name"><br>
<input type="submit" value="提交"><br>
</form>
@RequestMapping("/test")
@ResponseBody
public void testMethod(@RequestParam("name") String username) throws IOException {
System.out.println(username);
}
@RequestParam
的参数:
4.7 获取 Restful 风格的参数
Restful 是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等
Restful 风格的请求是使用 [url + 请求方式] 表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:
上述 url 地址 /user/hello 中的 hello 就是要获得的请求参数,在 SpringMVC 中可以使用占位符进行参数绑定,地址 /user/hello 可以写成 /user/{id} ,占位符 {id} 对应的就是 hello 的值,在业务方法中我们可以使用 @PathVariable
注解进行占位符的匹配获取工作
// 请求地址:http://localhost:8080/test/zhangsan
@RequestMapping("/test/{name}")
@ResponseBody
public void testMethod(@PathVariable(value = "name",required = true) String name){
System.out.println(name);
}
4.8 自定义类型转换器
SpringMVC 默认已经提供了一些常用的类型转换器,例如客户端提交的字符串转换成 int 型进行参数设置,但是不是所有的数据类型都提供了转换器,没有提供的就需要自定义转换器,例如:日期类型的数据就需要自定义转换器
自定义类型转换器的开发步骤:
-
定义转换器类实现 Converter 接口
public class DateConverter implements Converter<String,Date>{ @Override public Date convert(String source) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); try { Date date = format.parse(source); return date; } catch (ParseException e) { e.printstacktrace(); } return null; } }
-
在配置文件中声明转换器
<bean id="converterService" class="org.springframework.context.support.ConversionServicefactorybean"> <property name="converters"> <list> <bean class="com.example.converter.DateConverter"/> </list> </property> </bean>
-
在
<annotation-driven>
中引用转换器<mvc:annotation-driven conversion-service="converterService"/>
4.9 获取Servlet相关API
SpringMVC 支持使用原始 ServletAPI 对象作为控制器方法的参数进行注入,常用的对象如下:
- HttpServletRequest
- HttpServletResponse
- HttpSession
4.10 获取请求头
1. @RequestHeader
注解
相当于 request.getHeader(name)
方法,该注解有以下属性:
@RequestMapping("/test")
@ResponseBody
public void testMethod(@RequestHeader(value = "User-Agent",required = false) String headerValue){
System.out.println(headerValue);
}
2. @CookieValue
注解
使用该注解可以获得指定 Cookie 的值,该注解有以下属性:
@RequestMapping("/test")
@ResponseBody
public void testMethod(@CookieValue(value = "JSESSIONID",required = false) String jsessionid){
System.out.println(jsessionid);
}
4.11 文件上传
-
表单项 type = “ file ”
-
表单的提交方式是 post
-
表单的 enctype 属性是多部分表单形式,及 enctype = “ multipart/form-data ”
-
enctype = “ application/x-www-form-urlencoded ” 时,form表单的正文内容格式是:key=value&key=value&key=value
-
当 form 表单的 enctype 取值为 mutilpart/form-data 时,请求正文内容就变成多部分形式:
单文件上传步骤
-
导入 commons-fileupload 和 commons-io 坐标
-
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--上传文件总大小--> <property name="maxUploadSize" value="5242800"/> <!--上传单个文件的大小--> <property name="maxUploadSizePerFile" value="5242800"/> <!--上传文件的编码类型--> <property name="defaultEncoding" value="UTF-8"/> </bean>
-
@RequestMapping("/test") @ResponseBody public void testMethod(String name,multipartfile uploadFile) throws IOException { //获得文件名称 String originalFilename = uploadFile.getoriginalFilename(); //保存文件 uploadFile.transferTo(new File("C:\\upload\\"+originalFilename)); }
多文件上传,只需要将页面修改为多个文件上传项,将方法参数 multipartfile 类型修改为 multipartfile[] 即可
@RequestMapping("/test")
@ResponseBody
public void testMethod(String name,multipartfile[] uploadFiles) throws IOException {
for (multipartfile uploadFile : uploadFiles){
String originalFilename = uploadFile.getoriginalFilename();
uploadFile.transferTo(new File("C:\\upload\\"+originalFilename));
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。