SpringMvc框架知识简介

来源:互联网 发布:淘宝卖家规则大全2017 编辑:程序博客网 时间:2024/05/24 23:15
一.SpringMvc的执行流程
(1).浏览器发送请求到中央调度器(DispatchServlet)
(2)中央调度器直接将请求转给处理器映射器
(3)处理器映射器对请求进行简单判断后,找到处理该请求的处理器,将其封装为处理器执行链发送给中央调度器
(4)中央调度器根据处理器执行链中的处理器,找到可以执行该处理器的处理器适配器
(5)中央调度器调用执行处理器执行链中的拦截器前端方法,然后处理器适配器调用执行该处理器
(6)处理器将执行结果和要跳转的视图封装成ModelAndView对象,返回给处理器适配器
(7)处理器适配器直接将结果返回给中央调度器
(8)中央调度器调用执行拦截器后端方法postHandler(),因为中央处理器将ModelAndView传递给了postHandler(),该方法可以对ModelAndView进行修改,形成最终的调度结果,然后,中央调度器调用试图解析器,将ModelAndView中的视图名称封装为视图对象
(9)视图解析器将封装后的视图对象返回给中央调度器
(10)中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象,这个渲染过程主要做了三件事:1、合并Model;2、结合视图中的目标定位对象,准备响应对象Response;3、结合合并的Model与形成的响应对象Response,形成最终的响应视图,然后执行处理器执行链中的afterCompletion()方法,由该方法发出对请求的最终响应
(11)中央调度器响应浏览器

二.springmv注解式开发
1.配置文件
(1)配置组件扫描器,即处理器,指定处理器所在的包(@RequestMapping中可以写多个路径,并且@RequestMapping中还有一个属性是produces,该属性可以定义返回的字符集)
(2)注册mvc的注解驱动
2.中文乱码问题的解决
(1)在web.xml中注册字符集过滤器,并将该过滤器注册在第一个,因为过滤器是按照注册的顺序执行的
(2)可以在代码中指定字符集,但如果代码中指定了字符集,但是使用代码中指定的字符集的前提是web.xml中forceEncoding为false

三.请求转发和重定向
请求转发和重定向是springMvc的核心技术,这两种跳转方式都可以跳转到页面和controller,但是转发可以跳转到WEB-INF下的页面,而重定向不可以;两种跳转方式的返回值有三种:ModelAndView,String,void
1.返回值是ModelAndView,若需要向下传递参数,可以使用request,session,Model,request主要用于转发,因为它是一次请求,session和Model主要用于重定向;
请求转发,例如:
public ModelAndView doSome(){
ModelAndView mv = new ModelAndView ();
mv.addObject("student",student);
mv.setViewName("forward:third.do");或
mv.setViewName("forward:/WEB-INF/jsp/show.jsp");
return mv;
}
请求转发是可以携带参数的,而重定向不可以。且转发是一次请求,重定向是多次请求
重定向:
(1)重定向到页面
a.请求参数可以通过ModelAndView中的Model传递,但是视图解析器会将map中key和value当作参数放到url中去,所以放到Model中的数据只能是String类型的,不能是其他类型。前端接收参数时可以使用param来接收
b.使用HttpSession来传递,后台使用HtppSession来传递参数时,前端可以使用sessionScope来接受,例:
public ModelAndView doSome(Student student,HttpSession session){
session.setAttribute("student",student);
return new ModelAndView("redirect:/show.jsp");
}
(2)重定向到controller
a.使用Model传递参数,只要保证目标方法的参数名称与传递的参数名称一致就好,例1(参数逐个接收)
public ModelAndView doSome(Student student){
ModelAndView mv = new ModelAndView ();
mv.addObject("pname",student.getName);
mv.addObject("page",student.getAge);
mv.setViewName("redirect:third.do");
return mv;
}
public ModelAndView doOther(Stringpname,intpage){
ModelAndView mv = new ModelAndView();
mv.addObject("myStudent",new Student(pname,page));
mv.setViewName("forward:/WEB-INF/jsp/show.jsp");
return mv;
}
例2(参数整体接收)
public ModelAndView doSome(Student student){
ModelAndView mv = new ModelAndView ();
mv.addObject("name",student.getName);
mv.addObject("age",student.getAge);
mv.setViewName("redirect:third.do");
return mv;
}
public ModelAndView doOther(Studentstudent){
ModelAndView mv = new ModelAndView();
mv.addObject("myStudent",student);
mv.setViewName("forward:/WEB-INF/jsp/show.jsp");
return mv;
}
b.使用HttpSession传递参数
public ModelAndView doSome(Student student,HttpSession session){
session.setAttribute("student",student);
return new ModelAndView("redirect:other.do");
}
public ModelAndView doOther(HttpSession session){
Student student = (Student) session.getAttribute("student");
return new ModelAndView("forward:/WEB-INF/jsp/show.jsp");
}

