SpringMVC属于Spring全家桶中的一员,作用于web层,Spring准确的来说可以支持一个项目的各个层,SpringMVC的三大组件为处理器映射器、处理器适配器、视图解析器,需要用户完成的组件是Handler和View

SpringMVC工作流程

SpringMVC架构

SpringMVC入门

  1. jar包依赖
  2. 前端控制器的配置(SpringMVC的核心就在前端控制器,没有前端控制器,任何组件的功能都无法完成)
  <!-- web.xml -->
  <!-- springmvc的核心组件 -->
  <servlet>
  	<servlet-name>springmvc</servlet-name>
  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	<!-- 加载SpringMVC配置文件 -->
  	<init-param>
  		<param-name>contextConfigLocation</param-name>
  		<param-value>classpath:springmvc.xml</param-value>
  	</init-param>
  </servlet>
  
  <!-- 三种过滤方式 -->
  <!-- *.action /* 拦截所有 / 拦截所有不包括jsp -->
  <servlet-mapping>
  	<servlet-name>springmvc</servlet-name>
  	<url-pattern>*.action</url-pattern>
  </servlet-mapping>
  1. 开启注解扫描(非必须,目的为开发过程注入属性更加的方便)
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="tqb.controller"></context:component-scan>
  1. Handler组件的完成
package tqb.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/** * SpringMVC入门程序 * 处理业务逻辑请求 * @author tqb * */
@Controller
public class UserAction {
	
	/* * 返回用户列表 */
	// 请求的路径
	@RequestMapping("list/userList.action")
	public ModelAndView list(){
		ModelAndView mav = new ModelAndView();
		
		// 向request域中存放数据
		/*mav.addObject("list", list);*/
		
		// 执行完逻辑要跳转的路径
		mav.setViewName("/index.jsp");
		return mav;
	}
}

默认加载组件(位置:spring-webmvc包)

  1. 处理器映射器(过时)
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
  1. 处理器适配器(过时)
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
  1. 视图解析器
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

重新注册适配器和映射器

  1. 通过bean标签注册
<!-- 处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
  1. 通过mvc:annotation-driven自动注册
<mvc:annotation-driven />

配置视图解析器(配置前缀和后缀)

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/jsp/index.jsp"/>
	<property name="suffix" value=".jsp"/>
	<!-- 若跳转的视图名称为/WEB-INF/jsp/index.jsp 只需要setViewName("index"); -->
	
</bean>

SpringMVC-MyBatis整合

  1. Dao层
    1) sqlMapConfig.xml:别名等等
    2)applicationContext-dao.xml:数据库连接池、SqlSessionFactory、mapper文件扫描器
  2. Service层
    1)applicationContext-service:扫描Service层
    2)applicationContext-transaction:配置事务
  3. Controller层
    1)springmvc.xml:扫描Controller层、配置注解扫描、配置视图解析器、配置处理器
    2)web.xml:配置前端控制器、配置Spring

参数绑定

  1. 默认参数
	@RequestMapping("xxx")
	public ModelAndView findById(HttpServletRequest request, HttpServletResponse response, HttpSession session, Model model) {
		ModelAndView mv = new ModelAndView();
		String id = request.getParemeter("id");
		Order order = orderService.findById(id);
		// request域
		mv.addObject("order", order);
		mv.setViewName("list.jsp");
		return mv;
	}
  1. 简单参数
	@RequestMapping("xxx")
	public ModelAndView findById(int id) {
		ModelAndView mv = new ModelAndView();
		
		Order order = orderService.findById(id);
		// request域
		mv.addObject("order", order);
		mv.setViewName("list.jsp");
		return mv;
	}
  1. POJO

解决乱码问题

  1. POST(在web.xml添加如下内容,配置过滤器)
	<!-- 解决post乱码问题 -->
	<filter>
		<filter-name>encoding</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<!-- 设置编码参是UTF8 -->
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>encoding</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
  1. GET

