springMVC

springMVC

MVC简介

  1. MVC是一种架构模式

    程序分工,分工合作,既相互独立,又协同工作,分为三次,模型层,视图层,控制层.

  2. MVC是一种思考方式

    View : 视图层 ,为用户提供UI,终点关注数据的呈现,为用户提供界面.

    Model : 模型层,业务数据的信息标识,关注支撑业务的信息构成, 通常是多个业务实体的组合

    Controller : 控制层 , 调用业务逻辑产生合适的数据(Model) , 传递数据给视图用于呈现.

    MVC设计模式在B/S下的应用

    mark

    分析:

    ① : 浏览器发送请求到控制器;

    ② : 控制器不能处理请求必须给模型层来处理接着去访问数据库

    ③ : 模型层将处理好的结果返回给控制层

    ④ : 控制层将逻辑视图响应给浏览器.

    MVC的本质 : MVC的核心思想是业务数据抽取,同物业数据呈现分离;有利于程序简化,方便编程.

前端控制器模式

 前端控制器模式(Front Controller Pattern) 是用来提供一个集中的请求处理机制 , 所有的请求都将由一个单一的处理程序处理,该程序可以做认证/授权/记录日志,活着跟踪请求,然后吧请求传给响应的处理程序.

  • 前端控制器(Front Controller) 处理应用程序所有类型请求的单个处理程序, 应用程序可以是基于web的应用程序,也可以是基于桌面的应用程序.
  • 调度器(Dispatcher) 前端控制器使用一个调度器对象来调度请求到的相应的具体处理程序
  • 视图(View) 视图是为请求而创建的对象

前端控制器的作用

  • 指前端控制器将我们的请求分发给控制器去生成业务数据
  • 将生成的业务数据分发给恰当的视图模型来显示到界面上.
  • mark

SpringMVC的基本概念

mark

springMVC工作原理说明

mark

工作原理

  1. 用户发送请求到springMVC框架提供的DispatcherServlet 这个前端控制器(了解Struts2的朋友也都知道其实Struts2也有一个前端控制器web.xml中的Filter标签就是)
  2. 前端控制器会去找处理器去映射器(HandlerMapping),处理器映射器根据请求URL找到具体的处理器,生成处理器对象及处理拦截器(如果有则生成)一并返回给DispatcherServlet.
  3. 根据处理器映射器返回的处理器,DispatcherServlet会找"合适"的处理器适配器(HandlerAdapter)
  4. 处理器适配器HandlerAdapter会去执行处理器(Handler开发的时候会被叫成controller 也叫前端控制器在struts2中action也是一个后端控制器)执行之前会有转换器,数据绑定,校验器等等完成上面这些才回去执行Handler
  5. 后端控制器Handler执行完成后返回一个ModelAndView对象
  6. 处理器适配器HandlerAdapter会将这个ModelAndView返回给前端控制器DispatcherServlet.前端控制器会将ModelAndView对象交给视图解析器ViewResolver
  7. 视图解析器ViewResolver解析ModelAndView对象后返回逻辑视图.
  8. 前端控制器DispatcherServlet对逻辑视图进行渲染(填充数据)之后返回真正的物理View并响应给浏览器.

组件说明

  1. DispatcherServlet : 前端控制器

    用户请求到达前端控制器,相当于MVC中的C,而DispatcherServlet是整个流程的核心,它来调用其他组件来处理用户请求,前端控制器的存在降低了其他组件之间的耦合度.

  2. HandlerMapping : 处理器映射器

    它的作用好比去看电影,要拿着电影票根据电影票上面的座位号找到座位上的座位,其中座位就是Handler , 电影票以及上面的座位号就是URL.

    HandlerMapping 负责根据用户请求找到Handler即处理器 , springMVC提供了不同的映射器实现了不同的映射方式,例如 : 配置文件方式, 实现接口方式 ,注解方式等.

  3. Handler : 处理器

    Handler 是后端控制器, 在前端控制器的控制下后端控制器对具体的用户请求进行处理,Handler涉及到具体的用户请求,所以一般情况下需要程序员根据自己的业务开发.

  4. HandlerAdapter : 处理器适配器

    通过HandlerAdapter对处理器进行执行 , 这是适配器模式的应用 , 通过适配器可以对更多类型的处理器进行执行.

    播放的电影是3D的你看不清楚,电影院跟你说你要想看清电影就必须佩戴3D眼镜,也就是说Handler满足一定的要求猜可以被执行.

  5. ViewResolver : 视图解析器

    ViewResolver 负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图,即具体的页面地址,再生成view视图对象,最后对view进行渲染处理结果通过页面展示给用户.

