Java学习笔记——SpringMVC框架
一、注解
@RequestMapping:此注解可以放在方法和类上面,用于用于映射url到控制器类或一个特定的处理程序方法,若用在类上,则此类所有处理请求的方法都以该地址作为父路径。还有各种属性
/**
* @RequestMapping有8个属性
* value:访问路径,若只有value属性可以省略不写value,例@RequestMapping("/t")
* method:接受访问的请求方式有GET、POST、PUT、DELETE等。
* params:是表明处理请求必须的参数
* headers:表明处理请求的请求头参数
* consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html
* produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
*
* */
@RequestMapping(value="/t",method=RequestMethod.GET,params={"name","age!=12"},
headers={"Accept-Language=en-US,zh;q=0.8"},consumes={"application/json"},produces={})
public String t(){
System.out.println(2);
return "success";
}
@PathVariable
/**
* @PathVariable:SpringMVC向rest风格发展的标志。
* */
@RequestMapping("/t1/{id}")
public String t1(@PathVariable("id")Integer id){
System.out.println(id);
return "success";
}
@RequestParam
/**
* @RequestParam:获取请求参数
* required设置非必要参数
* defaultValue设置默认参数值
* 注意:若required为false时要把int设置成Integer类型或者设置defaultValue值,
* 否则抛出IllegalStateException异常
* */
@RequestMapping("/t2")
public String t2(@RequestParam("id")Integer id,
@RequestParam(value="name",required=false/*,defaultValue="0"*/)int name){
System.out.println(id);
System.out.println(name);
return "success";
}
@RequestHeader
/**
* @RequestHeader:获取请求头参数
* */
@RequestMapping("/t3")
public String t3(@RequestHeader(value="Accept-Language")String s1){
System.out.println(s1); //输出结果为: zh-CN,zh;q=0.8
return "success";
}
@CookieValue
/**
* @CookieValue:获取Cookie各属性值
* */
@RequestMapping("/t4")
public String t4(@CookieValue("JSESSIONID")String s1){
System.out.println(s1);
return "success";
}
@SessionAttributes:讲数据放到session域里面
@ModelAttribute:被此注解标记的方法会在每个目标方法执行之前先被调用一次!(但内部实行原理较复杂,可以参考尚硅谷SpringMVC第20集)
@ControllerAdvice:修饰处理异常的类。
@ResponseStatus:自定义异常类,可以标注类或者方法上。
@ResponseStatus(reason="异常",value=HttpStatus.NOT_FOUND)
public class FirstException extends RuntimeException{
/**
*
*/
private static final long serialVersionUID = 1L;
}
//@ResponseStatus(reason="异常two",value=HttpStatus.NO_CONTENT)
@RequestMapping("/t12")
public String t12(@RequestParam("num")int num){
System.out.println(1);
if(num==1){
System.out.println(2);
throw new FirstException();
}
System.out.println("FirstException");
return "success";
}
二、SpringMVC的应用
1、SpringMVC支持pojo入参,若一个表单中各个属性有与之相配的实体类。可以直接将实体类入参,SpringMVC会自动将表单中各个参数封装到实体类中去。例:
2、增删改查对应着post、delete、put、get,因为表单只能提交为post和get,使用hidden隐藏域、name=“_method”,添加HiddenHTTPMethodFilter过滤器把post请求转化为delete或put请求
3、SpringMVC支持原生servletAPI
4、ModelAndView、Map处理模型数据(ModelMap也一样)
/**
* Map处理模型数据
* */
@RequestMapping("/t6")
public String t6(Map<String, Object> map){
map.put("time", new Date());
return "success";
}
/**
* ModelAndView处理模型数据
* */
@RequestMapping("/t5")
public ModelAndView t5(){
ModelAndView modelAndView=new ModelAndView("success");
modelAndView.addObject("time", new Date());
return modelAndView;
}
5、国际化资源
1、首先要在配置文件中配置ResourceBundleMessageSource类来处理国际化资源文件。
2、在src目录下创建资源文件
6、WEB-INF下的文件是不能被直接访问的,但有时候我们也需要直接访问一些页面,例如登录注册页面。这是就可以 用<mvc:view-controller path="/q" view-name="q"/>标签,不过该标签需要和<mvc:annotation-driven></mvc:annotation-driven>标签一起用。
<!-- 配置直接转发页面 -->
<!-- 可以直接转发的页面,无需经过Handler的方法 -->
<mvc:view-controller path="/q" view-name="q"/>
<mvc:annotation-driven></mvc:annotation-driven>
7、 SpringMVC可以自定义视图,可以整合Excel,jsp等视图技术。只要配置BeanNameViewResolver类,order值越小,优先级越高,InternalResourceViewResolver的order为 Integer.MAX_VALUE。视图类实现View接口。接口return返回值只需写上视图类的首字母小写全称就可以了。
<!-- 第四步:建立jsp试图解析器 -->
<bean id="jspResourceViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
@Component
public class HelloView implements View {
@Override
public String getContentType() {
return "text/html";
}
@Override
public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
throws Exception {
response.getWriter().print("hello"+new Date());
}
}
@RequestMapping("/t9")
public String t9(){
System.out.println("t9");
return "helloView";
}
8、SpringMVC重定向可以在return "redirect:/namespace/toController";转发:return "forward:/namespace/toController";
9、SpringMVC类型转换自定义转换类继承org.springframework.core.convert.converter类,并注册为Spring成员。
配置ConversionServiceFactoryBean,并在<mvc:annotation-driven>的注入属性conversion-service,属性值是ConversionServiceFactoryBean Bean的id值。
10、mvc:annotation-driven 标签
在配置文件中配置<mvc:annotation-driven>会自动注册三个Bean。RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean,这是Spring MVC为@Controller分发请求所必需的,并且提供了数据绑定支持。
11、数据格式化。时间、数字等可以直接在实体类字段上面添加注解,时间用@DateTimeFormat、数字用@NumberFormat,若想自定义类型和SpringMVC提供的类型转换同时生效则要把ConversionServiceFactoryBean换成FormattingConversionServiceFactoryBean。
12、数据校验,加入jsr 303数据验证jar包,然后在需要数据验证的bean类字段上加上需要验证的注解。在接口上bean类入参前面要加上@Vaild注解,SpringMVC会自动把错误信息放到BindingResult里面。
@Min(100)
@NumberFormat(pattern="#,###,###.#")
private Integer id;
@NotEmpty
private String age;
@NotNull
private String name;
@DateTimeFormat(pattern="yyyy-mm-dd")
private Date brith;
@Email
private String Email;
@RequestMapping("/t10")
public String t10(@Valid User user,BindingResult result){
System.out.println(user);
if(result.getErrorCount()>0){
System.out.println("error!");
for(FieldError fieldError:result.getFieldErrors()){
System.out.println(fieldError.getField()+"---"+fieldError.getDefaultMessage());
}
}
return "success";
}
13、返回json数据,加入三个jar包,然后再接口上加上@ResponseBody注解,返回值直接为数据集合。返回值为byte[]数组可以实现下载的效果。
14、SpringMVC文件上传利用 MultipartResolver接口,SpringMVC自身没有提供上传实现,利用Apache的commons-fileupload-1.3.1.jar和commons-io-2.4.jar,表单的file名字和入参的@RequestParam的属性值要一致。
15、SpringMVC拦截器,<mvc:mapping path="/test/*" />可以配置拦截器的作用范围。拦截器的作用顺序跟在配置文件中的配置顺序有关,preHandle方法执行顺序是配置文件中的正序,postHandle和afterCompletion方法的配置文件中的反序。
public class FirstInterceptor implements HandlerInterceptor{
/**
* 方法在目标方法渲染视图之后执行方法。
* */
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
System.out.println("FirstInterceptor - "+"afterCompletion");
}
/**
* 方法在目标方法之后,渲染视图之前执行。
* 入参属性中有ModelAndView,可以对请求域中的属性或视图做出修改。
* */
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
System.out.println("FirstInterceptor - "+"postHandle");
}
/**
* 方法在目标方法之前执行
* 返回true,后续的拦截器会被继续执行。
* 返回false,后续的拦截器不会被继续执行。
* */
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
System.out.println("FirstInterceptor - "+"preHandle");
return true;
}
}
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="104857600" />
<property name="maxInMemorySize" value="4096" />
<property name="defaultEncoding" value="UTF-8"></property>
<!-- <property name="uploadTempDir" value="fileUpload/temp"></property> -->
</bean>
若第一个拦截器返回的是true,第二个返回的是false时。
16、SpringMVC异常处理
①、在当前Handler中添加异常处理方法使用@ExceptionHandler注解修饰,并传入异常类。
②、@ExceptionHandler方法中的入参不可以传入Map中。若想把异常传到页面上则需要用到ModelAndView对象。
③、@ExceptionHandler方法标记的异常有优先级的问题,与发生的异常匹配度越高优先级越高。也可以写专门处理异常的类,使用@ControllerAdvice注解来修饰类,若在当前Handler找不到匹配的异常处理(当前Handler中的@ExceptionHandler方法异常类是发生异常的父类,也会找到当前Handler的方法处理异常,即只有当前Handler没有与之匹配的异常类才会去找@ControllerAdvice修饰的类处理异常),则会去被@ControllerAdvice修饰的类中找匹配的异常处理方法来处理异常。
@ExceptionHandler(ArithmeticException.class)
public ModelAndView handlerException(Exception ex){
System.out.println(ex);
ModelAndView modelAndView=new ModelAndView("error");
modelAndView.addObject("exception",ex);
return modelAndView;
}
@RequestMapping("/t11")
public String t11(@RequestParam("num")int num){
int i=10/num;
System.out.println(i);
return "success";
}
@ControllerAdvice
public class ExceptionHandler {
@org.springframework.web.bind.annotation.ExceptionHandler(ArithmeticException.class)
public ModelAndView handlerException(Exception ex){
System.out.println("--->>"+ex);
ModelAndView modelAndView=new ModelAndView("error");
modelAndView.addObject("exception",ex);
return modelAndView;
}
}
17、SpringMVC在restfull风格中无法获取小数点,详细原因参考。
解决方法有两种:
1.在占位符里添加:.+,。
2.在<mvc:annotation-driven></mvc:annotation-driven>中添加<mvc:path-matching registered-suffixes-only="true"/>
.三、总结
1、SpringMVC运行流程。
一、先用文字描述
1.用户发送请求到DispatchServlet
2.DispatchServlet根据请求路径查询具体的Handler
3.HandlerMapping返回一个HandlerExcutionChain给DispatchServlet
HandlerExcutionChain:Handler和Interceptor集合
4.DispatchServlet调用HandlerAdapter适配器
5.HandlerAdapter调用具体的Handler处理业务
6.Handler处理结束返回一个具体的ModelAndView给适配器
ModelAndView:model-->数据模型,view-->视图名称
7.适配器将ModelAndView给DispatchServlet
8.DispatchServlet把视图名称给ViewResolver视图解析器
9.ViewResolver返回一个具体的视图给DispatchServlet
10.填充数据,渲染视图。
11.展示给用户
二、画图解析
2 、SpringMVC三大组件处理器映射器、处理器适配器、视图解析器。
处理器映射器:注解式处理器映射器,对类中标记了@ResquestMapping的方法进行映射,根据@ResquestMapping定义的url匹配@ResquestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器。
<!-- 配置处理器映射器 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
处理器适配器:对标记@ResquestMapping的方法进行适配
<!-- 配置处理器适配器 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" />
解决办法:
SpringMVC使用<mvc:annotation-driven>自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter
可以在springmvc.xml配置文件中使用<mvc:annotation-driven>替代注解处理器和适配器的配置。
<!-- 注解驱动 -->
<mvc:annotation-driven />
视图解析器:视图解析器使用SpringMVC框架默认的InternalResourceViewResolver,这个视图解析器支持JSP视图解析。
<!-- 配置视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置逻辑视图的前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 配置逻辑视图的后缀 -->
<property name="suffix" value=".jsp" />
</bean>
最终jsp物理地址:前缀+逻辑视图名+后缀
3、参数类型推荐使用包装数据类型,因为基础数据类型不可以为null。
4、SpringMVC与struts2的不同
- SpringMVC的入口是一个servlet即前端控制器,而struts2入口是一个filter过滤器。
- SpringMVC是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
- Struts2采用值栈存储请求和响应的数据,通过OGNL存取数据, SpringMVC通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过request域传输到页面。Jsp视图解析器默认使用jstl。