MVC(Model-View-Controller)模式。
请求在Spring MVC 的一个过程
- 来自客户的请求,带有用户所要请求的内容信息。
- 第一站到达,DispatcherServlet(前端控制器),它去 查询处理器映射(handler mapping)。
- 通过 handler mapping 来确定 对应的控制器。处理器映射会根据请求所携带的URL信息来进行决策。把结果反馈给DispatcherServlet。
- 选择了适合的控制器(Controller),DispatcherServlet会将请求发送给选中的控制器,把所有携带的信息交给控制器 等待其处理结果。
- 控制器完成逻辑处理后,通常会产生一些信息,这些信息被称为
模型
。 - 控制器所作的最后一件事就是将模型数据打包,并且标示出用于渲染输出的视图名。将将模型和视图名发送回DispacherServlet。
- dispatcherServlet 会使用 视图解析器(View resolver),把视图名与真正的视图进行匹配。
- 此时 dispatcherServlet 已经知道 视图 和 模型,最后一个站是 视图实现。
- 通过响应对象传递给 客户端。
搭建 Spring MVC
配置 DispatcherServlet
Sevlet 配置方式:一种是使用 web.xml。另一种是配置 DispatcherServlet。
public class SpittrWebAppInit extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
// 指定 配置类
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
// 将 dispatcher Servlet 映射到 “/”
return new String[]{"/"};
}
}
扩展 AbstractAnnotationConfigDispatcherServletInitializer 的任意类都会自动配置 DispatcherServlet 和 Spring Application Context,Spring 的应用上下文会位于应用程序的Servlet上下文中。
了解 AbstractAnnotationConfigDispatcherServletInitializer 类:
-
getServletMappings()
,将一个或多个路径映射到 DispatcherServlet 上
DispatcherServlet 和 Servlet监听器的关系。
- DispatcherServlet 启动时,它会创建 Spring ApplicationContext ,并 加载配置文件或配置类中所声明的bean。
- getServletConfigClasses()方法中,我们要求 DispatcherServlet 加载应用上下文时,使用定义在WebConfig配置类中的bean。
- 在 web 应用中,还有另一个 应用上下文是由
ContextLoaderListener
创建的。 - DispatcherServlet 加载包含 Web组件的bean,如控制器、视图解析器以及处理器映射等
- ContextLoaderListener 要加载应用中的其他 bean,通常是驱动应用后端的中间层和数据层组件。
-
getServletConfigClasses()
方法返回配置类 会用来定义DispatcherSevlet 应用上下文中的 bean。 -
getRootConfigClasses()
方法返回的配置类 会用来配置 ContextLoaderListener创建的应用上下文中的bean。 - Tomcat 要求 7.0 或 更高的版本。
启用 Spring MVC
@Configuration
@EnableWebMvc
@ComponentScan("beans")
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver =
new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
-
@EnableWebMvc
启用 Spring MVC。 -
InternalResourceViewResolver
负责查找 JSP 文件,并在视图名称 上加一个特定的前缀和后缀。 -
DefaultServletHandlerConfigurer
的enable()
方法,可以让 DispatcherServlet 将对 静态资源的请求转发到Servlet容器中默认的Servlet 上,而不是使用 DispatcherServlet 本身来处理此类请求。
@Configuration
@ComponentScan(basePackages = {"com.test"},excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class)
})
public class RootConfig {
}
编写控制器
@Controller
@RequestMapping(value = "/")
public class HelloController {
@RequestMapping(method = RequestMethod.GET)
public String showView(){
return "welcome";
}
@RequestMapping(value = "/hello", method = RequestMethod.POST)
public ModelAndView handleRequest(HttpServletRequest request) throws UnsupportedEncodingException {
request.setCharacterEncoding("utf-8");
String name = request.getParameter("name");
ModelAndView view = new ModelAndView("result","name",name);
return view;
}
}
@RequestMapping
注解,声明了它们所要处理的请求。
- 在 类级别上时,会应用到类级别的所有处理方法上。
-
value
属性指明这个方法所要处理的路径。 -
method
属性细化了它所处理的 Http 方法。
传递模型数据 到视图中
@RequestMapping(method = RequestMethod.GET)
public String showView(Model model){
model.addAttribute("title");
return "welcome";
}
Model
实际是一个 map ,它会传递给视图。
- 当调用 addAttribute() 方法并且不指定 key 的时候,那么 key 会根据值对象 进行推断确定。
- 可以使用 Map 替换
@RequestMapping(value = "/test", method = RequestMethod.GET)
public List<String> show(){
return Repository.findList();
}
- 处理方法 返回 是对象 或 集合时,这个值会放到模型中,key 根据类型 推断。
- 逻辑视图的名称 将会根据请求路径推断得出。
接受请求的输入
多种方式 将客户端数据传送给 控制器的处理方法:
- 查询参数
- 表单参数
- 路径变量
处理查询参数
为了处理这样的请求:/spittles?max=23&count=3
;
@RequestMapping(value = "/test", method = RequestMethod.GET)
public List<String> show(@RequestParam("max") int max,@RequestParam("count") int count){
}
@RequestParam()
把参数中对应值 赋给 对应的 变量
-
value
属性 设置 参数名,请求中的参数名。 -
defaultValue
属性:在请求中不存在 指定参数时 ,使用默认值。
通过路径参数接受输入
为了处理像:/results/123
的请求。
@RequestMapping(value = "/result/{id}", method = RequestMethod.GET)
public List<String> show(@PathVariable("id") int id){
return null;
}
-
@PathVariable()
注解,表明 把占位符id 对应的值,传递给 变量 id。
处理表单
为了处理:<form>
里面的 内容。
- 处理放的参数 可以是 封装的对象。
- 也可以在 HttpServletRequest 中获得
@RequestMapping(value = "/hello", method = RequestMethod.POST)
public String handleRequest(HttpServletRequest request) throws UnsupportedEncodingException {
String title = request.getParameter("title");// 通过 每个标签 对应 name 获取。
return "redirect:/result/123";
}
- 返回字符串中
- 前缀是:
redirect:
将其 解析为 重定向 规则。 - 前缀是:
forward:
请求将会前往 指定的URL路径,而不再是重定向。 - 只是返回字符串 ,表示 视图名。