欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring mvc 2

程序员文章站 2022-07-13 14:00:22
...



视图解析器
spring mvc的action返回的是一个逻辑视图名,视图解析器根据逻辑视图名,查找视图解析器,直到一个能处理的视图解析器存在,交给它处理。它会将逻辑视图转换成物理视图。

它支持多个视图解析器同时存在。可以把他们看成是一个链结构。必要时,也可以通过order属性来声明每个解析器的序列。 要记住的是,某个解析器的order越高, 它在解析链中的位置越靠后。

如果返回的逻辑视图名带有redirect:前缀 ,那么这个视图将被认为是重定向
如果返回的逻辑视图名带有forward:前缀,那么这个视图被认为是跳转。

spring提供的视图解析器有
AbstractCachingViewResolAvbesrtract
XmlViewResolver
ResourceBundleViewResolvIemrplementation
UrlBasedViewResolver 这个视图解析器会将视图名解析成URL,并将请求传递给RequestDispatcher来显示视图。类似于java代码中将逻辑视图组合成实际视图,然后调用一次RequestDispatcher来转发。
InternalResourceViewResoClovnevrenient
VelocityViewResolver
FreeMarkerViewResolver
ViewResolver
ContentNegotiatingViewReIsmopllevmeerntation

视图解析链
Spring支持多个视图解析器一起使用。可以把它们当作一个解析链。

必要时,也可以通过order属性来声明每个解析器的序列。 要记住的是,某个解析器的order越高, 它在解析链中的位置越靠后。
下面这个例子展示了一个包含两个解析器的解析链。 一个是InternalResourceViewResolver,这个解析器总是被自动的放到链的末端。 另一个是XmlViewResolver,它支持解析Excel视图(而InternalResourceViewResolver不可以)。
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> 
  <property name="prefix" value="/WEB-INF/jsp/"/> 
  <property name="suffix" value=".jsp"/> 
</bean> 

<bean id="excelViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver"> 
  <property name="order" value="1"/> 
  <property name="location" value="/WEB-INF/views.xml"/> 
</bean> 

views.xml文件内容
<beans> 
  <bean name="report" class="org.springframework.example.ReportExcelView"/> 
</beans> 

spring从第一个解析器开始,如果这个解析器没有找到实际的物理视图,那么这个逻辑视图就被下一个解析器处理。当到达最后一个还没有处理,Spring会抛出一个Exception

redirect:前缀和
forward:前缀
当返回的逻辑视图中包含了其中之一的前缀,会进行处理
redirect:是跳转操作
forward:是转发操作。如
return "forward:/home.html";


使用主题
和localeResolver一样,spring mvc会读取一个叫themeResolver的bean。
<bean id="themeResolver" 
class="org.springframework.web.servlet.theme.SessionThemeResolver" /> 
主题的内容是通过
主题是org.springframework.ui.context.ThemeSource的接口来读取的。WebApplicationContext是它的子类。

但是它本身木有实现这个接口,而是转交给另外的代理来处理。默认是org.springframework.ui.context.support.ResourceBundleThemeSource处理的。
如果要使用自己的实现,必须将这个实现定义为themeSource,WebApplicationContext会自动读取这个bean。

当ResourceBundleThemeSource寻找所需的属性文件时,它默认在配置的属性文件名中没有任何前缀basenamePrefix, 也就是说,它只会在classpath的根部寻找。举例来说,如果一个主题的定义包含在cool.properties这个属性文件中。需要把这个文件放在classpath的根部,比如在/WEB-INF/classes目录下。 同时,ResourceBundleThemeSource 使用标准的Java resource bundle管理机制, 这意味着实现主题的国际化是很容易的。 比如,/WEB-INF/classes/cool_nl.properties这个属性文件中可以指向一个显示荷兰文字的图片。

<!-- 配置主题解析器 --> 
<bean id="themeSource" 
class="org.springframework.ui.context.support.ResourceBundleThemeSource"> 
<property name="basenamePrefix"> 
<value>com.cgodo.daowole.spring.properties.themes.index</value> 
</property> 
</bean> 

springmvc默认的主题解析器是FixedThemeResolver,

