SpringMVC学习笔记之三

1.SpringMVC返回JSON

请求页面代码如下:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript" scr="scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
	$(function(){
			$("testJson").click(function(){
				var url=this.href;
				var args={};
				$.post(url,args,function(data){
					for(var i=0;i<data.length;i++){
							var id=data[i].id;
							var lastName=data[i].lastName;
							alert(id+":"+lastName);
						}
					});
					return false;
				});
		});
</script>
</head>
<body>
	<a href="emps">List All Employees</a>
	<a href="testJson" id="testJson">Test Json</a>
</body>
</html>

对应的java处理方法:

@ResponseBody
@RequestMapping("/testJson")
public Collection<Employee> testJson() {
	return employeeDao.getAll();
}

导入jar包
在这里插入图片描述
使用原理
HttpMessageConverter<T>是Spring3.0新添加的一个接口,负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息
HttpMessageConverter<T>接口定义的方法:
BooleancanRead(Class<?>clazz,MediaTypemediaType):指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为clazz类型的对象,同时指定支持MIME类型(text/html,applaiction/json等)
BooleancanWrite(Class<?>clazz,MediaTypemediaType):指定转换器是否可将clazz类型的对象写到响应流中,响应流支持的媒体类型在MediaType中定义。
LIst<MediaType>getSupportMediaTypes():该转换器支持的媒体类型。
T read(Class<? extends T>clazz,HttpInputMessageinputMessage):将请求信息流转换为T类型的对象。
void write(Tt,MediaTypecontnetType,HttpOutputMessgaeoutputMessage):将T类型的对象写到响应流中,同时指定相应的媒体类型为contentType。
在这里插入图片描述

public interface HttpInputMessage extends HttpMessage {
	InputStream getBody() throws IOException;
}
public interface HttpOutputMessage extends HttpMessage {
	OutputStream getBody() throws IOException;
}

类对应的实现类
在这里插入图片描述
SpringMVC中默认的实现类有哪些:
在这里插入图片描述
Spring提供了两种途径:
–使用@RequestBody/ @ResponseBody对处理方法进行标注
–使用HttpEntity<T> /ResponseEntity<T>作为处理方法的入参或返回值
当控制器处理方法使用到@RequestBody/@ResponseBodyHttpEntity<T>/ResponseEntity<T>时, Spring首先根据请求头或响应头的Accept属性选择匹配的HttpMessageConverter,进而根据参数类型或泛型类型的过滤得到匹配的HttpMessageConverter,若找不到可用的HttpMessageConverter将报错
@RequestBody@ResponseBody不需要成对出现
测试样例,页面代码如下:

<form action="testHttpMessageConverter" method="POST" enctype="multipart/form-data">
	File:<input type="file" name="file">
	Desc:<input type="text" name="desc">
	<input type="submit" value="sumbit">
</form>

过滤代码如下:

@ResponseBody
@RequestMapping("/testHttpMessageConverter")
public String testHttpMessageConverter(@RequestBody String body) {
	System.out.println(body);
	return "helloworld!"+new Date();
}

在这里插入图片描述
测试代码2:
页面jsp代码如下:

<a href="testResponseEntity">Test ResponseEntity</a>

过滤代码如下:

@RequestMapping("/testResponseEntity")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException{
	byte[] body=null;
	ServletContext servletContext=session.getServletContext();
	InputStream in=servletContext.getResourceAsStream("/files/abc.txt");
	body=new byte[in.available()];
	in.read(body);
	HttpHeaders headers = new HttpHeaders();
	headers.add("Content-Disposition","attachment;filename=abc.txt");
	HttpStatus statusCode=HttpStatus.OK;
	ResponseEntity<byte[]> resopnse=new ResponseEntity<byte[]>(body,headers,statusCode);
	return resopnse;
}
2.国际化

关于国际化:
1.在页面上能能够根据浏览器语言设置的情况对文本(不是内容),时间,数值进行本地化处理
2.可以在bean中获取国际化资源文件Locale对应的信息
3.可以通过超链接切换Locale,而不再依赖于浏览器的语言设置情况
解决:
1.使用JSTL的fmt标签
配置spring配置文件

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
	<property name="basename" value="i18n"></property>
</bean>
<mvc:view-controller path="/i18n" view-name="i18n"/>
<mvc:view-controller path="/i18n2" view-name="i18n2"/>