1)修改tomcat配置文件添加编码与工程编码一致

<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

2)另外一种方法对参数进行重新编码

String userName new 
String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")

Controller中方法的三种返回值

  1. ModelAndView:耦合度高,方便
  2. String:方法携带参数Model ,返回值返回的是视图名称,通过Model实现域的功能,耦合度低,官方推荐
返回值中携带转发或重定向
return "forward:index.jsp"
return "redirect:index.jsp"
  1. void:Ajax

异常处理器

  1. 自定义异常处理器
public class CustomHandleException implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception exception) {
		// 定义异常信息
		String msg;

		// 判断异常类型
		if (exception instanceof MyException) {
			// 如果是自定义异常,读取异常信息
			msg = exception.getMessage();
		} else {
			// 如果是运行时异常,则取错误堆栈,从堆栈中获取异常信息
			Writer out = new StringWriter();
			PrintWriter s = new PrintWriter(out);
			exception.printStackTrace(s);
			msg = out.toString();

		}

		// 把错误信息发给相关人员,邮件,短信等方式
		// TODO

		// 返回错误页面,给用户友好页面显示错误信息
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addObject("msg", msg);
		modelAndView.setViewName("error");

		return modelAndView;
	}
}
  1. 异常处理器配置(在springmvc.xml)
<!-- 配置全局异常处理器 -->
<bean id="customHandleException" class="tqb.CustomHandleException"/>

文件上传

@RequestMapping("updateItem")
public String updateItemById(Item item, MultipartFile pictureFile) throws Exception {
	// 图片上传
	// 设置图片名称,不能重复,可以使用uuid
	String picName = UUID.randomUUID().toString();

	// 获取文件名
	String oriName = pictureFile.getOriginalFilename();
	// 获取图片后缀
	String extName = oriName.substring(oriName.lastIndexOf("."));

	// 开始上传
	pictureFile.transferTo(new File("C:/upload/image/" + picName + extName));

	// 设置图片名到商品中
	item.setPic(picName + extName);
	// ---------------------------------------------
	// 更新商品
	this.itemService.updateItemById(item);

	return "forward:/itemEdit.action";
}

JSON数据交互

  1. @ResquestBody注解:
    RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容(json数据)转换为java对象并绑定到Controller方法的参数上
  2. @ResponseBody注解
    ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端。
  3. jar包
  4. 测试方法
@RequestMapping("testJson")
public @ResponseBody Item testJson(@RequestBody Item item) {
	return item;
}

***的执行规则

  1. preHandle按***定义顺序调用
  2. postHandler按***定义逆序调用
  3. afterCompletion按***定义逆序调用
  4. postHandler在***链内所有***返成功调用
  5. afterCompletion只有preHandle返回true才调用

***的方法

public class HandlerInterceptor1 implements HandlerInterceptor {
	// controller执行后且视图返回后调用此方法
	// 这里可得到执行controller时的异常信息
	// 这里可记录操作日志
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("HandlerInterceptor1....afterCompletion");
	}

	// controller执行后但未返回视图前调用此方法
	// 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		System.out.println("HandlerInterceptor1....postHandle");
	}

	// Controller执行前调用此方法
	// 返回true表示继续执行,返回false中止执行
	// 这里可以加入登录校验、权限拦截等
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		System.out.println("HandlerInterceptor1....preHandle");
		// 设置为true,测试使用
		return true;
	}
}

***的配置

<mvc:interceptors>
	<mvc:interceptor>
		<!-- 所有的请求都进入*** -->
		<mvc:mapping path="/**" />
		<!-- 配置具体的*** -->
		<bean class="tqb.interceptor.HandlerInterceptor1" />
	</mvc:interceptor>
	<mvc:interceptor>
		<!-- 所有的请求都进入*** -->
		<mvc:mapping path="/**" />
		<!-- 配置具体的*** -->
		<bean class="tqb.interceptor.HandlerInterceptor2" />
	</mvc:interceptor>
</mvc:interceptors>