数据层框架: MyBatis
表现层框架: Servlet->SpringMVC (即SpringMVC属于一种表现层框架)
简介: SpringMVC是一种基于Java实现MVC模型的轻量级Web框架
优点:
pom.xml文件中添加一些依赖,这些依赖版本之间是相互联系的,如果配错或配太低都不行
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>springmvc_01_testartifactId>
<packaging>warpackaging>
<version>1.0-SNAPSHOTversion>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.13.RELEASEversion>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.1.0version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.apache.tomcatgroupId>
<artifactId>tomcat-apiartifactId>
<version>10.1.7version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.1version>
<configuration>
<port>80port>
<path>/path>
configuration>
plugin>
plugins>
build>
project>
控制器类来指定对应的访问网址什么的,@Controller
标明这是一个bean,@RequestMapping
指定访问路径,@ResponseBody
指定返回不做任何解析和处理
package com.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("User save...");
return "{'module': 'springmvc'}";
}
}
类似于Spring的配置,通过@Configuration
指定为配置类,通过@ComponentScan
来指定扫描的控制器范围
package com.demo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.demo.controller")
public class SpringMvcConfig {
}
这里相当于是一些固定的写法
package com.demo.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
// 加载SpringMVC容器配置
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
// 设置哪些请求归属SpringMVC处理
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
// 加载Spring配置
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
配置Run Configurations
然后启动,在浏览器里输入http://localhost/save
可看到结果:
@Controller
:类注解,放在SpringMVC控制器上方,作用是设定SpringMVC的核心控制器bean
@RequestMapping
:方法注解,放在SpringMVC控制器方法定义上方,作用是设置当前控制器方法的请求路径
@ResponseBody
:方法注解, 放在SpringMVC控制器方法定义上方,作用是设置当前控制器方法相应内容为当前返回值,无需解析
ServletContainerInitConfig
类,初始化Web容器createServletApplicationContext
方法,创建了WebApplicationContext
对象SpringMVCConfig
@ComponentScan
对应的beanUserController
(也就是加载扫描包下注释了@Controller
的那些类),每个@RequestMapping
的名称都对应一个具体的方法(注意:如图中/save->save()
的映射实际上并不是放在每一个bean中管理的,而是由SpringMVC放在统一的地方进行管理的)getServletMappings
方法,定义所有的请求都通过SpringMVClocalhost/save
/save
/save
匹配执行对应的方法save()
save()
@ResponseBody
,直接将save()
方法的返回值作为响应请求体返回给请求方SpringMVC相关的bean是表现层的bean:
com.xx.controller
包内Spring控制的bean:
com.xx
,排除掉controller
包内的beanservice, dao
包等指定大的扫描类型,在其中通过excludeFilters
排除掉一些东西,具体写法如下,我们需要再excludeFilters
里边指定清楚过滤的规则
package com.demo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
@Configuration
@ComponentScan(value = "com.demo",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}
执行一下测试,看能否再拿到注释了@Controller
的UserController
类(注意,在测试之前要注释掉SpringMvcConfig上的@Configuration
):
package com.demo;
import com.demo.config.SpringConfig;
import com.demo.controller.UserController;
import com.demo.domain.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
UserController userController = ctx.getBean(UserController.class);
System.out.println(userController);
}
}
执行测试代码会报错:
如果取消掉这个过滤规则,再执行测试代码会发现不会报错,而是会打印拿到的实例信息。通过测试说明使用excludeFilters
这种方法是可以过滤包的
解释一下为什么要注释掉SpringMvcConfig上的@Configuration
:因为我们在SpringConfig
中扫描了com.demo
下的所有包,在SpringMvcConfig
上我们使用@Configuration
注解了它是一个配置类,那么这个配置就会被扫描,它所包括的所有bean也会被加载进来,如果将SpringMvcConfig
放到com.demo
下而不注释也可以解决这个问题(老师在视频里是这么讲的,但是我自己试了一下好像把SpringMvcConfig
放到com.demo
下,不注释也会被加载进来,不知道是不是我的问题)
我们使用mybatis
技术来进行开发,这里的com.demo.dao
是可以不写的,因为mybatis
通过自动代理的技术可以扫到com.demo.dao
下的bean(在Mybatis的MapperScannerConfigurer
中有设置msc.setPackage("...")
)
但是假如我们使用JDBC的技术来进行开发,我们就必须扫描com.demo.dao
下的包,否则我们就没有数据层的bean,Spring下JDBC的开发可以看一下这篇文章:Spring jdbc数据库管理,所以对于com.demo.dao
的扫描还是建议写,这样通用性比较好,如果不写的话通用性就会比较差
package com.demo.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan({"com.demo.service", "com.demo.dao"})
public class SpringConfig {
}
修改ServletContainersInitConfig
类中的内容,加上加载Spring配置的内容:
package com.demo.config;
import com.demo.controller.SpringConfig;
import com.demo.controller.SpringMvcConfig;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer {
// 加载SpringMVC容器配置
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
// 设置哪些请求归属SpringMVC处理
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
// 加载Spring配置
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
}
}
在Servlet容器中加载SpringMVC和Spring配置还有一个简化的类及写法,以下是以上的简化开发:
package com.demo.config;
import com.demo.controller.SpringConfig;
import com.demo.controller.SpringMvcConfig;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
public class ServletContainerInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}