码迷,mamicode.com
首页 > 编程语言 > 详细

SpringMVC.zzh

时间:2018-09-06 22:55:58      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:scroll   list()   页面   修改   date()   span   多个   存储   解决乱码   

SpringMVC概述

1、MVC:Model-View-Control
框架性质的C 层要完成的主要工作:封装web 请求为一个数据对象、调用业务逻辑层来处理数据对象、 返回处理数据结果及相应的视图给用户    
2、简要概述SpringMVC
Spring C层框架的核心是DispatcherServlet,它的作用是将请求分发给不同的后端处理器,也即是用了一种被称为Front Controller 的模式。Spring的C层框架使用了处理器适配器,处理器映射器和视图解析器来共同完成C 层框架的主要工作。并且spring的C层框架还真正地把业务层处理的数据结果和相应的视图拼成一个对象,即会经常用到的ModelAndView对象,SpringMVC处理流程如下图:
技术分享图片

SpringMVC与Struts2的不同

1、springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过滤器
2、springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例
3、 Struts采用值栈存储请求和响应的数据,通过OGNL存取数据, springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过request域传输到页面。Jsp视图解析器默认使用jstl


SpringMVC入门程序

springmvc与struts2不同的一点就是springmvc中的入口是servlet(org.springframework.web.servlet.DispatcherServlet),而struts2的入口是filter(org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter)

首先需要在web.xml文件中配置前端控制器
  <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>
12
 
1
  <servlet>
2
    <servlet-name>springmvc</servlet-name>
3
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
4
    <init-param>
5
        <param-name>contextConfigLocation</param-name>
6
        <param-value>classpath:springmvc.xml</param-value>
7
    </init-param>
8
  </servlet>
9
  <servlet-mapping>
10
    <servlet-name>springmvc</servlet-name>
11
    <url-pattern>*.action</url-pattern>
12
  </servlet-mapping>

创建ItemController:

ItemController是一个普通的java类,不需要实现任何接口,需要在类上添加@Controller注解,这样做的原因是把Controller交由Spring管理,在方法上面添加@RequestMapping注解,里面指定请求的url,其中“.action”可以加也可以不加

@Controller
public class ItemController {

	// @RequestMapping:里面放的是请求的url,和用户请求的url进行匹配
	// action可以写也可以不写
	@RequestMapping("/itemList.action")
	public ModelAndView queryItemList() {
		//创建页面需要显示的商品数据
		List<Items> list = new ArrayList<>();
		list.add(new Items(1, "1华为 荣耀8", 2399f, new Date(), "质量好!1"));
		list.add(new Items(2, "2华为 荣耀8", 2399f, new Date(), "质量好!2"));
		list.add(new Items(3, "3华为 荣耀8", 2399f, new Date(), "质量好!3"));
		list.add(new Items(4, "4华为 荣耀8", 2399f, new Date(), "质量好!4"));
		list.add(new Items(5, "5华为 荣耀8", 2399f, new Date(), "质量好!5"));
		list.add(new Items(6, "6华为 荣耀8", 2399f, new Date(), "质量好!6"));

		// 创建ModelAndView,用来存放数据和视图
		ModelAndView modelAndView = new ModelAndView();
		// 设置数据到模型中
		modelAndView.addObject("list", list);
		// 设置视图jsp,需要设置视图的物理地址
		modelAndView.setViewName("/jsp/itemList.jsp");

		return modelAndView;
	}
}
27
 