2.返回值是String
a.请求转发:当返回值是ModelAndView时,跳转到页面和controller时,参数都可以传递过去,而返回值是String时,就不可以了。因为返回值是String时,创建一个ModelAndView对象,它只是一个局部变量,方法运行结束,变量就销毁了,所以,当返回值是String时,不能用ModelAndView传递参数,而且当处理器接收到请求参数后,发现用于接收这些参数的处理器方法形参为包装类对象,则处理器会将参数包装为对象传递给形参外,还会将参数存放到request域属性中,例如:
传入的参数为name,age,经过下面的方法时,就已经将参数包装成student类传入了,此时,在前端页面可以使用requestScope来获取值
public String doSome(Student student){
return "forward:/WEB-INF/jsp/shou.jsp";
}
前端获取值:${requestScope.student}
注:因为在一个类上加了@Controller注解,就说明该类是一个处理器,所以当处理器发现处理器方法用来接收参数的形参为一个对象时,自动就会把参数包装成一个对象,跟加不加其他注解没关系,所以传入的参数要和该对象的属性名称保持一致,要用反射将参数映射到对象的属性上去
b.重定向:
(1)重定向到页面
方法一:通过Model形参携带参数,这个方式也是将参数拼接到URL上,所以参数必须是基本类型的,而不是自定义类型,例如:
public String doSome(Student student,Model model){
model.addAttribute("pname",student.getName);
model.addAttribute("page",student.getAge);
return "redirect:/show.jsp":
}
方法二:通过RedirectAttributes的addAttribute()携带参数,RedirectAttributes()是专门用于携带重定向参数的,它是一个继承自Model()的接口,通过addAttribute()会将参数名和参数值放到Map中,然后视图解析器会将其拼接到URL中,所以,这种携带参数的方式,不能携带自定义对象
例如:
public String doOther(Student student,RedirectAttributes ra){
ra.addAttribute("pname",student.getName);
ra.addAttribute("page",studnet.getAge);
return "redirect:/show.jsp";
}
注:因为RedirectAttributes是一个接口,它的实参会有MVC的注解驱动自动赋值,所以要使用RedirectAttribute需要在springmvc的配置文件中配置注解驱动
(2)重定向到controller
方法:使用URL携带参数,使用HttpSession,使用Model,使用RedirectAttributes的addAttribute()方法,例如:
public String doSome(Student student,Model model){
model.addAttribute("pname",student.getName());
model.addAttribute("page",student.getAge());
return "redirect:other.do";
}
public String doOther(Stringpname,Integerpage){
return "forward:/WEB-INF/jsp/show.jsp";
}
3.返回值是void
请求转发:当返回值是void时,需要使用HttpServletRequest的请求转发方法,无论下一级资源是页面还是controller,而且当有数据需要向下一级资源传递时,不能使用Model和RedirectAttributes,因为这两种方式都是将参数拼接到返回值中向下传递的,但此时没有返回值,所以只能将参数放到request和session中,例如:
public void register(HttpServletRequest request,HttpServletResponse response,Student student){
request.setAttribute("myStudent",s
tudent);
request.getRequestDispatcher("/WEB-INF/jsp/show.jsp").forward(request,response);
}
前端获取:student=${myStudent}
请求重定向:重定向使用HttpServletResponse的sendRedirect()方法实现,当有参数时,需要将参数放到session中,例如:
public void register(HttpServletRequest request,HttpServletResponse response,HttpSession session,Student student){
session.setAttribute("myStudent",student);
response.sendRedirect(request.getContextPath()+"/show.jsp");
}
前端获取:student=${myStudent}
四、异常
(1)异常处理器:SimpleMappingExceptionResolver
(2)自定义异常处理器:异常处理类需要实现HandlerExceptionResolver,在程序运行的过程中,只要发生异常,就会自动执行resolveException()方法,自定义异常类需要在配置文件中注册
例如:
public ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response,Object o,Exception ex){
ModelAndView mv = new ModelAndView();
mv.addObject("ex",ex);
if(exinstanceof NameException){
mv.setViewName("");
}
}
注:这里NameException就是自定义异常,instanceof 的用法:左边的是右边的实例
(3)异常注解:@ExceptionHandler,在一个方法上加上该注解表示该方法是异常处理方法,需要在该注解上加上自定义异常类,例如:@ExceptionHandler(NameException.class)
注:异常处理器和注解异常的区别:异常处理器捕获的是处理器方法执行过程中发生的发生的异常,而注解异常捕获的是处理器方法执行之前发生的异常