配置国际化资源文件:
在这里插入图片描述
jsp页面配置

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<fmt:message key="i18n.user"></fmt:message>
	<br>
	<a href="i18n2">I18n2 PAGE</a>
</body>
</html>

2.在bean中注入ResourceBundleMessageSource的示例,使用其对应的getMessage方法即可
springmvc配置文件信息如下:

<?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:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>	
	<context:component-scan base-package="com.atguigu.springmvc"></context:component-scan>
	<mvc:default-servlet-handler/>
	<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
		<!-- 配置 ConversionService -->
	<bean id="conversionService"
		class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
		<property name="converters">
			<set>
				<ref bean="employeeConverter"/>
			</set>
		</property>	
	</bean>
	<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
		<property name="basename" value="i18n"></property>
	</bean>
	<!-- 
	<mvc:view-controller path="/i18n" view-name="i18n"/>
	 -->
	<mvc:view-controller path="/i18n2" view-name="i18n2"/>
</beans>

配置拦截方法

@Autowired
private ResourceBundleMessageSource messageSource;
@RequestMapping("/i18n")
public String testI18n(Locale locale) {
	String val =messageSource.getMessage("i18n.user", null,locale);
	System.out.println(val);
	return "i18n";
}

3.配置LocalResolver和LocaleChangeInterceptor
运行原理:
在这里插入图片描述
•AcceptHeaderLocaleResolver:根据HTTP请求头的Accept-Language参数确定本地化类型,如果没有显式定义本地化解析器,SpringMVC使用该解析器。
•CookieLocaleResolver:根据指定的Cookie值确定本地化类型
•SessionLocaleResolver:根据Session中特定的属性确定本地化类型
•LocaleChangeInterceptor:从请求参数中获取本次请求对应的本地化类型。
springmvc配置文件信息如下:

<bean id="localeResolver" 
	class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
</bean>
<mvc:interceptors>
	<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>

jsp页面配置

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<fmt:message key="i18n.user"></fmt:message>
	<br>
	<a href="i18n2">I18n2 PAGE</a>
	<br>
	<a href="i18n?locale=zh_CH">中文</a>
	<br>
	<a href="i18n?locale=en_US">英文</a>
</body>
</html>
3.文件上传

Spring MVC为文件上传提供了直接的支持,这种支持是通过即插即用的MultipartResolver实现的。Spring用Jakarta CommonsFileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResovler
Spring MVC上下文中默认没有装配MultipartResovler,因此默认情况下不能处理文件的上传工作,如果想使用Spring的文件上传功能,需现在上下文中配置MultipartResolver
开发步骤
1.导入jar包
在这里插入图片描述
在这里插入图片描述
2.配置spring文件

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="defaultEncoding" value="UTF-8"></property>
	<property name="maxUploadSize" value="1024000"></property>
</bean>

3.编写目标方法

@RequestMapping("/testFileUpload")
public String testFileUpload(@RequestParam("desc")String desc,
		@RequestParam("file") MultipartFile file) throws IOException {
	System.out.println("desc:"+desc);
	System.out.println("OriginalFilename:"+file.getOriginalFilename());
	System.out.println("InputStream:"+file.getInputStream());
	String path="E:/"+new Date().getTime()+file.getOriginalFilename();
	File newFile=new File(path);
	file.transferTo(newFile);	
	return "success";
}

4.编写jsp页面:

<form action="testConversionServiceConverer" method="POST">
	Employee:<input type="text" name="employee">
	<input type="submit" value="Submit">
</form>

文件上传的三种方式

4.自定义拦截器

自定义的拦截器必须实现HandlerInterceptor接口
–preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求request进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false。可以做权限设置,或者日志和事务
–postHandle():这个方法在业务处理器处理完请求后,渲染视图之前调用。可以对请求域中的属性和视图进行修改。
–afterCompletion():这个方法在DispatcherServlet完全处理完请求后被调用(渲染视图之后),可以在该方法中进行一些资源清理的操作。
1.自定义拦截器类

public class FirstInterceptor implements HandlerInterceptor{
	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("[FirstInterceptor] afterCompletion");
	}
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("[FirstInterceptor] postHandle");
	}
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("[FirstInterceptor] preHandle");
		return true;
	}
}

2.springMVC中配置拦截器