1
@Controller
2
public class ItemController {
3
4
    // @RequestMapping:里面放的是请求的url,和用户请求的url进行匹配
5
    // action可以写也可以不写
6
    @RequestMapping("/itemList.action")
7
    public ModelAndView queryItemList() {
8
        //创建页面需要显示的商品数据
9
        List<Items> list = new ArrayList<>();
10
        list.add(new Items(1, "1华为 荣耀8", 2399f, new Date(), "质量好!1"));
11
        list.add(new Items(2, "2华为 荣耀8", 2399f, new Date(), "质量好!2"));
12
        list.add(new Items(3, "3华为 荣耀8", 2399f, new Date(), "质量好!3"));
13
        list.add(new Items(4, "4华为 荣耀8", 2399f, new Date(), "质量好!4"));
14
        list.add(new Items(5, "5华为 荣耀8", 2399f, new Date(), "质量好!5"));
15
        list.add(new Items(6, "6华为 荣耀8", 2399f, new Date(), "质量好!6"));
16
17
        // 创建ModelAndView,用来存放数据和视图
18
        ModelAndView modelAndView = new ModelAndView();
19
        // 设置数据到模型中
20
        modelAndView.addObject("list", list);
21
        // 设置视图jsp,需要设置视图的物理地址
22
        modelAndView.setViewName("/jsp/itemList.jsp");
23
24
        return modelAndView;
25
    }
26
}
27

SpringMVC架构

1、框架架构如下:
技术分享图片

2、架构的具体流程:

1、用户发送请求至前端控制器DispatcherServlet

2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet

4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器

5、执行处理器(Controller,也叫后端控制器)

6、Controller执行完成返回ModelAndView

7、HandlerAdaptercontroller执行结果ModelAndView返回给DispatcherServlet

8、DispatcherServletModelAndView传给ViewReslover视图解析器

9、ViewReslover解析后返回具体View

10、DispatcherServletView进行渲染视图(即将模型数据填充至视图中)

11、DispatcherServlet响应用户


3、组件说明

以下组件通常使用框架提供实现:

uDispatcherServlet:前端控制器

用户请求到达前端控制器,它就相当于mvc模式中的cdispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。

uHandlerMapping:处理器映射器

HandlerMapping负责根据用户请求url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

uHandler:处理器

Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。

由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler

uHandlAdapter:处理器适配器

通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。

下图是许多不同的适配器,最终都可以使用usb接口连接

技术分享图片

uViewResolver:视图解析器

View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。

uView:视图

springmvc框架提供了很多的View视图类型的支持,包括:jstlViewfreemarkerViewpdfView等。我们最常用的视图就是jsp

一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。

说明:在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。

需要用户开发的组件有handlerview


SpringMVC三大组件

1、由于处理器映射器和处理器适配器已经不再由spring默认配置了,因此我们需要在springmvc.xml中手动配置这两个组件的bean
2、使用注解驱动后,处理器映射器和处理器适配器将自动配置
3、配置视图解释器,在ModelAndView设置对应的jsp路径时可以省略前缀和后缀
	<!-- 处理器映射器 
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
	  处理器适配器 
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>-->
	<!-- 注解驱动 -->
	<mvc:annotation-driven />
	
	<!-- 视图解释器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/jsp/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>
12
 
1
    <!-- 处理器映射器 
2
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
3
      处理器适配器 
4
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>-->
5
    <!-- 注解驱动 -->
6
    <mvc:annotation-driven />
7
    
8
    <!-- 视图解释器 -->
9
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
10
        <property name="prefix" value="/jsp/"></property>
11
        <property name="suffix" value=".jsp"></property>
12
    </bean>

SpringMVC整合mybatis

步骤简述:
1、导入springmvc、mybatis、spring-mybatis整合包以及其他所需要的包
2、书写配置文件
3、编写dao层,service层以及controller层的代码
4、测试

整合思路:

Dao层:

1、SqlMapConfig.xml,空文件即可,但是需要文件头

2、applicationContext-dao.xml

a)数据库连接池

b)SqlSessionFactory对象,需要springmybatis整合包下的

c)配置mapper文件扫描器

Service层:

1、applicationContext-service.xml包扫描器,扫描@service注解的类

2、applicationContext-trans.xml配置事务

Controller层:

1、Springmvc.xml

a)包扫描器,扫描@Controller注解的类

b)配置注解驱动

c)配置视图解析器