在public Theme getTheme(String themeName) {

方法中,这个是查找主题集合的。他会把这个themeName(主题名字,我们不仅是针对国际化做的主题,我们还需要做主题的切换,比如一个叫free的主题,和一个叫sun的主题,我们可以在这两个主题之间互相切换,来完成像微薄那样的主题切换了,加上国际化功能,我们就可以让同一个主题,拥有多个的语言支持) 和我们设置的basenamePrefix,也就是com.cgodo.daowole.spring.properties.themes.index

拼装为

basenamePrefix + themeName

这个就是最后的resource base name。
themeName是外部传入的。
而外部对这个themeName的处理方式是themeResolver.resolveThemeName获取的。
里面的实现只是
return getDefaultThemeName(); 
public String getDefaultThemeName() { 
return this.defaultThemeName; 
} 


defaultThemeName是AbstractThemeResolver的属性

public final static String ORIGINAL_DEFAULT_THEME_NAME = "theme";

private String defaultThemeName = ORIGINAL_DEFAULT_THEME_NAME;

可以看到默认值是"theme"。因此可以知道,我们在不修改注解的默认配置下,主题文件的属性文件应该是
com.cgodo.daowole.spring.properties.themes包下面,zh_CN的国际locale,主题则是的indextheme_zh_CN.properties

另外
如果cooltheme.properties这个属性文件放置在了/WEB-INF/classes/com/aa/bb/cc目录下, 那么这个baseName的值应该为com.aa.bb.cc.cool。 更好的方式是文件名刚好是theme
这样我们配置basename前缀就可以写为com.aa.bb.cc.就行了。

主题解析器
FixedThemeResolver 选用一个固定的主题,这个主题由“defaultThemeName”属性决定。
SessionThemeResolver 主题保存在用户的HTTP session。在每个session中,这个主题只需要被设置一次,但是每个新session的主题都要重新设置。
CookieThemeResolver 用户所选择的主题以cookie的形式存在客户端的机器上面。

Spring 也支持一个叫ThemeChangeInterceptor 的请求拦截器。它可以根据请求中包含的参数来动态地改变主题。

当然我们还可以实现自己的主题解析器,来从用户表中读取一个主题的名字。


spring文件上传

spring支持web的文件上传,是由MultipartResolver实现的。这是个可插拔的解析器。定义在定义在org.springframework.web.multipart包。spring mvc提供了一个支持Commons FileUpload上传的实现。和COS FileUpload实现的类。

当DispatcherServlet检测到请求是属于multi-part的,那么它会查找定义在context中的解析器,并激活它。解析器将HttpServletRequest放入一个MultipartHttpServletRequest。MultipartHttpServletRequest可以获得对Multipart请求的信息。


<!-- 配置文件上传 --> 
<bean id="multipartResolver" 
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
<!-- 最大的文件20MB --> 
<property name="maxUploadSize" value="20971520" /> 
<!-- 
内存缓冲区,假设一个访问者的网速是64KB/S,实际速度可能只能发挥到10KB/S 
--> 
<property name="maxInMemorySize" value="10240" /> 
</bean> 

@RequestMapping("/fileupload") 
public String fileupload() { 
//这里由于使用freemarker,因此需要使用这个action来返回ftl。 
return "common/fileupload"; 
} 

@RequestMapping("/dofileupload") 
public String dofileupload(String name, @RequestParam MultipartFile file) throws IOException { 
InputStream in = file.getInputStream(); 
byte[] files = file.getBytes(); 
return "common/fileupload"; 
} 

注意在dofileupload方法的@RequestParam注解是必须的。否则会报错。 RequestParam 的配置参照spring mvc的资料


HandlerExceptionResolver异常解析器

有点类似于web.xml的error
扩展HandlerExceptionResolver,它只有一个方法
ModelAndView resolveException( 
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex); 

SimpleMappingExceptionResolver
这个异常解析器根据异常类名或者状态,来返回视图名。
exceptionMappings和
statusCodes

默认使用的是
DefaultHandlerExceptionResolver
异常处理器
他根据抛出的异常,来返回对应的状态码
Exception HTTP Status Code
ConversionNotSupportedException 500 (Internal Server Error)
HttpMediaTypeNotAcceptableException 406 (Not Acceptable)
HttpMediaTypeNotSupportedException 415 (Unsupported Media Type)
HttpMessageNotReadableException 400 (Bad Request)
HttpMessageNotWritableException 500 (Internal Server Error)
HttpRequestMethodNotSupportedExcepti4o0n5 (Method Not Allowed)
MissingServletRequestParameterExcept4i0o0n(Bad Request)
NoSuchRequestHandlingMethodException404 (Not Found)
TypeMismatchException 400 (Bad Request)


@ExceptionHandler
在controller中使用这个注释,来完成异常处理的功能
@Controller 
public class SimpleController { 
@ExceptionHandler(IOException.class) 
public String handleIOException(IOException ex, HttpServletRequest request) { 
return ClassUtils.getShortName(ex.getClass()); 
} 
} 

注解的value可以定义成一个数组,来支持多种异常
@ExceptionHandler(value = { Exception.class, IOException.class }) 
public String handleException(Exception ex, HttpServletRequest request) { 
return ClassUtils.getShortName(ex.getClass()); 
} 


Model ModelMap ModelAndView
都提供一个方法addObject
根据你传入的object类型生成对应的model的key,并将key对应的value设置为这个object
普通bean 将首字符小写后就是key
HasmMap hashMap

数组 首字母小写,加上List,如User数组是 userList
List类型 首字母小写,加上List,如List<User>是 userList
Set类型 首字母小写,加上List,如HashSet<User>是 userList
如果集合(包括数组)是空的(size=0),那么不会添加到model中
传入的对象是不允许为null的。



配置
mvc:annotation-driven
这个标签会注册一个
DefaultAnnotationHandlerMapping bean
和一个AnnotationMethodHandlerAdapter bean在spring上下文中。这是使用@Controller注解所必须的。这两个bean默认启动了以下配置

1.启动Type ConversionService,当数据需要写入javabean中,找到PropertyEditors 来编辑数据
2.支持@NumberFormat 注解
3.支持@DateTimeFormat注解
4.支持@Valid注解
5.如果在classpath有JAXB的架包,那么可以支持XML的读写
6.上下文中有Jackson的架包,那么就能支持json读写


mvc:interceptors
这个标签是用来注册拦截器的。当开启了mvc:annotation-driven配置,应该使用这个标签来注册拦截器

mvc:view-controller
使用的是SimpleControllerHandlerAdapter处理器。它的处理方法就是

@Override 
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) 
throws Exception { 
return new ModelAndView(getViewName()); 
} 


