Spring MVC将控制器中请求处理的逻辑和视图中的渲染实现解耦(所编写的控制器方法没有直接产生浏览器中渲染所需要的HTML,这些方法只是将一些数据填充到模型中,然后将模型传递给用来渲染的视图)
视图解析器 | 描述 |
---|---|
BeanNameViewResolver | 将视图解析为Spring应用上下文的Bean,其中Bean的ID与视图的名字相同 |
ContentNegotiatingViewResolver | 根据客户端需要的内容类型来解析视图,委托给另一个能够产生对应内容类型的视图解析器 |
FreeMarkerViewResolver | 将视图解析为FreeMarker模板 |
InternalResourceViewResolver | 将视图解析为Web应用的内部资源(eg: JSP) |
JasperReportsViewResolver | 将视图解析为JasperReports定义 |
ResourceBundleViewResolver | 将视图解析为资源bundle(一般为属性文件) |
UrlBasedViewResolver | 直接根据视图的名称解析视图,视图的名称会匹配一个物理视图的定义 |
XmlViewResolver | 将视图解析为特定XML文件中的Bean定义,类似于BeanNameViewResolver |
XsltViewResolver | 将视图解析为XSLT转换后的结果 |
InternalResourceViewResolver所采取的的方式是在视图名上添加前缀和后缀,进而确定一个Web应用中视图资源的物理路径。
例如:
视图名:home
通用实践将JSP文件放入Web应用的WEB-INF目录以防止对其直接访问。
@Bean
public ViewResolver viewResovler(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp"/>
通过配置将逻辑视图名解析为JSP文件物理地址
例如:
* home
解析为/WEB-INF/views/home.jsp
* productList
解析为/WEB-INF/views/productList.jsp
* books/detail
解析为/WEB-INF/views/books/detail.jsp
当处理请求的时候,抛出异常该如何处理?如果发生了这样情况该如何给出客户端响应?
无论是否异常,Servlet请求的输出都是一个Servlet响应,如果在请求处理的时候出现异常,输出依然会是Servlet响应。异常必须以某种方式转换为响应
@ResponseStatus
,将其映射为某一个HTTP状态码;@ExceptionHandler
注解,使其用来处理异常;默认情况下,Spring会将自身的异常自动转换为合适的状态码
Spring异常 | HTTP状态码 |
---|---|
BindException | 400 - Bad Request |
ConversionNotSupportedException | 500 - Internal Server Error |
HttpMediaTypeNotAcceptableException | 406 - Not Acceptable |
HttpMediaTypeNotSupportedException | 415 - Unsupported Media Type |
HttpMessageNotReadableException | 400 - Bad Request |
HttpMessageNotWritableException | 500 - Internal Server Error |
HttpRequestMethodNotSupportedException | 405 - Method Not Allowed |
MethodArgumentNotValidException | 400 - Bad Request |
MissingServletRequestParameterException | 400 - Bad Request |
MissingServletRequestPartException | 400 - Bad Request |
NoSuchRequestHandlingMethodException | 404 - Not Found |
TypeMismatchException | 400 - Bad Request |
异常一般为Spring自身抛出,作为DispatcherServlet处理过程中或执行校验时出现问题的结果。
Spring可以通过@ResponseStatus
注解将异常映射为HTTP 状态码
@ResponseStatus注解: 将异常映射为特定的状态码
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="Spittle Not Found") // 将异常状态映射为404
public class SpittleNotFoundException extends RuntimeException{
}
引入@ResposneStatus
注解之后,如果控制器方法抛出SpittleNotFoundException
异常的话,响应将会具有404状态码
SpittleNotFoundException
将异常映射为特定的状态码@RequestMapping(value="/{spittleId}", method=RequestMethod.GET)
public String spittle(@PathVariable("spittleId") long spittleId, Model model){
Spittle spittle = spittleRepository.findOne(spittleId);
if(spittle == null){
throw new SpittleNotFoundException();
}
model.addAttribute(spittle);
return "spittle";
}
之前通过异常映射为状态码但如果需要将响应中不仅要包含状态码还要有所产生的错误,则就不同将异常视为HTTP错误需要按照处理请求的方式来处理异常
@RequestMapping(method=RequestMethod.POST)
public String saveSpittle(SpittleForm form, Model model){
try{
spittleRepository.save(new Spittle(null, form.getMessage(), new Date(), form.getLongitude(), form.getLatitude()));
return "redirect:/spittles";
}catch(DuplicateSpittleException e){
return "error/duplicate";
}
}
@ExceptionHandler(DuplicateSpittleException.class)
public String handleDuplicateSpittle(){
return "error/duplicate";
}
handleDuplicateSpittle()
方法添加@ExceptionHandler
注解,当抛出DuplicateSpittleException异常时候,将委托该方法进行处理。
对于@ExceptionHandler
注解标注的方法能处理同一个控制器中所有处理器方法所抛出的异常。
控制器类的特定切面能够运用到整个应用程序的所有控制器中。
控制器通知(Controller Advice)是任意带有@ControllerAdvice
注解的类,此类包含一个或多个以下类型的方法
@ExceptionHandler
@InitBinder
@ModelAttribute
@ControllerAdvice
实用的一个场景是将所有的@ExceptionHandler
方法收集到一个类中,这样所有控制器的异常就能在一个地方进行一致的处理。
@ControlerAdvice
为所有的控制器处理异常@ControllerAdvice
public class AppWideExceptionHandler{ // 定义控制器类
@ExceptionHandler(DuplicateSpittleException.class)
public String duplicateSpittleHandler(){ // 定义异常处理方法
return "error/duplicate";
}
}
将DuplicateSpittleException的处理方法用到整个应用程序的所有控制器上。现在,如果任意的控制器方法抛出了DuplicateSpittleException
不管这个方法位于哪个控制器中,都会调用这个duplicateSpittleHandler()
方法来处理异常。
对于重定向来说,模型无法用来传递数据。
return "redirect:/spitter/{username}"
@RequestMapping(value="/register", method=POST)
public String processRegistration(Spitter spitter, Model model){
spitterRepository.save(spitter);
model.addAttribute("username", spitter.getUsername());
return "redirect:/spitter/{username}";
}
此时username作为占位符填充到URL模板中,不是直接连接到重定向String中,所以username中所有的不安全字符都会进行转义。允许用户输入任何想要的内容作为username,并将其附加到路径上。
模型中所有其他的原始类型值都可以添加到URL中作为查询参数。
@RequestMapping(value="/register", method=POST)
public String processRegistration(Spitter spitter, Model model){
spitterRepository.save(spitter);
model.addAttribute("username", spitter.getUsername());
model.addAttribute("spitterId", spitter.getId()); // 此时spitterId属性没有匹配重定向中URL的任何占位符,会自动以查询参数的形式附加到重定向URL上
return "redirect:/spitter/{username}";
}
eg: 如果username
属性是testxxx
且spitterId
是42
,则结果重定向URL路径是: /spitter/testxxx?spitterId=42
通过路径变量和查询参数的形式跨重定向传递数据是最简单直接的方式,但只限传输一些简单数据eg:String和数字值当发送复杂数据需要通过flash属性提供帮助的领域
如果需要发送实际的Spitter对象。
如果发送Spitter对象ID,处理重定向方法还需要从数据库中查找才能得到Spitter对象。但是在重定向之前已经获取Spitter对象如何直接将该已经存在的对象直接发送给处理重定向的方法则需要flash
Spitter对象比String和int更为复杂,不能像路径变量和查询参数那么容易发送Spitter对象。只能将其设置为模型中的属性。
存在的另一种方案。将Spitter放到会话中,会话能够长期存在,且能够跨越多个请求。可以在重定向发生之前将Spitter放到会话中。并在重定向后,从会话中将其取出,最后在重定向后在会话中将其清理掉。
Spring提供RedirectAttributes
设置flash属性的方法。RedirectAttributes
提供Model的所有功能还有用来设置flash属性的方法
RedirectAttributes提供一组addFlashAttribute()方法来添加flash属性。
@RequestMapping(value="/register", method=POST)
public String processRegistration(Spitter spitter, RedirectAttributes model){
spitterRepository.save(spitter);
model.addAttribute("username", spitter.getUsername());
model.addFlashAttribute("spitter", spitter);
return "redirect:/spitter/{username}";
}
调用addFlashAttribute()
方法,将spitter作为key,Spitter对象作为值。还可以不设置key参数,让key根据值的类型自行推断:model.addFlashAttribute(spitter)
在重定向执行之前,所有的flash属性都会复制到会话中。
在重定向执行之后,存在会话中的flash属性会被取出,并从会话转移到模型之中。处理重定向的方法能从模型中访问Spitter对象,像获取其他的模型对象一样。
视图渲染+Spring MVC进阶技术 -- 《Spring In Action》
原文:https://www.cnblogs.com/openmind-ink/p/13628704.html