五、类型转换器
1、自定义类型转换器:需要实现Converter<arg1,arg2>接口,其中arg1是待转换的类型,第二个参数是目标类型,该接口的converter()方法完成类型转换,自定义转换器需要在配置文件注册
2、当自定义类型转换器发生异常,需要注解异常捕获异常,因为类型转换是发生在处理器方法执行之前,异常处理器是捕获不到的;而且正常情况下,发生类型转换异常后,系统会自动跳转到400页面,所以为了发生类型转换异常后能跳转到指定的页面,需要使用注解异常捕获异常,在注解异常的处理方法上指定跳转的页面。数据回显的原理就是这样

六、数据验证(可以有后台验证,也可以由前端验证)
1、后台验证的步骤:
(1)、在配置文件中注册数据验证的类LocalValidtorFactoryBean,并将其注入给驱动
(2)、在实体类属性上添加验证注解(常用注解有:非空验证@Empty,长度验证@Size,最大最小值验证@Min,@Max,正则表达式验证@Pattern)
2、前端验证即表单验证
3、例如:
public ModelAndView register(@Validated Student student,BindingResultbr){
}
由于这里使用的验证器为bean对象验证器,所以需要将参数打包后用对象的方式接收,@Validated只能用在自定义的形参前,不可以用在String和基本类型的形参前,且加了@Validated的形参后,要跟上BindingResultBindingResult会对它之前的参数进行验证

七、文件上传
文件是否上传实际上是中央调度器在执行处理器映射器之前根据配置文件中的bean名称来判断的
1、单个文件上传:
(1)在配置文件中注册解析器CommonMultipartResolver,该bean的id必须为multipartResolver
(2)发送的请求需要是multipart请求的,即前端的enctype的值为multipart/form-data
(3)如果容器中定义了名称为multipart的bean,且请求也是multipart请求,则会返回MultipartHttpServletRequest,否则返回普通的HttpServletRequest
(4)文件上传的字符集:如果文件名称是中文名,且不设置上传时的字符集,那上传后的文件的名称回是乱码,因为文件上传处理器默认的编码方式为ISO-8859-1,解决方案就是设置encoding的字符集为UTF-8
(5)限定文件大小:可以在配置文件中限定文件大小
2、上传多个文件
(1)前端多个文件的名称必须一样
(2)当传入多个参数时,后台的参数是一个Multipart数组(Multipart[]),并且该数组必须加上@RequestParam注解.这是因为前端传入文件时,框架会自动将每一个文件转换成Multipart类型,但不会把这些Multipart类型的参数自动放到一个数组中,所以使用@RequestParam注解,就是要告诉框架,把这些Multipart类型的文件放到一个数组中传入,所以,当传入多个文件时,必须使用@RequestParam注解
(3)如果没有选择任何文件,这个数组也不为空,且长度也大于0,因为框架会自动为每个file表单元素创建File对象,只不过这个File对象没有指向任何文件,是空的,所以在上传时,需要对每一个表单元素进行判断,是否为empty;

八、拦截器
A、一个拦截器的执行
1、自定义拦截器:需要实现HandlerInterceptor接口,实现它的三个方法:
(1)、perHandler(HttpServletRequest request,HttpServletResponse response,Object handler),该方法是在执行处理器方法之前执行,它的返回值是boolean类型,如果为true,则会执行处理器方法,并将afterCompletion()放到方法栈中执行
(2)、postHandler(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView mv):该方法是在处理器方法执行之后执行,如果处理器方法没有执行,则该方法就不会执行,因为该方法中有ModelAndView,所以可以修改处理器方法的结果和将要跳转的页面
(3)、afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex):该方法是最后执行的,即中央处理器渲染数据后执行这个方法
B、多个拦截器的执行
多个拦截器的执行顺序与注册顺序一致,都是先执行preHandler()方法,在执行处理器方法,然后执行postHandler()方法,最后执行afterCompletion()方法;因为是一个拦截器执行链,所以,只要有一个preHandler()的返回值为false,则后面的方法都不会执行

C、权限拦截器:将用户信息放到session中,在preHandler()方法中,对用户输入的用户名和密码进行判断,如果是同一个用户,则执行处理器方法,否则,可以在preHandler()方法中转发到重新登录页面
原创粉丝点击