SpringMVC详解


简介

  • Spring MVC是Spring Framework提供的Web组件,全称是Spring Web MVC,是目前主流的实现MVC设计模式的框架,提供前端路由映射、视图解析等功能。

  • SpringMVC是Spring的一个后续产品,是Spring的一个子项目

  • SpringMVC 是 Spring 为表述层开发提供的一整套完备的解决方案。在表述层框架历经 Strust、WebWork、Strust2 等诸多产品的历代更迭之后,目前业界普遍选择了 SpringMVC 作为 Java EE 项目表述层开发的首选方案。

注:三层架构分为表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台
servlet

MVC是什么?

MVC是一种软件架构思想,把软件按照模型,视图,控制器来划分

  1. M(Model):模型层,指工程中的JavaBean,作用是处理数据
    • JavaBean分为两类:
      • 实体类Bean:专门存储业务数据的,如 Student、User 等,与数据库对应。
      • 业务处理 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。
  2. V(View):视图层,指工程中的htmljsp等页面,作用是与用户进行交互,展示数据
  3. C(Controller):指工程中的servlet,作用是接收请求和响应浏览器

优点

  1. 可以支持各种视图技术,而不仅仅局限于JSP;
  2. 与Spring框架集成(如IOC容器、AOP等)
  3. 清晰的角色分配:前端控制器(dispatcherServlet),请求到处理器映射(handlerMapping),处理器适配器(HandlerAdapter),视图解析器(ViewResolver
  4. 支持各种请求资源的映射策略

工作流程

(1)首先浏览器发送请求——>DispatcherServlet: 前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
(2)DispatcherServlet——>HandlerMapping: 通过对应的url寻找对应的映射器将会把请求映射为HandlerExecution对象重新发给DispatcherServlet
(3)DispatcherServlet——>HandlerAdapter: HandlerExecution将会寻找到相对应的适配器,就像对应型号的插头寻找对应的接口。
(4)HandlerAdapter——>调用处理器相应功能处理方法: 并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
(5)ModelAndView对象(Model部分是业务对象返回的模型数据,View部分为逻辑视图名)——> ViewResolver: 视图解析器将把逻辑视图名解析为具体的View;
(6)View——>渲染: View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构;
(7)返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。

在这里插入图片描述

核心组件

名词翻译说明
DispatcherServlet前端控制器负责调度其他组件的执行,可以降低不同组件之间的耦合性,是整个Spring MVC的核心模块
HandlerMapping处理器映射器DispatcherServlet是通过 HandlerMapping把请求映射到不同的Handler
Handler处理器处理器,完成具体的业务逻辑,相当于Servlet
HandlerInterceptor处理器拦截器是一个接口,如果我们需要进行一些拦截处理,可以通过实现该接口完成
HandlerExecutionChain处理器执行链包括两部分内容:HandlerHandlerInterceptor(系统会有一个默认的HandlerInterceptor,如果有额外拦截处理,可以添加拦截器进行设置)
HandlerAdapter处理器适配器Handler执行业务方法之前,需要进行一系列的操作包括表单的数据验证、数据类型转换、把表单数据封装到POJO等,这些一系列的操作都是由HandlerAdapter完成,DispatcherServlet通过HandlerAdapter执行不同的Handler
ModelAndView模型与视图封装了模型数据和视图信息,作为Handler的处理结果,返回给DispatcherServlet
ViewResolver视图解析器DispatcherServlet通过它把逻辑视图解析为物理视图,最终把渲染的结果响应给客户端
View视图渲染后的视图

Spring MVC常用注解

@RequestMapping

  • Spring MVC通过@RequestMapping注解把URL请求和业务方法进行映射
  • 在控制器的类定义处以及方法定义处都可以添加@RequestMapping,在类定义处添加相当于多了一层访问路径
  • 参数:
    • value:指定URL请求的实际地址,是@RequestMapping的默认值
    • method:指定请求的method类型,包括GET、POST、PUT、DELETE等
    • consumes指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
    • produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;
    • params指定request中必须包含某些参数值时,才让该方法处理。
    • headers指定request中必须包含某些指定的header值,才能让该方法处理请求。
  • @GetMapping,@PutMapping,@PostMapping,@DeleteMapping@RequestMapping用法级效果相同,但无method参数,因为注解直接表明了请求方式

参数绑定

@RequestParam:普通GET方式传参

  • 在业务方法定义时声明参数列表,给参数列表添加@RequestParam注解进行绑定
@RequestParam(value = "/test")
public class Test{
	@GetMapping(value = "/hello")
    public String hello(@RequestParam(value = "name",required=true) String name){
    }
}
  • 一般使用情况:GETDELETE
  • 访问上述接口地址为:xxx.xxx.xxx.xxx:xxxx/test/hello?name=jack,请求方法为:GET,参数为:name,是一个必传参数
  • 可以存在多个
  • 参数:
    • value :参数名称
      • 设置与url对应的参数名称并映射到方法的参数项
      • value值可以与方法的参数项不同,但必须与请求的参数名称相同,否则无法映射
      • value值一般最好与方法中的参数项保持一致
    • required是否必须
    • defaultValue设置默认值后,required就会失效,当请求地址中没有对应参数时就会使用此处设置

@PathVariable:RESTful URL风格传参
传统的URLxxx.xxx.xxx.xxx:xxxx/test/hello?name=jack
RESTful URL:xxx.xxx.xxx.xxx:xxxx/test/hello/jack

@RequestParam(value = "/test")
public class Test{
	@GetMapping(value = "/hello/{name}")
    public String hello(@PathVariable(value = "name",required=true) String name){
    }
}
  • 一般使用情况:GETDELETE
  • 可以存在多个
  • 参数:
    • value :参数名称
      • 设置与url对应的参数名称并映射到方法的参数项
      • value值可以与方法的参数项不同,但必须与请求的参数名称相同,否则无法映射
      • value值不可为空
    • required是否必须
    • defaultValue设置默认值后,required就会失效,当请求地址中没有对应参数时就会使用此处设置

@RequestBody:使用实体(对象)传参
实体:也就是对象、POJO
必须有 get set 方法

@Data //提供get set 方法
@AllArgsConstructor  //提供全参构造函数
@NoArgsConstructor //提供无参构造函数
public class Test{ 
		 private String name;
	    private Integer age;
	    private Integer sex;
}

接口示例

@RequestParam(value = "/test")
public class Test{ 
	@PostMapping("/user")
    public String userTest(@RequestBody User user){
        System.out.println(user);
        return "ok";
    }
}
  • 一般使用情况:POSTPUT
  • @RequestBody自动解析请求体json为实体对象
  • 一个请求,只有一个RequestBody(请求体)
  • 可与@RequestParam@PathVariable混合使用
    • @RequestBody只会解析请求体内的json
    • @RequestParam@PathVariable 还需按照原有方式进行传参,但可以是post请求
      @CookieValue:映射Cookie
  @RequestMapping("/cookie")
    public String getCookie(@CookieValue("JSESSIONID") String sessionId){
        System.out.println(sessionId);
        return "index";
    }
  • 一般使用情况:GETDELETEPOSTPUT
  • 用来获取Cookie中的值
  • 参数:
    • value:参数名称
      • Cookie名称
    • required:是否必须
    • defaultValue:默认值

转发和重定向

Spring MVC默认是通过转发的形式响应JSP

  • 转发:在返回值前面加"forward:",如:“forward:user.do?name=method4
  • 重定向:在返回值前面加"redirect:",如:“redirect:http://www.baidu.com

示例:常规用法,返回一个View

    @RequestMapping("/restful/{id}/{name}")
    public String restful(@PathVariable("id") Integer num, @PathVariable("name") String name){
        System.out.println(num+"-"+name);
        //Spring框架找到对应的View并渲染
        return "findex";
    }

示例:转发"forward:/…"

@RequestMapping(value="/testa", method=RequestMethod.POST)
public String outputData(HttpServletRequest request){
	//转发到 /testb 的Controller方法(即outputDataX)上
    return "forward:/testb"; 
}
 
@RequestMapping(value="/testb", method=RequestMethod.POST)
public String outputDataX(HttpServletRequest request){
    return "testb";
}

示例:重定向"redirect:/…"

@RequestMapping(value="/testa", method=RequestMethod.POST)
public String outputData(HttpServletRequest request){
    //重定向到 /testb 的Controller方法(即outputDataX)上
    return "redirect:/testb"; 
}
 
@RequestMapping(value="/testb", method=RequestMethod.POST)
public String outputDataX(HttpServletRequest request){
    return "testb";
}

设置重定向的时候不能写逻辑视图,必须写明资源的物理路径

重定向的三种方式

response.sendRedirect重定向跳转

@RequestMapping(value="/testredirect",method = { RequestMethod.POST, RequestMethod.GET })  
public String testredirect(HttpServletResponse response){  
    response.sendRedirect("/index");
    return "ok"; 
}

ViewResolver直接跳转

不带参数

@RequestMapping(value="/testredirect",method = { RequestMethod.POST, RequestMethod.GET })  
public  String testredirect(HttpServletResponse response){  
    return "redirect:/index";  
} 

带参数

@RequestMapping("/testredirect")
public String testredirect(Model model, RedirectAttributes attr) {
	//跳转地址带上test参数
	attr.addAttribute("test", "51gjie");
	//跳转地址不带上u2参数
    attr.addFlashAttribute("u2", "51gjie");
	return "redirect:/user/users";
}
  • 使用RedirectAttributesaddAttribute方法传递参数会跟随在URL后面,如上代码即为http:/index.action?test=51gjie
  • 使用addFlashAttribute不会跟随在URL后面,会把该参数值暂时保存于session,待重定向url获取该参数后从session中移除,这里的redirect必须是方法映射路径,jsp无效。你会发现redirect后的jsp页面b只会出现一次,刷新后b再也不会出现了,这验证了上面说的,b被访问后就会从session中移除。对于重复提交可以使用此来完成
  • spring mvc设置下RequestMappingHandlerAdapterignoreDefaultModelOnRedirect=true,这样可以提高效率,避免不必要的检索。

ModelAndView重定向

不带参数

@RequestMapping(value="/restredirect",method = { RequestMethod.POST, RequestMethod.GET })  
public  ModelAndView restredirect(String userName){  
    ModelAndView  model = new ModelAndView("redirect:/main/index");    
    return model;  
}

带参数

@RequestMapping(value="/toredirect",method = { RequestMethod.POST, RequestMethod.GET })  
public  ModelAndView toredirect(String userName){  
    ModelAndView  model = new ModelAndView("/main/index"); 
     //把userName参数带入到controller的RedirectAttributes  
    model.addObject("userName", userName); 
    return model;  
}

直接跳转某网页

@RequestMapping(value="/testredirect",method = { RequestMethod.POST, RequestMethod.GET })  
public String testredirect(HttpServletResponse response){  
  	HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
	httpServletResponse.sendRedirect("http://srip.cpu.edu.cn/#/admins");
    return "ok"; 
}

总结

  • redirect重定向可以跳转到任意服务器,可以用在系统间的跳转。
  • Spring MVC中redirect重定向,参数传递可以直接拼接url也可以使用RedirectAttributes来处理,由于是不同的请求,重定向传递的参数会在地址栏显示,所以传递时要对中文编码进行处理。

拦截器

过滤器、监听器、拦截器的对比

Servlet:处理Reequest请求和Response响应

  • 过滤器(Filter):
    • Request请求起到过滤作用,作用在Servlet之前,
    • 配置为\*可以为所有的资源(servlet、js/css静态资源等)进行过滤处理
  • 监听器(Listener):
    • 实现了javax.servlet.ServletContextListener接口的服务器端组件,它随Web应用的启动而启动,只初始化一次,然后一直监视,随Web应用的停止而销毁
    • 作用一做初始化工作,web应用中spring容器启动ContextLoaderListener
    • 作用二监听web中的特定事件,比如HttpSession,ServletRequest的创建和销毁;变量的创建、销毁和修改等可以在某些动作前后增加处理,实现监控,比如说统计在线人数,利用HttpSessionListener
  • 拦截器(Interceptor):
    • 是Spring MVC、Struts等表现层框架自己的
    • 不会拦截jsp/html/css/image等的访问,只会拦截访问的控制器方法(Handler)
    • servlet、filter、listener是配置在web.xml中,interceptor是配置在表现层框架自己的配置文件中
    • 在Handler业务逻辑执行之前拦截一次
    • 在Handler逻辑执行完但是还没有跳转页面之前拦截一次
    • 在跳转页面后拦截一次

拦截器基本概念

Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),用于对处理器进行预处理和后处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。

