SpringMVC属于Spring全家桶中的一员,作用于web层,Spring准确的来说可以支持一个项目的各个层,SpringMVC的三大组件为处理器映射器、处理器适配器、视图解析器,需要用户完成的组件是Handler和View
SpringMVC工作流程
SpringMVC架构
SpringMVC入门
- jar包依赖
- 前端控制器的配置(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>
- 开启注解扫描(非必须,目的为开发过程注入属性更加的方便)
<!-- 开启注解扫描 -->
<context:component-scan base-package="tqb.controller"></context:component-scan>
- 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包)
- 处理器映射器(过时)
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
- 处理器适配器(过时)
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
- 视图解析器
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
重新注册适配器和映射器
- 通过bean标签注册
<!-- 处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<!-- 处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
- 通过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整合
- Dao层
1) sqlMapConfig.xml:别名等等
2)applicationContext-dao.xml:数据库连接池、SqlSessionFactory、mapper文件扫描器 - Service层
1)applicationContext-service:扫描Service层
2)applicationContext-transaction:配置事务 - Controller层
1)springmvc.xml:扫描Controller层、配置注解扫描、配置视图解析器、配置处理器
2)web.xml:配置前端控制器、配置Spring
参数绑定
- 默认参数
@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;
}
- 简单参数
@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;
}
- POJO
解决乱码问题
- 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>
- 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中方法的三种返回值
- ModelAndView:耦合度高,方便
- String:方法携带参数Model ,返回值返回的是视图名称,通过Model实现域的功能,耦合度低,官方推荐
返回值中携带转发或重定向
return "forward:index.jsp"
return "redirect:index.jsp"
- void:Ajax
异常处理器
- 自定义异常处理器
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;
}
}
- 异常处理器配置(在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数据交互
- @ResquestBody注解:
RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容(json数据)转换为java对象并绑定到Controller方法的参数上 - @ResponseBody注解
ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端。 - jar包
- 测试方法
@RequestMapping("testJson")
public @ResponseBody Item testJson(@RequestBody Item item) {
return item;
}
***的执行规则
- preHandle按***定义顺序调用
- postHandler按***定义逆序调用
- afterCompletion按***定义逆序调用
- postHandler在***链内所有***返成功调用
- 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>