源碼地址:https://github.com/Young4Dream/yan/tree/master/Maven_spittr
筆記:
1.當DispatcherServlet啟動時,會創建Spring應用上下文,並加載配置文件或配置類中所聲明的bean。getServletConfigClasses()方法中,要求DispatcherServlet加載應用上下文時,使用定義在WebConfig配置類中的bean。但是在SpringWeb應用中,通常還會有另外一個應用上下文,另外的應用上下文在ContextLoaderListener創建。我們希望DispatcherServlet加載包含Web組件的bean,如控制器、視圖解析器以及處理器映射,二ContextLoaderListener要加載應用中其他的bean。這些bean通常是驅動應用后端的中間層和數據層組件。實際上AbstractAnnotationConfigDispatcherServletInitializer會同時創建DispatcherServlet和ContextLoaderListener。getServletConfigClasses方法返回的帶有@Configuration注解的類將會用來定義DispatcherServlet應用上下文中的bean。getRootConfigClasses方法返回帶有@Configuration注解的類將會用來配置ContextLoaderListener創建的應用上下文中的bean。
2.設置WebMvcConfigurerAdapter為WebConfig的父類,用來配置靜態資源,並重寫configureDefaultServletHandling方法,並使得默認的servlet生效:configurer.enable();
3.Controller中的@RequestMapping(method=GET,value="/")中的GET需要引入import static org.springframework.web.bind.annotation.RequestMethod.GET;
4.從Spring3.2開始,我們可以按照控制器的方式來測試SpringMVC中的控制器了,而不僅僅是作為POJO進行測試。Spring現在包含了一種mock Spring MVC並針對控制器執行HTTP請求的機制。這樣的話,在測試控制器的時候,就沒有必要再啟動Web服務器和Web瀏覽器了。要注意引用的靜態包!!!
5.類級別的@RequestMapping相當於命名空間,如果類級別的mapping為"/home",方法級別的mapping為"/method",那么得到此方法返回的視圖名時所要指定的action為"/home/method"
6.@RequestMapping的參數是String[]類型,也就是說可以指定多個action,如{"/","/home"},這表示兩個都有效
7.Model類型其實是一個Map,它會傳遞給視圖,這樣數據就能夠渲染到客戶端了,當調用model.addAttribute()方法並且不指定key的時候,那么key會根據值得對象類型推斷確定,如果是List<Book>,則會默認為bookList,以后可能會用ModelAndView類型,此處先不追究了。
8.如果想顯式聲明key的話,也可以自行指定,model.addAttribute("key",Object obj)
9.如果希望使用非Spring類型,也可以用Map來代替Model,model.addAttribute()變更為model.put()即可,原理參見https://zhidao.baidu.com/question/564038740.html
10.有有參構造方法時,一定一定要給對應bean的類中添加無參構造方法!!!!!!!!!!!!!!!!!!否則啟動時會報no default constructor found 異常
11.當java文件出現此錯誤:The type javax.servlet.ServletException cannot be resolved. It is indirectly referenced from required .class files,只需要添加tomcat的lib目錄中的servlet-api.jar即可
12.fn:length()是jstl函數,返回字符串長度或集合中元素的數量。
13.<mvc:annotation-driven/>相當於注冊了DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter兩個bean,配置一些messageconverter。即解決了@Controller注解的使用前提配置。
14.<context:annotation-config/>是對包進行掃描,實現注釋驅動Bean定義,同時將bean自動注入容器中使用。即解決了@Controller標識的類的bean的注入和使用。
15.配置如果沒有<mvc:annotation-driven/>,那么所有的Controller可能就沒有解析,所有當有請求時候都沒有匹配的處理請求類,就都去<mvc:default-servlet-handler/>即default servlet處理了。添加上<mvc:annotation-driven/>后,相應的do請求被Controller處理,而靜態資源因為沒有相應的Controller就會被default servlet處理。總之沒有相應的Controller就會被default servlet處理就ok了。
16.插入的sql語句最好寫全,不然會因為順序不對而錯位:
String sql="insert into spitter(id,firstname,lastname,username,password,email) values(" +
"seq_spitter.nextval,:firstname,:lastname,:username,:password,:email" +
")";
17.跳轉個人信息頁面時報:Mapped class was not specified異常。
原因:沒傳Spitter.class進去。
解決:rowMapper=new BeanPropertyRowMapper<Spitter>(Spitter.class);
18.當你開發一個項目,如果你選擇的是spring MVC 框架,而你在前台使用spring的標簽時,那么你有可能出現在這個情況。
javax.servlet.jsp.JspTagException: Neither BindingResult nor plain target object for bean name 'command' available as request attribute
方法:1為拋出異常原因,2為異常解決方法。
1. 原因: 進入spring:bind標簽源碼你可以看到
Object target = requestContext.getModelObject(beanName);
if (target == null) {
throw new IllegalStateException("Neither BindingResult nor plain target object for bean name '" +
beanName + "' available as request attribute");
}
beanName= <spring:bind path="command.spjg">的綠色部分
如果你是直接對某個頁面進行請求,那么request中還沒command這個對象
2.
在頁面上加上
<jsp:useBean id="command" class="com.ztenc.proj.bean.AFRFOAP" scope="request" ></jsp:useBean>
紅色部分填上你的綁定類
public String register(@Valid @ModelAttribute("spitter") Spitter spitter,BindingResult errors){
19.BindingResult和Errors同樣可以起到校驗的效果,它們同位於org.springframework.validation包中
20.實現國際化:
1.使用spring的<%@ taglib prefix="s" uri="http://www.springframework.org/tags"%>中的<s:message/>實現;
2.配置信息源:ResourceBundleMessageSource或ReloadableResourceBundleMessageSource,分別以A和B代稱
A方案是在根路徑下配置,名字與配置的BaseName有關,如:BaseName="a",那么在根路徑下新建a.properties文件;
B方案是在整個系統中配置,可用classpath或file來修飾
3.使用方法:<s:message code="key"/>
21.Multipart文件上傳見xmind文件
22.處理異常
22.1對於能轉換成HttpStatus的異常
1.創建處理某類異常的類,讓其繼承RuntimeException
public class SpittleNotFoundException extends RuntimeException{}
2.添加@ResponseStatus注解,標明對應的HttpStatus的值,並自定義reason
@ResponseStatus(value=HttpStatus.NOT_FOUND,reason="Spittle Not Found")
3.例子:在(controller或Dao層都行)相關方法中加入try-catch塊即可:
try {
spittle = jt.queryForObject(sql, rowMapper, id);
} catch (Exception e) {
throw new SpittleNotFoundException();
}
4.當出現錯誤時顯示信息如下:
HTTP Status 404 - Spittle Not Found
type Status report
message Spittle Not Found
description The requested resource is not available.
Apache Tomcat/7.0.65
22.2對於無對應HttpStatus的異常:比如重復插入數據
1.創建處理異常的類
public class DuplicateSpitterException extends RuntimeException{}
2.在controller層新增方法,表示當此類中有拋出自定義異常DuplicateSpitterException時,指定對應的邏輯視圖名
@ExceptionHandler(value=DuplicateSpitterException.class)
public String handleDuplicateSpitter(){
return "error/error";
}
3.@ExceptionHandler的作用就是監聽DuplicateSpitterException,只要拋出DuplicateSpitterException類的異常便會轉向相應的視圖
4.這種方式可以處理同一個Controller類中拋出的DuplicateSpitterException異常
22.3處理全局異常
1.創建一個定義全局異常的類:public class APPWideException extends RuntimeException{}
2.創建一個專門處理全局異常的類,它其實是一個Controller,並且在其類上添加@ControllerAdvice,這樣就可以監聽所有Controller層拋出的異常
3.在APPWideExceptionController中定義全局異常的處理方法,指定邏輯視圖
4.如果@ControllerAdvice監聽到的異常在此類中有定義的處理方法,則會照此規則執行,如定義了APPWideException.class,捕捉到則執行error/appError處理
package com.spring.mvc.controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import com.spring.mvc.web.APPWideException;
@ControllerAdvice
public class APPWideExceptionController {
@ExceptionHandler(value=APPWideException.class)
public String appWideExceptionHandler(){
return "error/appError";
}
}
23.跨重定向請求數據
23.1可以使用redirect:/spitter/{username},前提是:model.addAttribute("username",spitter.getUsername());
23.2如果有多余參數,如model.addAttribute("id",spitter.getId());,那么會變為.../spitter/yan?id=***;
23.3使用model.addFlashAttribute("spitter",spitter)可以傳遞除String和數字類型外的數據,作用域為重定向完成為止,比session短。