springMVC是表示层的框架,它的入口是一个servlet 前端控制器 DispatcherServlet
工程搭建,首先在web.xml中配置 DispatcherServlet,url-pattern为/ ,load-on-startup 为1 代表web容器初始化的时候一起初始化 dispacherServlet 并且加载它的初始化参数init-param(spring配置文件)
<servlet>
<servlet-name>dispacherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispacherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
springmvc.xml为spring配置文件 开启注解扫描及mvc注解支持
<context:component-scan base-package="controller"></context:component-scan>
<mvc:annotation-driven></mvc:annotation-driven>
springMVC的三大组件 处理器映射器,处理器适配器,视图解析器
一个请求的过程
- 请求进来 http://localhost:8080/springmvc/hello 到达前端控制器 dispatchServlet
2.前端控制器将/hello这个请求资源路径发送给 处理器映射器,处理器映射器找到对应的处理器及具体方法 HelloController.sayHello(),返回控制器
3.控制器找到处理器适配器,处理器适配器找处理器HelloController去执行方法sayHello(),接收处理器返回的结果并返回给控制器
4.控制器再找到视图解析器,视图解析器找到对应的视图并返回给控制器
5.控制器将视图响应给客户
@RequestMapping 注解的作用是建立请求路径url和处理请求方法之间的对应关系
@RequestMapping 注解的属性有 value请求的路径 method请求的方法 params请求参数的限制 headers请求头的限制
springMVC中请求参数的绑定, 能识别get post 发送过来的键值对形式的数据 比如表单提交数据
1.如果处理请求方法的参数名和请求的参数名相同则可以直接获取.
2.如果处理请求方法的参数是一个对象,且对象的属性名和请求的参数名相同则可以将请求参数直接存入对象中.
3.如果处理请求方法的参数是一个对象user,且对象的属性名name和请求的参数名name相同则可以将请求参数直接存入对象中. 对象中还有对象属性car,那么 属性对象名.属性名 和请求参数的名称(car.name)相同也可以存入
4.接收list类型的数据参数名应这样 list[0].name list[0].age
5.接收map类型的数据参数名应这样 map[‘one’].name map[‘one’].age
前端提交过来的数据其实都是字符串的,而我们接收的数据类型可以是我们需要的,过程中springMVC帮我们进行了数据类型的转换,虽然提供了很多转换类,但是日期等可能还需要我们自己自定义类型转换器.
自定义的类型转换器需实现Convert<S,T> 接口 然后在配置文件中配置加入spring管理 并且在 mvc驱动中配置进行使用
<mvc:annotation-driven conversion-service="conversionServiceFactory"></mvc:annotation-driven>
<bean id="conversionServiceFactory" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters" >
<set>
<bean class="controller.StringToDateConversion"></bean>
</set>
</property>
</bean>
解决post请求中文乱码问题在web.xml中配置spring提供的编码过滤器
<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>
在springMVC 的Controller类的方法上可以直接定义Servlet原生的 request 和response对象并获取到 进而通过request获取到session servletContext等
@RequestParam(“name”) 获取传入的参数,且必须传此参数
@RequestBody 获取请求体的内容,不能接收get方法 因为get方法没有请求体
@PathVariable 获取请求路径上的变量值 {}为url占位符 restful风格一般会使用请求路径占位符的形式 相同的请求路径 不同的请求方式来区分方法
@RequestMapping("/user/{id}")
public String sayHello(@PathVariable String id){
System.out.println("hello SpringMVC");
System.out.println(id);
return "success";
}
@RequestHeader(“请求头的名称”) 获取请求头
@ModelAttribute 此注解加在方法上,则此方法会先执行,并将方法返回值放入springMVC 数据模型中,被调用的方法参数就可以使用被注解方法的返回值了
@ModelAttribute(“变量名”) 此注解加在方法参数前,代表从容器中取出名称为变量名的变量赋值到方法参数
springMVC被访问的Controller类方法,
1.方法返回值是字符串,默认情况下走的是通用的视图解析器,从webapp下面寻找资源 return “success.jsp”; 如果要访问 WEB-INF内的资源就需要在spring配置文件中配置内部资源视图解析器
2.方法返回值是void 那么解析不到视图会报错 我们可以选择请求转发 或者重定向 也可以用response响应
3.方法返回值是ModelAndView 里面添加属性,相当于放到了request域中 view就相当于返回的字符串
springMVC web项目入口是前端控制器,那么各种请求都会被前端控制器拦截住,一些前端资源访问也不例外,需要放开这些前端资源的访问 在配置文件中配置
<mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
springMVC默认使用jackson 对json数据进行转换的,可以将接收的请求体中的json格式数据直接封装进@RequestBody 注解的方法参数对象 ,也可以将@ResponseBody注解的对象 转变成 json数据的响应体
导入jackson与springMVC配合的jar包坐标
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
springMVC之文件上传
form表单的 method必须是post , 必须有一个 文件选择域, form表单的enctype 必须是 multipart/formdata 默认是 application/x-www-form-urlencoded
文件上传需引入的jar包坐标
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
传统方式的文件上传
@RequestMapping("/user")
public void sayHello1(HttpServletRequest request,HttpServletResponse response) throws Exception {
//1.定义本地存放上传文件的文件夹
String uploadPath = request.getSession().getServletContext().getRealPath("/upload");
File file = new File(uploadPath);
if (!file.exists()){
//文件不存在则创建
file.mkdir();
}
//2.将上传的文件上传至本地
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
ServletFileUpload upload=new ServletFileUpload(diskFileItemFactory);
List<FileItem> fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()){
//普通表单字段
}else{
//文件
String name = UUID.randomUUID()+fileItem.getName();
fileItem.write(new File(file,name));
fileItem.delete();
}
}
response.getWriter().write("wancheng");
}
用springMVC方式上传的话 文件对象可以直接被封装到controller方法入参中 前提是参数类型必须是MultipartFile 参数名必须和页面的file input标签的name相同 并且在spring配置文件中配置 multipartResolver ,id必须是这个一个字不能变
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
@RequestMapping("/user")
public void sayHello1(HttpServletRequest request, HttpServletResponse response, MultipartFile upload) throws Exception {
//1.定义本地存放上传文件的文件夹
String uploadPath = request.getSession().getServletContext().getRealPath("/upload");
File file = new File(uploadPath);
if (!file.exists()) {
//文件不存在则创建
file.mkdir();
}
//2.将上传的文件上传至本地
//文件
String name1 = upload.getName();
System.out.println(name1);
String name = UUID.randomUUID() + upload.getOriginalFilename();
upload.transferTo(new File(file, name));
response.getWriter().write("wancheng");
}
跨服务器上传文件,就是客户访问我们服务器,上传文件,我们文件不存放在本机,而是直接传给文件服务器. 这样的话需要引入 jesery jar包
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.14</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.9</version>
</dependency>
文件服务器的tomcat配置文件 web.xml 需新增配置 在DefaultServlet中增加初始化参数,允许上传文件
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
而上传的代码如下,创建客户端,连接服务器文件地址,上传文件
@RequestMapping("/user")
public void sayHello1( HttpServletResponse response, MultipartFile upload) throws Exception {
String name = upload.getOriginalFilename();
Client client=new Client();
WebResource resource = client.resource("http://192.168.111.30:8080/fileServer/upload/"+name);
resource.put(String.class, upload.getBytes());
response.getWriter().write("wancheng");
}
springMVC之异常处理 每一层异常都抛出不处理的话,那么将直接抛到浏览器 如果在spring配置文件中配置自定义的异常解析器,那么会跳到指定的页面并展示对应异常信息 也需要自定义异常
<bean id="springExceptionHandel" class="controller.SpringExceptionHandel"></bean>
public class SpringExceptionHandel implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ModelAndView mv=new ModelAndView();
if (ex instanceof SpringException){
mv.addObject("msg",((SpringException) ex).getMsg());
}else {
mv.addObject("msg","系统异常");
}
mv.setViewName("error.jsp");
return mv;
}
}
拦截器和过滤器的区别
过滤器是javaweb规范中的部分,任何javaweb项目都可以使用 url-pattern /* 拦截所有请求,包括静态资源等
拦截器是springMVC框架提供的,只能在springMVC框架下使用,只拦截访问的controller的方法 基于aop的 实现自定义拦截器必须实现 HandlerInterceptor 接口
自定义拦截器完毕后需要在spring配置文件中配置这些拦截器及其拦截的方法
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/user"/>
<bean class="controller.MyInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>