Web.xml文件:

1、配置spring

2、配置前端控制器



SpringMVC参数绑定

1、在SpringMVC中,提交请求的数据是通过方法形参来接收的,从客户端请求的 key/value 数据,经过参数绑定,将 key/value 数据绑定到 Controller 的形参上,然后在 Controller 就可以直接使用该形参


2、默认支持的类型
SpringMVC 有支持的默认参数类型,我们直接在形参上给出这些默认类型的声明,就能直接使用
①、HttpServletRequest对象:通过request对象获取请求信息
②、HttpServletResponse对象:通过response处理响应信息
③、HttpSession对象:通过session对象得到session中存放的对象
④、Model/ModelMap对象:除了ModelAndView以外,还可以使用Model来向页面传递数据,Model是一个接口,在参数里直接声明model即可
如果使用Model则可以不使用ModelAndView对象,Model对象可以向页面传递数据,View对象则可以使用String返回值替代


3、支持的数据类型
可以在方法的参数列表中定义接收的参数类型:
	@RequestMapping(value="/editItem.action")
	public ModelAndView editItem(Integer id,HttpServletRequest request,HttpServletResponse response,HttpSession session,Model model){}
2
 
1
    @RequestMapping(value="/editItem.action")
2
    public ModelAndView editItem(Integer id,HttpServletRequest request,HttpServletResponse response,HttpSession session,Model model){}
参数类型推荐使用包装数据类型,因为基础数据类型不可以为null
整形:Integer、int
字符串:String
单精度:Float、float
双精度:Double、double
布尔型:Boolean、boolean
说明:对于布尔类型的参数,请求的参数值为true或false。或者1或0
请求url:
http://localhost:8080/xxx.action?id=2&status=false
处理器方法:
public String editItem(Model model,Integer id,Boolean status) 


4、参数绑定——POJO
直接在方法参数列表中传入POJO,POJO中的属性都将传入方法内


5、绑定QueryVo
还可以在方法参数列表中传入具有对应bean类属性的QueryVo对象,此时JSP中对应的name属性需要改为name="${QueryVo.bean类属性名}"

解决post提交乱码的方法是在web.xml文件里配置对应的解决乱码过滤器,实现代码如下:
  <filter>
  	<filter-name>encoding</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>encoding</filter-name>
  	<url-pattern>*.action</url-pattern>
  </filter-mapping>
12
 
1
  <filter>
2
    <filter-name>encoding</filter-name>
3
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
4
    <init-param>
5
        <param-name>encoding</param-name>
6
        <param-value>UTF-8</param-value>
7
    </init-param>
8
  </filter>
9
  <filter-mapping>
10
    <filter-name>encoding</filter-name>
11
    <url-pattern>*.action</url-pattern>
12
  </filter-mapping>
而解决get提交乱码则可以使用将从页面传递过来的参数进行解码再编码的方法,实现代码如下:
String s = new String(request.getParameter("XX").getBytes("ISO-8859-1","UTF-8"));
1
 
1
String s = new String(request.getParameter("XX").getBytes("ISO-8859-1","UTF-8"));



6、自定义参数绑定
由于日期数据有很多种格式,springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。
前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适配,并对方法中的形参进行参数绑定。可以在springmvc处理器适配器上自定义转换器Converter进行参数绑定。

1、一般使用<mvc:annotation-driven/>注解驱动加载处理器适配器,可以在此标签上进行配置。
	<!-- 注解驱动 -->
	<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>
	
	<!-- 配置Converter转换器 转换工厂 (日期、去掉前后空格等) -->
	<bean name="conversionServiceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
		<property name="converters">
			<list>
				<bean class="com.zzh.converter.DateConverter"></bean>
			</list>
		</property>
	</bean>
11
 
1
    <!-- 注解驱动 -->
2
    <mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>
3
    
4
    <!-- 配置Converter转换器 转换工厂 (日期、去掉前后空格等) -->
