Spring MVC 入门
1、发起请求到前端控制器(DispacherServlet)
2、前端控制器请求HandlerMapping查找Handler
可以根据xml配置、注解进行查找
3、处理器映射器HandlerMapping向前端控制器返回Handler
4、前端控制器调用处理器适配器执行Handler
5、处理器适配器执行Handler
6、Hanler执行完向适配器返回ModelAndView
7、处理器适配器向前端控制器返回ModelAndView
8、前端控制器请求视图解析器进行视图解析
9、视图解析器向前端控制器返回View
10、前端控制器进行视图渲染
11、前端控制器向用户响应结果
二、SpringMVC环境搭建
1、建立如下目录
2、导入和spring相关的jar包
3、在web.xml文件中配置SpringMVC前端控制器
<!-- 配置前端控制器DispatcherServlet --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 初始化参数配置 contextConfigLocation配置springmvc加载的配置文件(配置HandlerMapping、HandlerAdapter) 如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 第一种:*.action,访问.action结尾的DispatcherServlet解析 第二种:/,访问所有的地址,都由DispatcherServlet解析,对于静态文件需要配置不让其解析 第三种:/*,struts习惯使用,springmvc不管用,使用这种配置,最终要转发到一个jsp页面时, 仍然由DispatcherServlet解析jsp地址,不能根据jsp地址转到Handler,会报错 --> <url-pattern>*.action</url-pattern> </servlet-mapping>
4、在创建的springmvc.xml中配置HandlerMapping(C)、HandlerAdapter(M)、ViewResolver(V)
<!-- 配置Handler --> <bean name="/itemController.action" class="cn.itcast.ssm.controller.ItemController"></bean> <!-- 简单控制器处理器适配器 (HandlerAdapter) 所有的适配器都实现HandlerAdapter接口 --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean> <!-- 配置处理器映射器 (HandlerMapping) 将Handler(Controller)的Bean的name作为url进行查找,需要在配置Handler时指定name public class org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter implements org.springframework.web.servlet.HandlerAdapter { public boolean supports(java.lang.Object handler); } --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> <!-- 配置视图解析器(ViewResover),这里解析默认用jstl标签,所以注意:classpath下面是否导入jstl相关包--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>
5、编写名叫ItemController的Handler
package cn.itcast.ssm.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class ItemController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
List list = new ArrayList();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("itemList",list);
modelAndView.setViewName("/WEB-INF/jsp/jsp1/index.jsp");
return modelAndView;
}
}
三、使用非注解的HandlerAdapter和HandlerMapping
1、HandlerMapping
<!-- ================非注解的HandlerMapping ================= --> <!-- 第一种:<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean> 第二种:<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"></bean>
--> <bean id="itemController" name="/itemController.action" class="cn.itcast.ssm.controller.ItemController"></bean> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mapping"> <props> <!--<prop key="/***.action">controller的bean的Id</prop>--> <prop key="/itemController1.action">itemController</prop> <prop key=""></prop> </props> </property> </bean>
多个映射器可以并存,例如:/itemController.action,/itemController1.action指向同一个Bean,但此时两个地址都可以正常访问。
2、HandlerAdapter
<!-- ================非注解的HandlerAdapter ================= --> <!-- 第一种:<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
要求Handler/Controller的Bean实现Controller接口 第二种:<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean> 要求Handler/Controller实现org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter接口 --> <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean> <bean id="itemController2" class="cn.itcast.ssm.controller.ItemController2"></bean> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mapping"> <props> <!--<prop key="/***.action">controller的bean的Id</prop>--> <prop key="/itemController1.action">itemController</prop> <prop key="/itemController2.action">itemController2</prop> </props> </property> </bean>
ItemController.java源文件,如图
以上Handler中有一个弊端,就是一个Handler(Controller)中只有一个方法。
四、注解的HandlerAdapter和HandlerMapping
在spring3.1之后才使用下面的注解
添加注解驱动配置
<!-- ================注解的HandlerAdapter ================= --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.class"></bean> <!-- ================注解的HandlerMapping ================= --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.class"></bean>
这里的代码在程序开发时,通常会用下面的代码替换
<!-- springmvc 注解驱动,配置下面这行代码,上面两行代码不再需要配置 --> <mvc:annotation-driven />
创建Controller名叫ItemController3.java
package cn.itcast.ssm.controller; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class ItemController3 { //这里的url可以为"/queryItems","/queryItems.action" @RequestMapping("/queryItems") public ModelAndView queryItems(){ List list = new ArrayList(); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("itemList", list); return modelAndView; } }
添加组件扫描Controller的配置文件
<!-- 这里使用组件扫描controller包,以后还可以扫描Service....等 -->
<context:component-scan base-package="cn.itcast.ssm.controller" />
五、视图解析器
为了简化 modelAndView.setViewName("/WEB-INF/jsp/jsp1/index.jsp"); 地址,采用前缀和后缀
用下面代码替换前面的视图解析器的配置
<!-- 配置视图解析器(ViewResover) -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/jsp1/"/>
<property name="suffix" value=".jsp"/>
</bean>
六、SpringMVC整合MyBatis
面试题:在SpringMVC中spring的作用是什么?
Spring将SpringMVC的各层进行整合
1、spring对持久层的Mapper接口进行管理
2、spring对业务层的Service进行管理,可以调用Mapper接口
3、spring对表现层的Handler进行管理,可以调用Service
4、Spring在业务层进行事务处理。
具体步骤如下:
1、整合DAO层
mybatis和Spring整合,通过Spring管理mapper接口
使用Mapper扫描器自动扫描包
2、整合Service层
使用配置方式将Service接口配置在spring配置文件中
3、整合Springmvc,由于它是Spirng的模块,所以不需要整合。
sringmvc.xml配置文件部分如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd"> <context:annotation-config /> <context:component-scan base-package="cn.com" /> <tx:annotation-driven transaction-manager="transactionManager" /> <mvc:annotation-driven /> <aop:aspectj-autoproxy proxy-target-class="true" /> <!-- annotation的方法映射适配器 --> <bean id="handlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <!-- annotation默认的方法映射适配器 --> <!-- <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> --> <!-- <property name="order" value="1" /> --> <!-- </bean> --> <!-- 静态文件 --> <mvc:resources location="/assets/" mapping="/assets/**"></mvc:resources> <!-- 跳转文件的前后缀 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/view/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- ================mvc ================= --> <!-- ==================spring context=============== --> <!-- 引入配置文件 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>WEB-INF/conf/jdbc.properties</value> <!-- <value>WEB-INF/conf/conf.properties</value> --> </list> </property> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <!-- 初始化连接大小 --> <property name="initialSize" value="${initialSize}"></property> <!-- 连接池最大数量 --> <property name="maxActive" value="${maxActive}"></property> <!-- 连接池最大空闲 --> <property name="maxIdle" value="${maxIdle}"></property> <!-- 连接池最小空闲 --> <property name="minIdle" value="${minIdle}"></property> <!-- 获取连接最大等待时间 --> <property name="maxWait" value="${maxWait}"></property> </bean> <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 自动扫描mapping.xml文件 --> <property name="mapperLocations" value="classpath:mapper/*.xml"></property> </bean> <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> <property name="basePackage" value="cn.com.**.dao" /> <property name="properties"> <value>mappers=cn.com.common.ssm.engine.mapper.BaseDao</value> </property> </bean> <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
<!-- 通知,限定业务层Service的方法名必须以下面的开头,并通知给事务管理器 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- aop配置,因为AOP要调用通知
execution(* cn.itcast.ssm.service.impl.*.*(..)),表示
按照cn.itcast.ssm.service.impl所有的类名所有的方法名,(..)表示不管什么参数
-->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.itcast.ssm.service.impl.*.*(..))"/>
</aop:config>
<!-- shiro --> <bean id="myRealm" class="cn.com.security.shiro.CustomRealm" /> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm" /> </bean> <!-- Shiro过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- Shiro的核心安全接口,这个属性是必须的 --> <property name="securityManager" ref="securityManager" /> <!-- 身份认证失败,则跳转到登录页面的配置 --> <property name="loginUrl" value="login.do" /> <!-- 权限认证失败,则跳转到指定页面 --> <property name="unauthorizedUrl" value="/unauthor.jsp" /> <!-- Shiro连接约束配置,即过滤链的定义 --> <property name="filterChainDefinitions"> <value> /login.do=anon /**/*.do=authc </value> </property> </bean> <!-- 保证实现了Shiro内部lifecycle函数的bean执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- 开启Shiro注解 --> <!-- <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" /> --> <!-- <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> --> <!-- <property name="securityManager" ref="securityManager" /> --> <!-- </bean> --> </beans>
在web.xml中配置前端控制器和加载Spring容器
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <!-- 前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 初始化参数配置 contextConfigLocation配置springmvc加载的配置文件(配置HandlerMapping、HandlerAdapter) 如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 第一种:*.action,访问.action结尾的DispatcherServlet解析 第二种:/,访问所有的地址,都由DispatcherServlet解析,对于静态文件需要配置不让其解析 第三种:/*,struts习惯使用,springmvc不管用,使用这种配置,最终要转发到一个jsp页面时, 仍然由DispatcherServlet解析jsp地址,不能根据jsp地址转到Handler,会报错 --> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- 加载Spring容器 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/Classes/spring/application-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
七、注解列举、参数绑定
1、@RequestMapping(),请求映射
特性:url映射,限制请求方式
@RequestMapping("/editItems")
@RequestMapping(value="/editItems",method = RequestMethod.GET)
@RequestMapping(value="/editItems",method = {RequestMethod.GET,RequestMethod.POST})
2、Controller方法的返回值
第一种:ModelAndView , model和View需要分别设置
ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("itemCustom",itemCustom); modelAndView.setViewName("/WEB-INF/jsp/jsp1/editItem.jsp");
第二种:string,表示返回的是逻辑视图名,真正的视图名:jsp路径 + 前缀+视图名+后缀
@RequestMapping(value="/editItems",method={RequestMethod.GET,RequestMethod.POST}) public String editItems(Model model) throws Exception{ //通过方法的形参表示ModelAndView中的Model ItemCustom itemCustom = itemService.findItemById(1); model.addAttribute("itemCustom",itemCustom); return "/WEB-INF/jsp/jsp1/editItem.jsp"; }
页面重定向redirect
特定:url地址发生改变、request不可以共享
@RequestMapping("/editItemSubmit") public String editItemSubmit(){ //重定向,因为在同一controller中不需要添加绝对路径 return "redirect:success.action"; }
页面转发forward
特点:url地址不改变、request可以共享
@RequestMapping("/editItemSubmit") public String editItemSubmit(){ //重定向,因为在同一controller中不需要添加绝对路径 return "forward:success.action"; }
第三种:void
在Controller方法的形参上定义request和response,使用它们指定相应结果:
@RequestMapping("/editItemSubmit") public String editItemSubmit(HttpServletRequest request, HttpServletResponse response){ //request实现转发 request.getRequestDispathcer("页面路径").forward(request,response); //request重定向 request.sendRedirect("页面路径"); //Response相应结果,例如:json response.setCharacterEncoding("utf-8"); response.SetContentType("application/json;charset=utf-8"); response.getWriter().write("json串"); }
3、参数绑定和参数绑定的组件Converter(转换器)
- 默认支持的参数类型转换包含:
1、HttpServletRequest
2、HttpServletResponse
3、HttpSession
4、Model(接口)/ ModelMap(Model的实现类) :作用:将model数据填充到Request域
- 自定义参数绑定,实现日期格式的绑定
要求:自定义参数绑定要和pojo中的成员变量属性的类型保持一致
步骤:1、在web.xml的注解驱动中添加如下代码
<mvc:annotation-driven conversion-service="conversionService"/> <!-- 自定义参数类型转换器 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionService"> <property name="converters"> <list> <bean class="cn.itcast.ssm.controller.CustomDateConverter"></bean> <bean class=""></bean> </list> </property> </bean>
2、创建自定义的Controller转换器并且实现org.springframework.core.convert.converter.Converter接口,例如:CustomDateConverter
package cn.itcast.ssm.controller; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.core.convert.converter.Converter; public class CustomDateConverter implements Converter<String, Date> { @Override public Date convert(String arg0) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:sss"); try { return simpleDateFormat.parse(arg0); } catch (ParseException e) { e.printStackTrace(); } return null; } }
4、简单类型
@RequestParam,接收请求参数
public String editItemSubmit(@RequestParam("id") Integer item_id) public String editItemSubmit(@RequestParam(value="id",required=true,defaultValue="1") Integer item_id)
5、pojo绑定,要求表单的name属性值必须和pojo的成员变量属性名保持一致。
6、@ModelAttribute
·· 1、做数据回显,如下:
//@ModelAttribute可以指定pojo回显到页面中的request的key, //这样页面显示调用方法:item.name,此时requst域中的key值不再必须是和pojo的类型(首字符小写)保持一致 public String saveEmployeeAction( @ModelAttribute("item") @Validated(value={ValidationGroup1.class}) Item item, BindingResult bindingResult, Model model) {}
2、将方法的返回值返回到页面
八、校验器的配置
- 不同Controller中同一方法校验
1、在Springmvc.xml文件中添加校验器的相关配置
<mvc:annotation-driven validator="validator" /> <!-- 校验器配置 在注解驱动中添加 validator="validator" --> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <property name="providerClass" value="org.hibernate.validator.HibernateValidator" /> <!--不设置则默认为classpath下的ValidationMessages.properties --> <property name="validationMessageSource" ref="validatemessageSource" /> </bean>
<!--错误信息的配置文件--> <bean id="validatemessageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename"> <list> <value>classpath:validatemessages</value> </list> </property> <property name="fileEncodings" value="utf-8" />
<!--文件缓存时间--> <property name="cacheSeconds" value="120" /> </bean>
2、创建错误信息文件validatemessages.properties添加错误信息
#错误校验信息 item.name.length.error=请输入1-30的字符长度 item.name.isNull.error=不能为空
3、在实体类的属性前面添加如下校验
//验证字符长度 @Size(min=1,max=30,message="{item.name.length.error}") //非空校验 @NotNull(message="{item.name.isNull.error}") private String itemName;
Bean Validation 中内置的 constraint 2 @Null 被注释的元素必须为 null 3 @NotNull 被注释的元素必须不为 null 4 @AssertTrue 被注释的元素必须为 true 5 @AssertFalse 被注释的元素必须为 false 6 @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 7 @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 8 @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 9 @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 10 @Size(max=, min=) 被注释的元素的大小必须在指定的范围内 11 @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内 12 @Past 被注释的元素必须是一个过去的日期 13 @Future 被注释的元素必须是一个将来的日期 14 @Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式 15 16 Hibernate Validator 附加的 constraint 17 @NotBlank(message =) 验证字符串非null,且长度必须大于0 18 @Email 被注释的元素必须是电子邮箱地址 19 @Length(min=,max=) 被注释的字符串的大小必须在指定的范围内 20 @NotEmpty 被注释的字符串的必须非空 21 @Range(min=,max=,message=) 被注释的元素必须在合适的范围内
4、在Controller中添加校验
@RequestMapping(value = "save", method = RequestMethod.POST) //在需要校验的pojo前添加@Validated注解,在后面添加BindingResult接收校验参数 //@Validated和BindingResult是配对出现的并且位置是固定的,不能修改,多个参数需要校验,必须按照这样的位置处理 public String saveEmployeeAction(@Validated Item item, BindingResult bindingResult, Model model) { //获取校验信息 if (bindingResult.hasErrors()) { List<ObjectError> allErrors = bindingResult.getAllErrors(); for(ObjectError objectError : allErrors){ System.out.println(objectError.getDefaultMessage()); } return "empSave"; } model.addAttribute("allError", allErrors); return "empSaveSuccess"; }
5、jsp页面上进行遍历输出即可。
- 分组校验,不同Controller采用不同方法校验
1、新建接口文件
目录结构如下:
2、在javaBean修改为如下代码
//验证字符长度 //groups表示校验属于哪个分组 @Size(min=1,max=30,message="{item.name.length.error}",groups={ValidationGroup1.class})
3、在Controller中指定使用哪个分组
public String saveEmployeeAction(@Validated(value={ValidationGroup1.class}) Item item, BindingResult bindingResult, Model model) {
九、异常处理
1、自定义异常处理类CustomException
2、编写自定义异常解析器CustomExceptionResolver
package cn.itcast.ssm.exception; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; public class CustomExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception ex) { // TODO Auto-generated method stub //判断异常是否是自定义的异常 CustomException customException = null; if(ex instanceof CustomException){ ex = (CustomException)ex; }else{ customException = new CustomException("未知错误"); } String message = customException.getMessage(); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("message", message); modelAndView.setViewName("error"); return null; } }
3、配置全局异常处理器
<!-- 配置全局异常处理器 -->
<bean class="cn.itcast.ssm.exception.CustomExceptionResolver"></bean>
十、文件上传
1、导入jar包
2、在SpringMVC.xml文件中添加文件解析器的配置
<!-- 配置文件解析器,用于文件上传 -->
<bean id="commonsMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 这里指定为5M -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
3、在Controller中添加上传代码
//MultipartFile item_pic 绑定图片,用于上传图片 public String saveEmployeeAction( @ModelAttribute("item") @Validated(value={ValidationGroup1.class}) Item item, BindingResult bindingResult, Model model ,MultipartFile item_pic) throws Exception, IOException { //获取校验信息 if (bindingResult.hasErrors()) { List<ObjectError> allErrors = bindingResult.getAllErrors(); for(ObjectError objectError : allErrors){ System.out.println(objectError.getDefaultMessage()); } return "empSave"; } //获取文件名 String originalFilename = item_pic.getOriginalFilename(); //生成新的文件名 String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf(".")); //指定文件上传路径 String filePath = ""; File file = new File(filePath + newFileName); //上传文件,将内存数据写入到磁盘 item_pic.transferTo(file); //修改数据库文件的路径,通过设置POJO类的属性完成 //...... model.addAttribute("emp", item); return "empSaveSuccess"; }
十一、json解析
1、导jar包
2、在SpringMVC.xml配置json转换器,如果用了mvc注解驱动,则可以不再配置一下的json转换器
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" p:ignoreDefaultModelOnRedirect="true"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> </list> </property> </bean>
3、在形参起前面添加@RequestBody,在方法的返回类型前面添加@ResponseBody
十二、RestFul前端控制器配置
- 对静态资源访问
十三、拦截器
1、preHandle、postHandle、afterCompleted方法
2、拦截器的配置
3、拦截器的执行结果
1、拦截器1、2都放行
2、拦截1放行、2不放行
3、两个都不放行
十四、乱码的解决方案
1、post乱码
在web.xm中添加filter过滤器
<!-- 解决post乱码,添加过滤器 --> <filter> <filter-name>Encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter.class</filter-class> </filter> <filter-mapping> <filter-name>Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
SpringMVC和Strus2的区别
1、Springmvc 面向方法开发的,Struts2面向类开发的
2、Springmvc是单例的,Struts2是多例开发的