<mvc:interceptors>
		<bean class="com.atguigu.springmvc.crud.interceptors.FirstInterceptor"></bean>
		<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
	</mvc:interceptors>

3.运行结果如下:

[FirstInterceptor] preHandle
list
[FirstInterceptor] postHandle
[FirstInterceptor] afterCompletion

preHandle:该方法在目标方法之前被调用
若返回为true,则继续调用后续的拦截器和目标方法
若返回为false,则不会再调用后续的拦截器和目标方法
执行顺序如下图所示:
在这里插入图片描述
指定拦截器springmvc配置

<mvc:interceptors>
	<bean class="com.atguigu.springmvc.crud.interceptors.FirstInterceptor"></bean>
	<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
	<!--配置拦截器(不)作用的路径  -->
	<mvc:interceptor>
		<mvc:mapping path="/emps"/>
		<!-- <mvc:exclude-mapping path=""/> -->
		<bean class="com.atguigu.springmvc.crud.interceptors.SecondInterceptor"></bean>
	</mvc:interceptor>
</mvc:interceptors>

运行结果如下:

[FirstInterceptor] preHandle
[SecondInterceptor] preHandle
list
[SecondInterceptor] postHandle
[FirstInterceptor] postHandle
[SecondInterceptor] afterCompletion
[FirstInterceptor] afterCompletion

拦截器调用顺序
在这里插入图片描述

5.异常处理

Spring MVC通过HandlerExceptionResolver处理程序的异常,包括Handler映射、数据绑定以及目标方法执行时发生的异常。
SpringMVC提供的HandlerExceptionResolver的实现类
在这里插入图片描述
DispatcherServlet默认装配的HandlerExceptionResolver:
–没有使用mvc:annotation-driven/配置:
在这里插入图片描述
–使用了mvc:annotation-driven/配置:
在这里插入图片描述
主要处理Handler中用@ExceptionHandler注解定义的方法。
实例配置过程:
测试handler代码:

@RequestMapping("/testExceptionHandlerExceptionResolver")
	public String testExceptionHandlerExceptionResolver(@RequestParam("i") int i) {
		System.out.println("result:"+(10/i));
		return "success";
	}

异常处理方法:

@ExceptionHandler(ArithmeticException.class)
public String handleArithmeticException(Exception ex){
	System.out.println("出异常了"+ex);
	return "error";
}

配置页面可获取异常:

@ExceptionHandler(ArithmeticException.class)
public ModelAndView handleArithmeticException(Exception ex){
	System.out.println("出异常了"+ex);
	ModelAndView mv=new ModelAndView("error");
	mv.addObject("exception",ex);
	return mv;
}

jsp页面获取信息如下:

${exception }

1.在@ExceptionHandler方法的入参中可以加入Exception类型的参数,该参数即对应发生的异常对象
2.在@ExceptionHandler方法的入参中不能传入Map,若希望把异常信息传到页面上,需要使用ModelAndView最为返回值
执行方法2:
自定义处理类来进行异常处理

@ControllerAdvice
public class ExceptionHandlerTest {
	@ExceptionHandler(ArithmeticException.class)
	public ModelAndView handleArithmeticException(Exception ex){
		System.out.println("---出异常了"+ex);
		ModelAndView mv=new ModelAndView("error");
		mv.addObject("exception",ex);
		return mv;
	}
}

@ControllerAdvice如果在当前Handler中找不到@ExceptionHandler方法类处理当前方法出现的异常,则将去@ControllerAdvice标记的类中查找@Exception标记的方法来处理异常。
自定义异常类,进行异常处理

@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="用户名和密码不匹配!")
public class UserNameNotMatchPasswordException extends RuntimeException{
	private static final long serialVersionUID = 1L;
}

定义请求处理方法

@RequestMapping("/testResponseStatusExceptionResolver")
public String testResponseStatusExceptionResolver(@RequestParam("i") int i) {
	if(i==13) {
		throw new UserNameNotMatchPasswordException();
	}
	System.out.println("testResponseStatusExceptionResolver....");
	return "success";
}

运行结果如下:
在这里插入图片描述
使用异常方法

@ResponseStatus(reason="测试",value=HttpStatus.NOT_FOUND)
@RequestMapping("/testResponseStatusExceptionResolver")
public String testResponseStatusExceptionResolver(@RequestParam("i") int i) {
	if(i==13) {
		throw new UserNameNotMatchPasswordException();
	}
	System.out.println("testResponseStatusExceptionResolver....");
	return "success";
}