5
    <bean name="conversionServiceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
6
        <property name="converters">
7
            <list>
8
                <bean class="com.zzh.converter.DateConverter"></bean>
9
            </list>
10
        </property>
11
    </bean>
2、自定义converter转换器,实现Converter<S,T>接口,S是页面传递过来的参数类型,T是参数经转换之后的类型
package com.zzh.converter;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.core.convert.converter.Converter;

//第一个参数S:页面传递过来的类型,第二个参数T转换后的类型
public class DateConverter implements Converter<String, Date>{
	@Override
	public Date convert(String source) {
		try {
			if(null != source) {
				DateFormat df = new SimpleDateFormat("yyyy:MM-dd HH_mm-ss");
				Date date = df.parse(source);
				System.out.println(date);
				return date;
			}
		}catch (Exception e) {
			// TODO: handle exception
		}
		return null;
	}
}
26
 
1
package com.zzh.converter;
2
3
import java.text.DateFormat;
4
import java.text.SimpleDateFormat;
5
import java.util.Date;
6
7
import org.springframework.core.convert.converter.Converter;
8
9
//第一个参数S:页面传递过来的类型,第二个参数T转换后的类型
10
public class DateConverter implements Converter<String, Date>{
11
    @Override
12
    public Date convert(String source) {
13
        try {
14
            if(null != source) {
15
                DateFormat df = new SimpleDateFormat("yyyy:MM-dd HH_mm-ss");
16
                Date date = df.parse(source);
17
                System.out.println(date);
18
                return date;
19
            }
20
        }catch (Exception e) {
21
            // TODO: handle exception
22
        }
23
        return null;
24
    }
25
}
26


7、绑定数组
Controller方法中可以用页面数据类型所对应的数组接收,或者在POJO类中定义相应数据类型的数组作为属性接收
@RequestMapping("queryId.action")
public String queryId(Integer[] ids) {
    for(Integer id :ids){
       System.out.println(id); 
    }
	return "success";
}
8
 
1
@RequestMapping("queryId.action")
2
public String queryId(Integer[] ids) {
3
    for(Integer id :ids){
4
       System.out.println(id); 
5
    }
6
    return "success";
7
}
8

8、绑定集合List
①、List中存放对象,将定义的List放在包装类QueryVo中,使用包装类接收,如下:
技术分享图片

②、在JSP中需要通过遍历把对应的数据封装到itemList集合中,因此实际页面的代码应该如下:
技术分享图片

此时需要在<c:forEach>标签中定义一个索引varStatus,这个索引会随着数据的遍历自增
<c:forEach items="${itemList }" var="item" varStatus="s">
<tr>
	<td><input type="checkbox" name="ids" value="${item.id}"/></td>
	<td>
		<input type="hidden" name="itemList[${s.index}].id" value="${item.id }"/>
		<input type="text" name="itemList[${s.index}].name" value="${item.name }"/>
	</td>
	<td><input type="text" name="itemList[${s.index}].price" value="${item.price }"/></td>
	<td><input type="text" name="itemList[${s.index}].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
	<td><input type="text" name="itemList[${s.index}].detail" value="${item.detail }"/></td>
	
	<td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>

</tr>
</c:forEach>
16
 
1
<c:forEach items="${itemList }" var="item" varStatus="s">
2
<tr>
3
    <td><input type="checkbox" name="ids" value="${item.id}"/></td>
4
    <td>
5
        <input type="hidden" name="itemList[${s.index}].id" value="${item.id }"/>
6
        <input type="text" name="itemList[${s.index}].name" value="${item.name }"/>
7
    </td>
8
    <td><input type="text" name="itemList[${s.index}].price" value="${item.price }"/></td>
9
    <td><input type="text" name="itemList[${s.index}].createtime" value="<fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>
10
    <td><input type="text" name="itemList[${s.index}].detail" value="${item.detail }"/></td>
11
    
12
    <td><a href="${pageContext.request.contextPath }/itemEdit.action?id=${item.id}">修改</a></td>