mark

SpringMVC 的配置

  1. 前端控制器需要再web.xml中进行配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
             http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
             id="WebApp_ID" version="2.5">
    
        <!-- 配置前端控制器 -->
        <servlet>
            <servlet-name>web-dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--加载前端控制器配置文件 上下文配置位置-->
            <init-param>
                <!-- 备注:
                    contextConfigLocation:指定 SpringMVC 配置的加载位置,如果不指定则默认加载
                    WEB-INF/[DispatcherServlet 的 Servlet 名字]-servlet.xml
                 -->
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/spring-*.xml</param-value>
            </init-param>
            <!-- 表示随WEB服务器启动 -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>web-dispatcher</servlet-name>
            <!-- 备注:可以拦截三种请求
                第一种:拦截固定后缀的url,比如设置为 *.do、*.action, 例如:/user/add.action 此方法最简单,不会导致静态资源(jpg,js,css)被拦截
                第二种:拦截所有,设置为/,例如:/user/add  /user/add.action此方法可以实现REST风格的url,
                很多互联网类型的应用使用这种方式.但是此方法会导致静态文件(jpg,js,css)被拦截后不能正常显示.需要特殊处理
                第三种:拦截所有,设置为/*,此设置方法错误,因为请求到Action,当action转到jsp时再次被拦截,提示不能根据jsp路径mapping成功
            -->
            <!-- 默认匹配所有的请求 -->
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
    
  2. 在spring/spring-web.xml配置视图解析器

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
        <!-- 配置视图解析器 -->
        <!-- InternalResourceViewResolver:支持JSP视图解析 -->
        <!-- viewClass:JstlView 表示JSP模板页面需要使用JSTL标签库,所以classpath中必须包含jstl的相关jar包; -->
        <!-- prefix 和 suffix:查找视图页面的前缀和后缀,最终视图的址为: -->
        <!-- 前缀+逻辑视图名+后缀,逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为hello,-->
        <!-- 则最终返回的jsp视图地址 "WEB-INF/jsp/hello.jsp" -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!-- 决定视图类型,如果添加了jstl支持(即有jstl.jar),那么默认就是解析为jstl视图 -->
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
            <!-- 视图前缀 -->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!-- 视图后缀 -->
            <property name="suffix" value=".jsp"/>
        </bean>
    </beans>
    
  3. 在spring/spring-web.xml的注解模式

    <!-- 自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter, -->
    <!-- 可用在xml配置文件中使用<mvc:annotation-driven>替代注解处理器和适配器的配置。 -->
    <mvc:annotation-driven/>
    
  4. 在spring/spring-web.xml 配置扫描web相关的bean

    <!-- 组件扫描器:可以扫描 @Controller、@Service、@Repository 等等 -->
    <context:component-scan base-package="com.controller" />
    

springMVC中的注解

@Controller注解

用于标识这个类是一个后端控制器(类似于struts2种的action), 主要作用就是接收页面的参数,转发页面

@controller源码:

@Target({ElementType.TYPE}) // 表明只能定义在类上面
@Retention(RetentionPolicy.RUNTIME) //保留策略是RUNTIME,在JVM加载类时,会把注解加载到JVM内存中(它是唯一可以用反射来读取注解的策略)
@Documented //@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。
@Component //spring框架规定当一个类不好归类(service、dao、controller)的时候可以使用这个注解,由此可见即便好归类内部还是使用的@Component注解
public @interface Controller {
    /**
     * The value may indicate a suggestion for a logical component name,
     * to be turned into a Spring bean in case of an autodetected component.
     * @return the suggested component name, if any
     */
    String value() default "";
}

@RequestMapping

这个注解的作用是跟@Controller不一样,这个注解可以定义在类上,也可以定义在方法上.

