源码地址: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"
[email protected]的参数是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";
}
[email protected]的作用就是监听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短。