13
14
</tr>
15
</c:forEach>
16
注意:接收List类型的数据必须是pojo的属性,如果方法的形参为ArrayList类型无法正确接收到数据。


@RequestMapping注解

1、通过@RequestMapping注解可以定义不同的处理器映射规则
①、URL路径映射
@RequestMapping(value="item")或@RequestMapping("/item"),value的值是数组,可以将多个url映射到同一个方法
/**
 * 查询商品列表
 * @return
 */
@RequestMapping(value = { "itemList", "itemListAll" })
public ModelAndView queryItemList() {
	// 查询商品数据
	List<Item> list = this.itemService.queryItemList();

	// 创建ModelAndView,设置逻辑视图名
	ModelAndView mv = new ModelAndView("itemList");

	// 把商品数据放到模型中
	mv.addObject("itemList", list);
	return mv;
}
17
 
1
/**
2
 * 查询商品列表
3
 * @return
4
 */
5
@RequestMapping(value = { "itemList", "itemListAll" })
6
public ModelAndView queryItemList() {
7
    // 查询商品数据
8
    List<Item> list = this.itemService.queryItemList();
9
10
    // 创建ModelAndView,设置逻辑视图名
11
    ModelAndView mv = new ModelAndView("itemList");
12
13
    // 把商品数据放到模型中
14
    mv.addObject("itemList", list);
15
    return mv;
16
}
17

②、添加在类上面
在class上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求url必须以请求前缀开头,可以使用此方法对url进行分类管理
技术分享图片


③、请求方法限定
除了可以对url进行设置,还可以限定请求进来的方法
? 限定GET方法
@RequestMapping(method = RequestMethod.GET)

如果通过POST访问则报错:
HTTP Status 405 - Request method ‘POST‘ not supported

例如:
@RequestMapping(value = "itemList",method = RequestMethod.POST)

限定POST方法
@RequestMapping(method = RequestMethod.POST)

如果通过GET访问则报错:
HTTP Status 405 - Request method ‘GET‘ not supported

GET和POST都可以
@RequestMapping(method = {RequestMethod.GET,RequestMethod.POST})


Controller方法返回值

1、返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view的页面路径


2、返回void
当无返回值时,需要在方法形参上定义request和response,使用request或response指定响应结果,
可以使用response页面重定向、request转发页面以及通过response指定响应结果:
①、使用request转发页面:
request.getRequestDispatcher("页面路径").forward(request, response);
request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);
2
 
1
request.getRequestDispatcher("页面路径").forward(request, response);
2
request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);
②、使用response页面重定向:
response.sendRedirect("url")
response.sendRedirect("/springmvc-web2/itemEdit.action");
2
 
1
response.sendRedirect("url")
2
response.sendRedirect("/springmvc-web2/itemEdit.action");
③、使用response指定响应结果:
response.getWriter().print("{\"abc\":123}");
1
 
1
response.getWriter().print("{\"abc\":123}");

3、返回字符串
①、逻辑视图名:controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址
//指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/jsp/itemList.jsp
return "/WEB-INF/jsp/itemList.jsp";
3
 
1
//指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/jsp/itemList.jsp
2
return "/WEB-INF/jsp/itemList.jsp";
3

②、Redirect重定向:Contrller方法返回字符串可以重定向到一个url地址
@RequestMapping("updateItem")
public String updateItemById(Item item) {
	// 更新商品
	this.itemService.updateItemById(item);

	// 修改商品成功后,重定向到商品编辑页面
	// 重定向后浏览器地址栏变更为重定向的地址,
	// 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失
	// 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数
	return "redirect:/itemEdit.action?itemId=" + item.getId();
}
11
 
1
@RequestMapping("updateItem")
2
public String updateItemById(Item item) {
3
    // 更新商品
4
    this.itemService.updateItemById(item);
5
6
    // 修改商品成功后,重定向到商品编辑页面
7
    // 重定向后浏览器地址栏变更为重定向的地址,
8
    // 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失
9
    // 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数
10
    return "redirect:/itemEdit.action?itemId=" + item.getId();
11
}