/**
* 1.@RequestMapping:除了修饰方法,还可以修饰类
* 2.类定义处:提供初步的请求信息映射.相对于WEB应用的根目录(窄化请求)
* 3.方法处:提供进一步的细分映射信息。相对于类定义处的URL。
*      若类定义处为标注@RequestMapping,则方法出的URL相对于WEB应用的根目录
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String[] value() default {};
    RequestMethod[] method() default {}; //限制请求方式
    String[] params() default {}; //要求请求的URL包含指定的参数
}

代码实例

@Controller
@RequestMapping("/demo")
public class IndexController {
    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public String index(Model model, HttpServletRequest request) {
        // 在游览器访问 http://localhost:8080/demo/test 将进入这里
        model.addAttribute("originURL", "");
        model.addAttribute("controllerName", "index");
        return "index";
    }
}

@RequestMapping还支持Ant方格的请求

?:匹配文件中的一个字符
*:匹配文件中任意字符
**:**匹配多层路径

/user/*/createUser : 匹配 -/user/aa/createUser 或者 -/user/aa/createUser
/user/**/createUser : 匹配 -/user/aa/createUser 或者 -/user/createUser 或者 -/user/aa/cc/createUser
/user/createUser?? : 匹配 -/user/aa/createUseraa

@PathVariable

这个注解支持现在当下较为流行的Restful风格的URL.先说这个注解的作用,支持将URL中的占位符参数绑定到目标方法上的参数上,该功能也是springMVC实现Restful风格URL的重要措施.

代码实现

// http://localhost:8080/demo/sss
@RequestMapping(value = "/{slug:.+}", method = RequestMethod.GET)
    public String index2(@PathVariable("slug") String slug, Model model) {
    LOG.info("DemoController index2 slug  " + slug);
    // common
    model.addAttribute("originURL", "demo/");
    model.addAttribute("controllerName", "demo");
    model.addAttribute("controllerMethod", "index2");
    model.addAttribute("slug", slug);
    return "demo";
}

//slug = sss

我们熟悉的请求应该是POST和GET请求,这两个请求也是最常用的,而实际上http1.1请求还是put , delete 等 8种来表名请求的动作

在springMVC中要实现put和delete请求需要再web.xml额外配置一个过滤器,这个过滤器的作用就是吧post请求变为put和delete请求.

@RequestParam

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    String value() default "";//值即为请求参数的参数名
    boolean required() default true;//该参数是否是必须。默认值为true
    String defaultValue() default ValueConstants.DEFAULT_NONE;//请求参数的默认值
}
// http://localhost:8080/demo/para?slug=google
@RequestMapping(value = "/para", method = RequestMethod.GET)
public String index3(@RequestParam(value = "slug", defaultValue = "") String slug, Model model) {
    model.addAttribute("originURL", "demo/");
    model.addAttribute("controllerName", "demo");
    model.addAttribute("controllerMethod", "index3");
    model.addAttribute("slug", slug);
    return "demo";
}
slug = google

另外还有一点要提示一下,参数没有加这个注解也能映射成功,这是应为 SpringMVC 框架支持请求参数和目标方法参数一致的时候可以省略这个注解。

@ResponseBody

/**
 * Annotation that indicates a method return value should be bound to the web
 * response body. Supported for annotated handler methods in Servlet environments.
 * 
 * 这个注解指明一个方法的返回值应该绑定在 web response body 中,在 Servlet 环境中支持注解处理方法
 * 
 * <p>As of version 4.0 this annotation can also be added on the type level in
 * which case it is inherited and does not need to be added on the method level.
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {
}

代码

// http://localhost:8080/demo/json
@RequestMapping(value = "/json", method = RequestMethod.POST)
public @ResponseBody Domain index7(HttpServletRequest request, Model model) {

    LOG.info("DemoController demo index7");
    model.addAttribute("originURL", "demo/");
    model.addAttribute("controllerName", "demo");
    model.addAttribute("controllerMethod", "index7");

    Domain domain = new Domain();
    domain.setDomain("gggoogle.com");
    domain.setId(100);
    return domain;
}

/* response body
{
    "id": 100,
    "domain": "gggoogle.com"
}
*/
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343