JSP:负责生成动态网页
Servlet:负责流程控制
JavaBean:负责业务逻辑处理
模型(Model):负责封装应用的状态,并实现应用的功能。通常分为数据模型和业务逻辑模型,数据模型用来存放业务数据,比如订单信息、用户信息等;而业务逻辑模型包含应用的业务操作,比如订单的添加或者修改等。通常由java开发人员编写程序完成,代码量最多
视图(View):视图通过控制器从模型获得要展示的数据,然后用自己的方式展现给用户,相当于提供界面来与用户进行人机交互。通常有前端和java开发人员完成,代码量较多。
控制器(Controller):用来控制应用程序的流程和处理用户所发出的请求。当控制器接收到用户的请求后,会将用户的数据和模型的更新相映射,也就是调用模型来实现用户请求的功能;然后控制器会选择用于响应的视图,把模型更新后的数据展示给用户。起到总调度的作用,Controller通常由框架实现,使用时基本不需要编写代码
优点:
多视图共享一个模型,大大提高代码的可重用性
MVC三个模块相互独立,松耦合架构
控制器提高了应用程序的灵活性和可配置性
有利于软件工程化管理
缺点:
原理复杂
增加了系统结构和实现的复杂性
视图对模型数据的低效率访问
提示:这里对文章进行总结:
大部分java应用都是web应用,展现层是web应用最为重要的部分。Spring为展现层提供了一个优秀的web层框架——SpringMVC。和众多其他web框架一样,它基于MVC的设计理念,此外,它采用了松散耦合可插拔组件结构,比其他MVC框架更具扩展性和灵活性。
SpringMVC通过一套MVC注解,让POJO成为处理请求的控制器,无需实现任何接口,同时,SpringMVC还支持REST风格的URL请求。此外,SpringMVC在数据绑定、视图解析、本地化处理以及静态资源处理上都有许多不俗的表现。它在框架设计、扩展性、灵活性等方面全面超越了Struts、WebWork等MVC框架,从原来的追赶者一跃成为MVC的领跑者。
SpringMVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet是SpringMVC框
架的总导演、总策划,它负责截获请求并将其分派给相应的处理器处理Spring MVC是Spring框架中用于web应用开发的一个模块,是一个基于MVC设计模式的优秀WEB开发框架,通过控制器(Controller)来建立模型和视图的数据交互,是结构最清晰的MVC Model2实现。
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!--事务依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!--整合需要的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--数据源依赖-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<!--面向切面的依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!--spring测试依赖-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<!--spring依赖-->
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
</dependencies>
springmvc默认读取resources/{servlet-name}-servlet.xml这个配置文件,因为我们在web.xml中的servlet-name配置的是springmvc,所以在resources目录下创建springmvc-servlet.xml文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
beans>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
web-app>
package com.kgc.springmvc.demo01.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class IndexController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
System.out.println("hello,springMVC");
return new ModelAndView("index");
}
}
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<bean name="/hello.do" class="com.kgc.springmvc.demo01.controller.IndexController" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/">property>
<property name="suffix" value=".jsp">property>
bean>
部署并启动项目,访问:http://localhost/hello.do
通过查看DispatcherServlet源码可以看到,DispatcherServlet会读取DispatcherServlet.properties文件,在此文件中已经配置了映射处理器和适配器,因此可以省略配置。
package com.kgc.springmvc.demo02.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping("hello.do")
public String hello(){
return "index";
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven/>
<context:component-scan base-package="com.kgc.springmvc.demo02.controller">context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/">property>
<property name="suffix" value=".jsp">property>
bean>
beans>
复制log4j.properties到resources目录下
启动并访问:http://localhost/hello.do
由日志可以看出,springmvc核心Servlet并没有在容器启动时加载,而是在第一次访问时加载,因此可能会影响第一次的访问速度。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc-servlet.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
web-app>
@RequestMapping(value=”xxx”)
在springmvc众多Controller以及每个Controller的众多方法中,请求时如何映射到具体的处理方法上,它可以定义在方法上,也可以定义在类上
请求映射的规则:
类上的@RequestMapping的value+方法上的@RequestMapping的value,如果value不以“/”开头,springmvc会自动加上
类上的@RequestMapping可省略,这时请求路径就是方法上的@RequestMapping的value
路径不可重复
@RequestMapping("index")
@Controller
public class IndexController {
@RequestMapping("hello.do")
public String hello(){
return "index";
}
}
测试:
http://localhost/index/hello.do
?:通配一个字符
*:通配0个或者多个字符 任意多个字符
**:通配0个或者多个路径
package com.kgc.springmvc.demo02.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@RequestMapping("index")
@Controller
public class IndexController {
@RequestMapping("hello.do")
public String hello(){
return "index";
}
@RequestMapping("a?/show2.do")
public ModelAndView test2(){
ModelAndView mv = new ModelAndView();
mv.setViewName("index");
mv.addObject("msg", "ant风格的映射:?");
return mv;
}
@RequestMapping("b*/show3.do")
public ModelAndView test3(){
ModelAndView mv = new ModelAndView();
mv.setViewName("index");
mv.addObject("msg", "ant风格的映射:*");
return mv;
}
@RequestMapping("**/show4.do")
public ModelAndView test4(){
ModelAndView mv = new ModelAndView();
mv.setViewName("index");
mv.addObject("msg", "ant风格的映射:**");
return mv;
}
}
测试:
http://localhost/index/aa/show2.do
http://localhost/index/bbb/show3.do
http://localhost/index/aa/bb/cc/dd/show4.do
思考:
如果把test3方法的请求路径,改为“*/show3”, test4方法的请求路径,改为“**/show3”,
访问路径:http://localhost/index/bbb//show3.do会进入test3方法还是test4方法呢
访问路径:http://localhost/index/bbb/show3.do会进入test3方法还是test4方法呢?
@RequestMapping(value=“/user/{userId}/{name} ")
请求URL:http://localhost:8080/user/1001/zhangsan.do
这种方式虽然和通配符“*”类似,却比通配符更加强大,占位符除了可以起到通配的作用,最精要的地方是在于它还可以传递参数。
比如:通过@PathVariable(“userId”) Long id, @PathVariable(“name”)String name获取对应的参数。
注意:@PathVariable(“key”)中的key必须和对应的占位符中的参数名一致,而方法形参的参数名可任意取
如果传递的参数类型和接受参数的形参类型不一致,则会自动转换,如果转换出错(例如:id传了abc字符串,方法形参使用Long来接受参数),则会报400错误(参数列表错误)
package com.kgc.springmvc.demo02.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@RequestMapping("index")
@Controller
public class IndexController {
@RequestMapping("show5/{name}/{id}.do")
public ModelAndView test5(@PathVariable("name")String name, @PathVariable("id")Long id){
ModelAndView mv = new ModelAndView();
mv.setViewName("index");
mv.addObject("msg", "rest风格的映射:name=" + name + ",id=" + id);
System.out.println("name:"+name+",id:"+id);
return mv;
}
}
测试:
http://localhost/index/show5/aaa/1.do