③、forward转发:Controller方法执行后继续执行另一个Controller方法
@RequestMapping("updateItem")
public String updateItemById(Item item) {
	// 修改商品成功后,继续执行另一个方法
	// 使用转发的方式实现。转发后浏览器地址栏还是原来的请求地址,
	// 转发并没有执行新的request和response,所以之前的请求参数都存在
	return "forward:/itemEdit.action";
}
7
 
1
@RequestMapping("updateItem")
2
public String updateItemById(Item item) {
3
    // 修改商品成功后,继续执行另一个方法
4
    // 使用转发的方式实现。转发后浏览器地址栏还是原来的请求地址,
5
    // 转发并没有执行新的request和response,所以之前的请求参数都存在
6
    return "forward:/itemEdit.action";
7
}

异常处理器

系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生
系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器(DispatcherServlet)交由异常处理器(HandlerExceptionResolver)进行异常处理,如下图:
技术分享图片

1、自定义异常处理,需要实现HandlerExceptionResolver接口并实现resolveException方法,参数列表中的Object将以字符串的形式存放发生异常的的地方的包名、类名、方法名(形参)
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

public class ItemExceptionResolver implements HandlerExceptionResolver{

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object obj,
			Exception e) {
		//参数列表中的obj将以字符串的形式存放发生异常的的地方的包名、类名、方法名(形参)
		ModelAndView mav = new ModelAndView();
		mav.addObject("error","未知异常");
		mav.setViewName("error");
		return mav;
	}
}
18
 
1
import javax.servlet.http.HttpServletRequest;
2
import javax.servlet.http.HttpServletResponse;
3
4
import org.springframework.web.servlet.HandlerExceptionResolver;
5
import org.springframework.web.servlet.ModelAndView;
6
7
public class ItemExceptionResolver implements HandlerExceptionResolver{
8
9
    @Override
10
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object obj,
11
            Exception e) {
12
        //参数列表中的obj将以字符串的形式存放发生异常的的地方的包名、类名、方法名(形参)
13
        ModelAndView mav = new ModelAndView();
14
        mav.addObject("error","未知异常");
15
        mav.setViewName("error");
16
        return mav;
17
    }
18
}
接着在springmvc.xml中配置该异常处理器即可
<bean class="com.zzh.exception.ItemExceptionResolver"/>
1
 
1
<bean class="com.zzh.exception.ItemExceptionResolver"/>

自定义异常类

由于在抛出异常信息时不建使用议throw new RuntimeException("异常信息")这种形式,所以往往需要自定义一个异常类来对异常信息进行说明,如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息
public class MyException extends Exception {
	// 异常信息
	private String message;

	public MyException() {
		super();
	}

	public MyException(String message) {
		super();
		this.message = message;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
}
21
 
1
public class MyException extends Exception {
2
    // 异常信息
3
    private String message;
4
5
    public MyException() {
6
        super();
7
    }
8
9
    public MyException(String message) {
10
        super();
11
        this.message = message;
12
    }
13
14
    public String getMessage() {
15
        return message;
16
    }
17
18
    public void setMessage(String message) {
19
        this.message = message;
20
    }
21
}
需要用到该自定义异常类时,只需要在异常处理器中判断异常是否包含自定义异常,true则读取自定义异常信息,false则读取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");
23
 
1
        // 定义异常信息
2
        String msg;
3
4
        // 判断异常类型
5
        if (exception instanceof MyException) {
6
            // 如果是自定义异常,读取异常信息
7
            msg = exception.getMessage();
8
        } else {
9
            // 如果是运行时异常,则取错误堆栈,从堆栈中获取异常信息
10
            Writer out = new StringWriter();
11
            PrintWriter s = new PrintWriter(out);
12
            exception.printStackTrace(s);
13
            msg = out.toString();
14
15
        }
16
17
        // 把错误信息发给相关人员,邮件,短信等方式
18
        // TODO
19
20
        // 返回错误页面,给用户友好页面显示错误信息
21
        ModelAndView modelAndView = new ModelAndView();
22
        modelAndView.addObject("msg", msg);
23
        modelAndView.setViewName("error");


上传图片

1、配置虚拟目录,有两种方法,分别是:
①、在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:
<Context docBase="G:\upload\" path="/pic" reloadable="false"/>

②、通过eclipse配置:
技术分享图片

技术分享图片

2、上传图片
①、导入jar包依赖
commons-fileupload-1.2.2.jar
commons-io-2.4.jar
②、JSP页面图片上传代码,设置表单可以进行文件上传
	       <!-- 表单设置为可以进行文件上传
               enctype="multipart/form-data"
           ->