直接返回一个视图名

<mvc:view-controller path="/" view-name="application/index.json" /> 



如上,表示访问
http://127.0.0.1:81/daowole/会被直接返回一个叫application/index.json的逻辑视图名。

另外要说明的是http://127.0.0.1:81/daowole方法的时候,apache会使用302,重定向到
http://127.0.0.1:81/daowole/。

还有这个标签的优先级别低于@RequestMapping。


@RequestMapping(value = { "/"})
public String home(
这里写了RequestMapping为/,

<mvc:view-controller path="/" view-name="application/index.json" />


这个时候这里的配置就无效了。

mvc:resources
可以使用路径模式,来完成静态资源的读取。
mapping支持ant风格的方式

<mvc:resources mapping="/static/**/*" location="/static/" />
 

mapping表示请求的路径,location表示请求路径将被映射到的路径。location可以自定多个路径,使用逗号分隔。

它同时支持最后修改时间来决定是否返回304

设置资源的缓存时间
<mvc:resources mapping="/static/**/*" location="/static/" 
cache-period="31556926" /> 

从classpath中的一个jar文件中的/META-INF/public-web-resources/目录加载资源
<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/public-web-resources/"/> 

资源mapping可以从属性文件加载
/WEB-INF/spring/application.properties文件
application.version=1.0.0

<util:properties id="applicationProps" location="/WEB-INF/spring/application.properties"/>

加载资源文件

<mvc:resources mapping="/resources-#{applicationProps['application.version']}/**" location="/public-resources/"/> 


#{applicationProps['application.version']}这部分将从资源文件中读取。

mvc:default-servlet-handler
在请求静态资源的时候,会使用web上下文提供的处理器处理,(如apache有一个自己的js处理器)。

相关标签: Spring UI MVC