测试结果如下:
在这里插入图片描述
DefaultHandlerExceptionResolver
对一些特殊的异常进行处理,比
如NoSuchRequestHandlingMethodException、HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException等。
jsp配置如下:

<a href="testDefaultHandlerExceptionResolver">Test DefaultHandlerExceptionResolver</a>

拦截代码如下:

@RequestMapping(value="/testDefaultHandlerExceptionResolver",method=RequestMethod.POST)
public String testDefaultHandlerExceptionResolver() {
	System.out.println("testDefaultHandlerExceptionResolver");
	return "success";
}

SimpleMappingExceptionResolver
如果希望对所有异常进行统一处理,可以使用SimpleMappingExceptionResolver,它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常
jsp代码如下:

<a href="testSimpleMappingExceptionResolver?i=2">Test SimpleMappingExceptionResolver</a>
springMVC配置信息如下:
	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="exceptionAttribute" value="ex"></property>
		<property name="exceptionMappings">
			<props>
				<prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
			</props>
		</property>
	</bean>
6.Spring整合SpringMVC

1.需要进行Spring整合SpringMVC吗?
1)需要:通常情况下,类似于数据源、事务、整合其他框架都是放在Spring的配置文件中(而不是放在SpringMVC的配置文件中),实际上放入Spring配置文件对应的IOC容器中的还有Service和Dao.
2)不需要,都放在SpringMVC的配置文件,也可以分成多个Spring的配置文件,然后使用import节点导入其他的配置文件
问题:若Spring的IOC容器和SpringMVC的IOC容器扫描的包有重合的部分,就会导致bean被创建2次。
使用exclude-filter和include-filter子节点来规定只能扫描的注解
1.使Spring的IOC容器扫描的包和SpringMVC的IOC扫描的包没有重合的部分。
2.还是否需要再加入Spring的IOC容器?
3.是否需要在web.xml文件中配置启动Spring IOC容器的ContextLoaderListener?
配置样例,web.xml中的配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
		xmlns="http://java.sun.com/xml/ns/javaee" 
		xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
		id="WebApp_ID" version="3.0">
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:beans.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<servlet>
		<servlet-name>springDispatcherServlet</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>springDispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<filter>
		<filter-name>HiddenHttpMethodFilter</filter-name>
		<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>HiddenHttpMethodFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

springmvc.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:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>	
	<context:component-scan base-package="com.atguigu.springmvc" use-default-filters="false">
	<context:include-filter type="annotation" 
			expression="org.springframework.stereotype.Controller"/>
		<context:include-filter type="annotation" 
			expression="org.springframework.web.bind.annotation.ControllerAdvice"/> 
	</context:component-scan>
	<mvc:default-servlet-handler/>
	<mvc:annotation-driven></mvc:annotation-driven>
</beans>

beans.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:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>	
	<context:component-scan base-package="com.atguigu.springmvc" use-default-filters="false">
	<context:include-filter type="annotation" 
			expression="org.springframework.stereotype.Controller"/>
		<context:include-filter type="annotation" 
			expression="org.springframework.web.bind.annotation.ControllerAdvice"/> 
	</context:component-scan>
	<mvc:default-servlet-handler/>
	<mvc:annotation-driven></mvc:annotation-driven>
</beans>

SpringMVC的IOC容器中的bean可以用来引用Spring IOC容器中的bean,反之Spring IOC容器中的bean却不能来引用SpringMVC IOC容器中的bean。
多个Spring IOC容器之间可以设置为父子关系,以实现良好的解耦。
Spring MVC WEB层容器可作为“业务层”Spring容器的子容器:即WEB层容器可以引用业务层容器的Bean,而业务层容器却访问不到WEB层容器的Bean。

7.SpringMVC对比Struts2

•①. Spring MVC的入口是Servlet,而Struts2是Filter
•②. Spring MVC会稍微比Struts2快些. Spring MVC是基于方法设计,而Sturts2是基于类,每次发一次请求都会实例一个Action.
•③. Spring MVC使用更加简洁,开发效率Spring MVC确实比struts2高:支持JSR303,处理ajax的请求更方便
•④. Struts2的OGNL表达式使页面的开发效率相比Spring MVC更高些.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值