            <tr>
				<td>商品图片</td>
				<td>
					<c:if test="${item.pic !=null}">
						<img src="/pic/${item.pic}" width=100 height=100/>
						<br/>
					</c:if>
					<input type="file"  name="pictureFile"/> 
				</td>
			</tr>
14
 
1
           <!-- 表单设置为可以进行文件上传
2
               enctype="multipart/form-data"
3
           ->
4
5
            <tr>
6
                <td>商品图片</td>
7
                <td>
8
                    <c:if test="${item.pic !=null}">
9
                        <img src="/pic/${item.pic}" width=100 height=100/>
10
                        <br/>
11
                    </c:if>
12
                    <input type="file"  name="pictureFile"/> 
13
                </td>
14
            </tr>
③、配置文件上传解析器
	<!-- 文件上传,id必须设置为multipartResolver -->
	<bean id="multipartResolver"
		class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 设置文件上传大小 -->
		<property name="maxUploadSize" value="5000000" />
	</bean>
6
 
1
    <!-- 文件上传,id必须设置为multipartResolver -->
2
    <bean id="multipartResolver"
3
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
4
        <!-- 设置文件上传大小 -->
5
        <property name="maxUploadSize" value="5000000" />
6
    </bean>

Json数据交互

首先需要加入json的处理jar包使spirngMVC支持json
技术分享图片


@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容(json数据)转换为java对象并绑定到Controller方法的参数上

传统的请求参数:itemEdit.action?id=1&name=zhangsan&age=12
现在的请求参数:使用POST请求,在请求体里面加入json数据
技术分享图片

@ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

配置json转换器:如果不使用注解驱动<mvc:annotation-driven />,就需要给处理器适配器配置json转换器,参考之前学习的自定义参数绑定。
在springmvc.xml配置文件中,给处理器适配器加入json转换器:
<!--处理器适配器 -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<property name="messageConverters">
		<list>
		<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
		</list>
		</property>
	</bean>
8
 
1
<!--处理器适配器 -->
2
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
3
        <property name="messageConverters">
4
        <list>
5
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
6
        </list>
7
        </property>
8
    </bean>

RESTful支持

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。分别对应 添加、 删除、修改、查询。
传统方式操作资源
http://127.0.0.1/item/queryItem.action?id=1     查询,GET
http://127.0.0.1/item/saveItem.action      新增,POST
http://127.0.0.1/item/updateItem.action      更新,POST
http://127.0.0.1/item/deleteItem.action?id=1     删除,GET或POST

使用RESTful操作资源
http://127.0.0.1/item/1      查询,GET
http://127.0.0.1/item       新增,POST
http://127.0.0.1/item      更新,PUT
http://127.0.0.1/item/1      删除,DELETE


使用RESTful风格开发的接口,根据id查询商品
/**
 * 使用RESTful风格开发接口,实现根据id查询商品
 * 
 * @param id
 * @return
 *使用注解@RequestMapping("item/{id}")声明请求的url
 *{xxx}叫做占位符,请求的URL可以是“item /1”或“item/2”
 *使用(@PathVariable() Integer id)获取url上的数据 
 */
@RequestMapping("item/{id}")
@ResponseBody
public Item queryItemById(@PathVariable() Integer id) {
 Item item = this.itemService.queryItemById(id);
 return item;
}
x
 
1
/**
2
 * 使用RESTful风格开发接口,实现根据id查询商品
3
 * 
4
 * @param id
5
 * @return
6
 *使用注解@RequestMapping("item/{id}")声明请求的url
7
 *{xxx}叫做占位符,请求的URL可以是“item /1”或“item/2”
8
 *使用(@PathVariable() Integer id)获取url上的数据 
9
 */
10
@RequestMapping("item/{id}")
11
@ResponseBody
12
public Item queryItemById(@PathVariable() Integer id) {
13
 Item item = this.itemService.queryItemById(id);
14
 return item;
15
}
注意:
1、如果@RequestMapping中表示为"item/{id}",id和形参名称一致,@PathVariable不用指定名称。如果不一致,例如"item/{ItemId}"则需要指定名称@PathVariable("itemId")
2、@PathVariable是获取url上数据的。@RequestParam获取请求参数的(包括post表单提交)
3、如果加上@ResponseBody注解,就不会走视图解析器,不会返回页面,目前返回的json数据。如果不加,就走视图解析器,返回页面

拦截器

Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理

1、自定义拦截器,实现HandlerInterceptor
public class MyInterceptor implements HandlerInterceptor{
	/**
	 * 	 Controller执行前调用此方法
	 * 	  返回true表示继续执行,返回false中止执行
	 *   这里可以加入登录校验、权限拦截等
	 */
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		
		return false;
	}
	
	
	/**
	 * controller执行后但未返回视图前调用此方法 
	 * 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
	 */
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
	}
	
	
	/**
	 * controller执行后且视图返回后调用此方法
	 * 可得到执行controller时的异常信息
	 * 可记录操作日志
	 */
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
	}
}
1
33
 
