SpringMVC
来源:互联网 发布:迅雷7优化版 编辑:程序博客网 时间:2024/06/08 02:51
SpringMVC介绍
简介
和Struts2一样 SpringMVC页是一个前端表现层框架,同时也可以说是spring的一个组件, springMVC完全诠释了MVC模式,在项目间的使用更加方便清晰。
MVC模式
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如同一批数据可以显示成不同的形态(表,饼状图,柱状图等),
M的作用就是处理数据逻辑,最后返回一组数据;
V的作用就是接受M的数据,并处理展示;
C的作用就是控制V和M的同步,实现M的数据变化后,V的视图(页面)也发生相应的改变
工作流程
SpringMVC和struts2对比的优缺点
1、Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC就容易实现restful url,而struts2的架构实现起来要费劲,因为Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。
2、由上边原因,SpringMVC的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架,方法之间不共享变量,而Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码 读程序时带来麻烦,每次来了请求就创建一个Action,一个Action对象对应一个request上下文。
3、由于Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。
4、 拦截器实现机制上,Struts2有以自己的interceptor机制,SpringMVC用的是独立的AOP方式,这样导致Struts2的配置文件量还是比SpringMVC大。
5、SpringMVC的入口是servlet,而Struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是servlet的一种特殊),这就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。
6、SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
7、SpringMVC验证支持JSR303,处理起来相对更加灵活方便,而Struts2验证比较繁琐,感觉太烦乱。
8、spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高(当然Struts2也可以通过不同的目录结构和相关配置做到SpringMVC一样的效果,但是需要xml配置的地方不少)。
9、 设计思想上,Struts2更加符合OOP的编程思想, SpringMVC就比较谨慎,在servlet上扩展。
10、SpringMVC开发效率和性能高于Struts2。
11、SpringMVC可以认为已经100%零配置。
SpringMVC和struts2和servlet的访问流程及实现原理对比
SpringMVC流程
- 用户发送请求至前端控制器DispatcherServlet
- DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
- DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
- 执行处理器(Controller,也叫后端控制器)。
- Controller执行完成返回ModelAndView
- HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- ViewReslover解析后返回具体View
- DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
- DispatcherServlet响应用户
Struts2
请求--->strutsPrepareAndExecuteFilter(doFilter)--->判断当次访问的路径是否是一个action(结果:若是,继续往核心走,结果:若不是,直接放行了)--->若是action继续往核心走-->拿到访问的路径和action之后--生成action的代理对象--->action执行类-->会判断是否有拦截器(若有拦截器,依次执行)-->若没有需要执行的拦截器了放行到action-->action执行-->找到执行的result-->执行指定的资源--->倒序执行拦截器链-->执行过滤器的放行后的操作--->web服务器(生成响应信息)
Servlet
SpringMVC和struts2和servlet的线程安全问题
Struts2
每个请求都对应一个action,所以基本不存在线程安全问题
struts 2的Action是多实例的并非单例,也就是每次请求产生一个Action的对象。原因是:struts 2的Action中包含数据,例如你在页面填写的数据就会包含在Action的成员变量里面。如果Action是单实例的话,这些数据在多线程的环境下就会相互影响,例如造成别人填写的数据被你看到了。所以Struts2的Action是多例模式的。
Servlet
servlet容器维护一个线程池,里面放着工作者线程来相应请求,同时还有一个调度线程来管理工作者线程。当容器收到一个servlet请求,调度线程就从线程池中取出一个工作者线程,该工作者线程将处理这个请求,做法是执行servlet的service方法;当这个线程执行时,收到另一个请求,调度线程就在线程池中取出另一个工作者线程来响应新的请求。容器不关心请求是否访问的是同一个servlet,当多个请求同时访问同一个servlet时,这个servlet的service方法将在多线程中并发执行。
SpringMVC
Spring MVC Controller默认是单例的:其实和servlet一样
单例的原因有二:
1、为了性能。
2、不需要多例。
1、这个不用废话了,单例不用每次都new,当然快了。
2、不需要的原因是看开发者怎么用,如果你给controller中定义很多的属性,那么单例肯定会出现竞争访问了。
因此,只要controller中不定义属性,那么单例完全是安全的。下面给个例子说明下:
@Controller
@RequestMapping("/demo/lsh/ch5")
@Scope("prototype")
public class MultViewController {
private static int st = 0; //静态的
private int index = 0; //非静态
@RequestMapping("/show")
public String toShow(ModelMap model) {
User user = new User();
user.setUserName("testuname");
user.setAge("23");
model.put("user", user);
return "/lsh/ch5/show";
}
@RequestMapping("/test")
public String test() {
System.out.println(st++ + " | " + index++);
return "/lsh/ch5/test";
}
}
0 | 0
1 | 0
2 | 0
3 | 0
4 | 0
改为单例的:
0 | 0
1 | 1
2 | 2
3 | 3
4 | 4
从此可见,单例是不安全的,会导致属性重复使用。
最佳实践:
1、不要在controller中定义成员变量。
2、万一必须要定义一个非静态成员变量时候,则通过注解@Scope("prototype"),将其设置为多例模式。
SpringMVC的组件说明
以下组件通常使用框架提供实现:
- DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
- HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
- Handler:处理器
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
- HandlAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
- View Resolver:视图解析器
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
- View:视图
springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
说明:在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。
需要用户开发的组件有handler、view
SpringMVC使用方法
环境的配置(SSM 整合)
第一步:配置前端控制器(web.xml)
<!--加载spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 前端控制器 -->
<servlet>
<servlet-name>springmvc</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>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!--解决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>
第二步:SpringMvcConfig.xml
<!--组件扫描 -->
<context:component-scanbase-package="controller"/>
<!--加载属性文件用来在controller -->
<context:property-placeholderlocation="classpath:resource.properties"/>
<!--视图解析器 -->
<beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver">
<propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/>
<!--路径前缀 -->
<propertyname="prefix"value="/WEB-INF/jsp/"/>
<!--路径后缀 -->
<propertyname="suffix"value=".jsp"/>
</bean>
<!--加载注解驱动 -->
<mvc:annotation-drivenconversion-service="conversionService"/>
<!--转换器配置 -->
<beanid="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<propertyname="converters">
<set>
<beanclass="convert.DateConverter"/>
</set>
</property>
</bean>
<!--配置多部件解析器(图片上传用) -->
<beanid="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置上传文件的最大尺寸为5MB -->
<propertyname="maxUploadSize">
<value>5242880</value>
</property>
</bean>
<!--异常处理器 -->
<!-- <bean id="handlerExceptionResolver" class="Exception.MyExceptionResolver"/> -->
<!--拦截器的配置,执行顺序是安装配置顺序执行 -->
<!--
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="Interceptor.HandlerInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors> -->
第三步:applicationContext.xml配置
<!-- dao -->
<!--引入属性配置文件 -->
<!--只能配置一次可以用*统配 -->
<context:property-placeholderlocation="classpath:*.properties"/>
<!--数据源配置 -->
<beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource">
<propertyname="driverClassName"value="${driver}"/>
<propertyname="url"value="${url}"/>
<propertyname="username"value="${name}"/>
<propertyname="password"value="liqichen"/>
<propertyname="maxActive"value="10"/>
<propertyname="maxIdle"value="5"/>
</bean>
<!--配置Mybatis的工厂 -->
<beanclass="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据源 -->
<propertyname="dataSource"ref="dataSource"/>
<!--配置Mybatis的核心配置文件所在位置 -->
<propertyname="configLocation"value="classpath:SqlMyBatisConfig.xml"/>
<!--配置pojo别名 -->
<propertyname="typeAliasesPackage"value="bean"></property>
</bean>
<beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer">
//配置包路径就行保证mapper和接口在一个包下
<propertyname="basePackage"value="BaseDictDao"/>
</bean>
<!-- service -->
<!--组件扫描器 -->
<context:component-scanbase-package="service"/>
<!--配置事物 -->
<!--事务管理器 -->
<beanid="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--数据源 -->
<propertyname="dataSource"ref="dataSource"/>
</bean>
<!--通知 -->
<tx:adviceid="txAdvice"transaction-manager="transactionManager">
<tx:attributes>
<!--传播行为 -->
<tx:methodname="save*"propagation="REQUIRED"/>
<tx:methodname="insert*"propagation="REQUIRED"/>
<tx:methodname="add*"propagation="REQUIRED"/>
<tx:methodname="create*"propagation="REQUIRED"/>
<tx:methodname="delete*"propagation="REQUIRED"/>
<tx:methodname="update*"propagation="REQUIRED"/>
<tx:methodname="find*"propagation="SUPPORTS"read-only="true"/>
<tx:methodname="select*"propagation="SUPPORTS"read-only="true"/>
<tx:methodname="get*"propagation="SUPPORTS"read-only="true"/>
</tx:attributes>
</tx:advice>
<!--切面 -->
<aop:config>
<aop:advisoradvice-ref="txAdvice"
pointcut="execution(* jd.service.*.*(..))"/>
</aop:config>
</beans>
第五步:Controller(web层)
在类上添加@Controller注解即可。在方法上加@RequestMapping注解指定请求的url,其中".action","/"可以加也可以不加。在ModelAndView对象中,将视图设置为返回视图的路径
@Controller
publicclass ItemController {
@RequestMapping("/itemList")
public ModelAndView itemList()throws Exception {
List<Items>itemList =new ArrayList<>();
//添加model
modelAndView.addObject("itemList",itemList);
//添加视图
modelAndView.setViewName("itemsList");
returnmodelAndView;
}
}
参数绑定
默认支持的参数类型
HttpServletRequest:通过request对象获取请求信息。
HttpServletResponse:通过response处理响应信息。
HttpSession:通过session对象得到session中存放的对象。
Model/ModelMap:ModelMap是Model接口的实现类,通过Model或ModelMap向页面传递数据,方法直接返回String代替View对象
基本类型绑定
说明
当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。从Request取参数的方法可以进一步简化。
@RequestMapping("/itemEdit")
public String itemEdit(Integerid, Modelmodel) {
Itemsitems =itemService.getItemById(id);
//向jsp传递数据
model.addAttribute("item",items);
//设置跳转的jsp页面
return"editItem";
}
支持的数据类型
参数类型推荐使用包装数据类型,因为基础数据类型不可以为null
整形:Integer、int
字符串:String
单精度:Float、float
双精度:Double、double
布尔型:Boolean、boolean
@RequestParam (形参描述,默认值和规定)
使用@RequestParam常用于处理简单类型的绑定。
参数属性:
value:参数名字,里边写的是请求传过来的参数名,作用是把参数名对应到形参名,解决参数和形参名不一致的问题。
required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报异常;
TTP Status 400 - Required Integer parameter 'XXXX' is not present
defaultValue:默认值,表示如果请求中没有同名参数时的默认值
POJO类型的绑定
普通POJO
如果提交的参数很多,或者提交的表单中的内容很多的时候可以使用pojo接收数据。要求pojo对象中的属性名和表单中input的name属性一致
包装POJO
包装对象定义如下:
Public classQueryVo {
private Itemsitems;
}
页面定义
<input type="text" name="items.name" />
<input type="text" name="items.price" />
Controller方法定义
public String useraddsubmit(Model model,QueryVoqueryVo)throws Exception{
System.out.println(queryVo.getItems());
数组类型绑定
例如前台传来多个id。可以采用两种方式接受
- 在形参中放入数组类型的参数 例 String[ ] ids
- 在POJO中设置数组类型的成员属性,把POJO放到形参中
List集合绑定
第一步:在POJO中设置相应参数的List集合属性,例: private List<Items> itemsList;
第二步:在页面中设置提交参数名称, Name属性必须是包装pojo的list属性+下标+元素属性
<tr>
<td>
<input type="text" name="itemsList[0].id" value="${item.id}"/>
</td>
<td>
<input type="text" name=" itemsList[0].name" value="${item.name }"/>
</td>
<td>
<input type="text" name=" itemsList[0].price" value="${item.price}"/>
</td>
</tr>
<tr>
<td>
<input type="text" name="itemsList[1].id" value="${item.id}"/>
</td>
<td>
<input type="text" name=" itemsList[1].name" value="${item.name }"/>
</td>
<td>
<input type="text" name=" itemsList[1].price" value="${item.price}"/>
</td>
</tr>
还可以这么写
<c:forEachitems="${itemList }"var="item"varStatus="status">
<tr>
<td>
<inputtype="checkbox"name="ids"value="${item.id }">
<inputtype="hidden"name="itemList[${status.index }].id"value="${item.id }">
</td>
<td><inputtype="text"name="itemList[${status.index }].name"value="${item.name }"></td>
<td><inputtype="text"name="itemList[${status.index }].price"value="${item.price }"></td>
<td><inputtype="text"name="itemList[${status.index }].createtime"value="<fmt:formatDatevalue="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"></td>
<td><inputtype="text"name="itemList[${status.index }].detail"value="${item.detail }"></td>
<td><ahref="${pageContext.request.contextPath }/item/itemEdit.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
varStatus属性常用参数总结下:
${status.index} 输出行号,从0开始。
${status.count} 输出行号,从1开始。
${status.current} 当前这次迭代的(集合中的)项
${status.first} 判断当前项是否为集合中的第一项,返回值为true或false
${status.last} 判断当前项是否为集合中的最后一项,返回值为true或false
begin、end、step分别表示:起始序号,结束序号,跳跃步伐。
解决post乱码问题
在web.xml中加入:
<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>
解决get乱码问题
String userName =new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
自定义参数绑定
由于日期数据有很多种格式,所以springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适配,并对方法中的形参进行参数绑定。在springmvc这可以在处理器适配器上自定义Converter进行参数绑定。如果使用<mvc:annotation-driven/>可以在此标签上进行扩展。
自定义Converter
publicclass DateConverterimplements Converter<String, Date> {
@Override
public Date convert(Stringsource) {
SimpleDateFormatsimpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
returnsimpleDateFormat.parse(source);
}catch (ParseExceptione) {
e.printStackTrace();
}
returnnull;
}
}
Converter<String, Date>表示string转Date类型。
配置Converter
<!-- 加载注解驱动 -->
<mvc:annotation-drivenconversion-service="conversionService"/>
<!-- 转换器配置 -->
<beanid="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<propertyname="converters">
<set>
<beanclass="cn.jd.springmvc.convert.DateConverter"/>
</set>
</property>
</bean>
@RequestMapping注解详解
Value属性:可以配置多个url到同一个方法
@RequestMapping(value={"queryitem","itemEdit","itemList"})
Method属性:可以限定请求方法(默认不限定请求方法)
@RequestMapping(value={"queryitem","itemEdit","itemList"},method=RequestMethod.POST)
可以加在类上
@RequestMapping("item")
publicclass ItemController {
产生多级url 必须先访问item 在访问下边的requestMapping的路径
Controller方法的返回值(重定向,转发)
ModelAndView
String(代表逻辑视图)
重定向
请求转发
加/是在项目名后找起
不加/是相对目录直接替换最后边的
Void
使用原始的HttpServletRequest 或 HttpServletResponse 原始方式
图片上传
配置虚拟目录
在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:
<Context docBase="F:\develop\upload\temp" path="/pic" reloadable="false"/>
访问http://localhost:8080/pic即可访问F:\develop\upload\temp下的图片。
也可以通过eclipse配置:
jar包
配置解析器(springMVC.xml)
<!--配置多部件解析器(图片上传用) -->
<beanid="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置上传文件的最大尺寸为5MB -->
<propertyname="maxUploadSize">
<value>5242880</value>
</property>
</bean>
Controller编写
在形参中放入MultipartFile类型参数,形参名和前台input标签名一样
@RequestMapping(value={"edit"})
public String edit(Itemsitems, MultipartFilepictureFile) throws Exception{
//原始文件名
StringoldName=pictureFile.getOriginalFilename();
//新文件名
StringnewName=UUID.randomUUID().toString()+oldName.substring(oldName.lastIndexOf("."));
//上传路径
FileuploadPic=new File("F:/img/"+newName);
//判断路径是否存在
if (!uploadPic.exists()) {
uploadPic.mkdirs();
}
//向磁盘写文件
pictureFile.transferTo(uploadPic);
return"editItem";
}
页面编写
在from表单中写入属性enctype="multipart/form-data"
<formid="itemForm" action="${pageContext.request.contextPath }/edit.action"
method="post"enctype="multipart/form-data">
添加file标签
<input type="file" name="pictureFile"/>
注意
使用ajax上传需要添加以下meta,否则会报错
<meta http-equiv="Content-Type" content="multipart/form-data; charset=utf-8" />
Json数据交互
@RequestBody
@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。
@ResponseBody
该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
例:
@RequestMapping("/editItemSubmit_RequestJson")
public@ResponseBody Items editItemSubmit_RequestJson(@RequestBody Items items) throws Exception {
System.out.println(items);
returnitems;
}
配置json转换器
注意:如果使用<mvc:annotation-driven /> 则不用定义下边的内容。
在注解适配器中加入messageConverters
<!--注解适配器 -->
<beanclass="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<propertyname="messageConverters">
<list>
<beanclass="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean>
RESTful支持
Restful是一个资源定位及资源操作的风格,不是标准也不是协议。
应用例子:RESTful方式实现商品信息查询,返回json数据
添加DispatcherServlet的rest配置
<servlet>
<servlet-name>springmvc-servlet-rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc-servlet-rest</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
/是拦截除了jsp的所有,/*是拦截所有
URL 模板模式映射
@RequestMapping(value="/viewItems/{id}"):{×××}占位符,请求的URL可以是"/viewItems/1"或"/viewItems/2",通过在方法中使用@PathVariable获取{×××}中的×××变量。
@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。
@RequestMapping("/viewItems/{id}")
public @ResponseBody viewItems(@PathVariable("id") String id,Model model) throws Exception{
//方法中使用@PathVariable获取useried的值,使用model传回页面
//调用 service查询商品信息
ItemsCustom itemsCustom =itemsService.findItemsById(id);
return itemsCustom;
}
如果RequestMapping中表示为"/viewItems/{id}",id和形参名称一致,@PathVariable不用指定名称。
静态资源访问<mvc:resources>
如果在DispatcherServlet中设置url-pattern为 /则必须对静态资源进行访问处理。
spring mvc 的<mvc:resources mapping="" location="">实现对静态资源进行映射访问。
如下是对js文件访问配置:
<mvc:resources location="/js/" mapping="/js/**"/>
异常处理器
自定义异常类
为了区别不同的异常通常根据异常类型自定义异常类,这里我们创建一个自定义系统异常,如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息
自定义异常处理器
publicclass CustomExceptionResolverimplements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
ex.printStackTrace();
CustomException customException =null;
//如果抛出的是系统自定义异常则直接转换
if(exinstanceof CustomException){
customException = (CustomException)ex;
}else{
//如果抛出的不是系统自定义异常则重新构造一个系统错误异常。
customException =new CustomException("系统错误,请与系统管理员联系!");
}
ModelAndViewmodelAndView =new ModelAndView();
modelAndView.addObject("message", customException.getMessage());
modelAndView.setViewName("error");
returnmodelAndView;
}
}
异常处理器配置
在springMVC.xml中加入
<bean id="handlerExceptionResolver" class="Exception.MyExceptionResolver"/>
拦截器
定义拦截器
publicclass HandlerInterceptor1implements HandlerInterceptor{
/**
* controller执行后且视图返回后调用此方法
*这里可得到执行controller时的异常信息
*这里可记录操作日志,资源清理等
*/
@Override
publicvoid afterCompletion(HttpServletRequestarg0, HttpServletResponse arg1, Objectarg2, Exceptionarg3)
throws Exception {
System.out.println("1执行后");
}
/**
* controller执行后但未返回视图前调用此方法
*这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
*/
@Override
publicvoid postHandle(HttpServletRequestarg0, HttpServletResponse arg1, Objectarg2, ModelAndViewarg3)
throws Exception {
System.out.println("1执行中");
}
/**
* controller执行前调用此方法
*返回true表示继续执行,返回false中止执行
*这里可以加入登录校验、权限拦截等
*/
@Override
publicboolean preHandle(HttpServletRequestarg0, HttpServletResponse arg1, Objectarg2)throws Exception {
System.out.println("1执行前");
returntrue;
}
}
配置拦截器
<!--拦截器的配置,执行顺序是安装配置顺序执行 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mappingpath="/**"/>
<beanclass="Interceptor.HandlerInterceptor1"/>
<beanclass="Interceptor.HandlerInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
- SpringMVC
- springmvc
- SpringMVC
- SpringMVC
- springMvc
- springMVC
- springmvc
- springMVC
- springMVC
- springmvc
- SpringMVC
- SpringMVC
- springMvc
- springmvc
- springmvc
- SpringMVC
- Springmvc
- springmvc
- jsp页面登录超时页面嵌套解决办法
- RabbitMQ -- 安装及配置
- 动态规划——单调递增最长子序列
- IDEA断点过一次后失效
- 常用IO系统调用函数
- SpringMVC
- Netty4 学习笔记之四: Netty HTTP服务的实现
- SVN定时自动更新
- 计算机开机过程
- 百度编辑器ueditor插入表格没有边框,没有颜色的解决方法
- Android LocationManager的getLastKnowLocation方法异常解决
- xxx.app文件已损坏,打不开,解决方案
- 查询数据库的数据忽略大tetime类型的时分秒
- 大数据七大趋势 第一个趋势是物联网