使用Spring MVC中的拦截器的定义和配置。
通常拦截器类可以通过两种方式来定义。
1.实现HandlerInterceptor接口
2. 继承HandlerInterceptorAdapter抽象类

实现HandlerInterceptor接口

  1. 创建拦截器类实现HandlerInterceptor接口
    	public class MyInterceptor1 implements HandlerInterceptor {
        /**
         * 访问controller方法之前执行
         * 返回为true才会去执行Controller方法,返回false,就被拦截了,原路打回(主要做权限控制,有权限才放行)
         * 注意:如果preHadle返回true,但是没有找到对应的Controller,是不会执行postHandle方法哦
         * @param request
         * @param response
         * @param handler
         * @return         true:也许放行。false:不允许放行
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle..........");
            String param = request.getParameter("param");
            if("yes".equals(param)){
                return true;
            }else {
                request.getRequestDispatcher("/error.jsp").forward(request, response);
                return false;
            }
        }
    
        /**
        * 在执行controller方法之后,
        * 执行jsp页面之前执行该方法,可以向作用域中放入数据,影响jsp展示效果,(可以在执行jsp之前做渲染)
        */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            modelAndView.addObject("name","NanMu");
            System.out.println("postHandle..........");
        }
    
        /**
        * 在jsp页面渲染完成之后执行(全部SpringMVC流程完结之后)
        * 主要用于记录日志,资源释放
        */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            //打印
            System.out.println("afterCompletion..........");
        }
    }
    
    1. 在SpringMVC的配置文件中配置
     <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
        	<!--/** 代表对所有路径拦截-->
            <mvc:mapping path="/**"/>
            <bean class="com.lfs.interceptor.MyInterceptor1"/>
        </mvc:interceptor>
    	<mvc:interceptor>
        	<!--/test/** 代表对第一个资源节点是test的路径拦截-->
            <mvc:mapping path="/test/**"/>
            <bean class="com.lfs.interceptor.MyInterceptor1"/>
        </mvc:interceptor>
    </mvc:interceptors>
    

拦截器拦截器的执行顺序

拦截器中的方法执行顺序是:preHandler-------目标资源-------postHandle-------afterCompletion

存在多个拦截器时,拦截器的执行顺序

所有拦截器都通过(都不拦截)执行顺序:
在这里插入图片描述
如果拦截器A拦截(拦截器.ApreHandle返回false)那么之后拦截器也不执行,直接返回
在这里插入图片描述

如果拦截器3拦截,那么也不执行controller方法
在这里插入图片描述
总结:

  • 当拦截器的preHandle方法返回true则会执行目标资源(Controller),如果返回false则不执行
  • 当拦截器的preHandle方法返回true则会执行postHandle,如果返回false则不执行
  • 多个拦截器情况下,配置在前的先执行,配置在后的后执行

其他

SpringMvc和AJAX相互调用

通过Jackson框架把Java里面的对象直接转化成Js可以识别的Json对象。

(1)加入Jackson.jar

(2)在配置文件中配置json的映射

(3)在接受Ajax方法里面可以直接返回ObjectList等,但方法前面要加上@ResponseBody注解

请求中文乱码

POST请求乱码

  1. 在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
     
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

GET请求乱码

  1. 修改tomcat配置文件添加编码与工程编码一致
    <ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
    
  2. 对参数进行重新编码
    ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
    String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我好帅啊~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值