1
public class MyInterceptor implements HandlerInterceptor{
2
    /**
3
     *   Controller执行前调用此方法
4
     *    返回true表示继续执行,返回false中止执行
5
     *   这里可以加入登录校验、权限拦截等
6
     */
7
    @Override
8
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
9
        
10
        return false;
11
    }
12
    
13
    
14
    /**
15
     * controller执行后但未返回视图前调用此方法 
16
     * 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示
17
     */
18
    @Override
19
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
20
            throws Exception {
21
    }
22
    
23
    
24
    /**
25
     * controller执行后且视图返回后调用此方法
26
     * 可得到执行controller时的异常信息
27
     * 可记录操作日志
28
     */
29
    @Override
30
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
31
            throws Exception {
32
    }
33
}

2、拦截器配置
	<!-- springmvc的拦截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<!-- 自定义拦截类
				path="/**"表示拦截所有
			 -->
			<mvc:mapping path="/**"/>
			<bean class="com.zzh.interceptor.MyInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>
1
10
 
1
    <!-- springmvc的拦截器 -->
2
    <mvc:interceptors>
3
        <mvc:interceptor>
4
            <!-- 自定义拦截类
5
                path="/**"表示拦截所有
6
             -->
7
            <mvc:mapping path="/**"/>
8
            <bean class="com.zzh.interceptor.MyInterceptor"></bean>
9
        </mvc:interceptor>
10
    </mvc:interceptors>

3、拦截器的运行规则
①preHandle按拦截器定义顺序调用
②postHandler按拦截器定义逆序调用
③afterCompletion按拦截器定义逆序调用
④postHandler在拦截器链内所有拦截器返成功调用
⑤afterCompletion只有preHandle返回true才调用




















SpringMVC.zzh

标签:scroll   list()   页面   修改   date()   span   多个   存储   解决乱码   

原文地址:https://www.cnblogs.com/zzh1997/p/9601134.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!