整合Spring MVC

目录

SpringMVC基本概念

SpringMVC执⾏流程:如图

具体流程

一、Spring MVC 自动配置介绍

1.自动配置介绍

2.Spring Boot整合Spring MVC 的自动化配置功能特性

二、Spring MVC 功能拓展实现

1.搭建步骤

1、项目基础环境搭建(示例):

​编辑

2.功能拓展实现

3.效果测试 

三.简单案例


SpringMVC基本概念


SpringMVC可以理解为对Servlet封装的MVC框架,当前,Java Web技术底层由两种实现⽅式︓⼀种基于Servlet,⼀种基于Netty,前者由Spring MVC框架等,后者则有WebFlux。
Spring的模型-视图-控制器(MVC)框架是围绕⼀个DispatcherServlet来设计的,这个Servlet会把请求分发给各个处理器,并⽀持可配置的处理器映射、视图渲染、本地化、时区与主题渲染等,甚⾄还能⽀持⽂件上传。

提示:以下是本篇文章正文内容,下面案例可供参考


SpringMVC执⾏流程:如图

作为Web MVC的实现,职责对应关系为︓DispatcherServlet -> 前端控件器, HandlerMapping与ViewResolver-> 应⽤控制器, Handler -> 页⾯控制器。

具体流程

1. ⽤户请求 -> DispatcherServlet DispatcherServlet:本质上是⼀个Servlet,相当于⼀个中转站,所有的访问都会⾛到这个Servlet中,再根据配置进⾏中转到相应的Handler中进⾏处理,获取到数据和视图后,在使⽤相应视图做出响应。
2. DispatcherServlet -> HandlerMapping,HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含⼀个Handler处理器(页⾯控制器)对象、多个HandlerInterceptor拦截器)对象HandlerMapping︓本质上就是⼀段映射关系,将访问路径和对应的Handler存储为映射关系,在需要时供前端控制器查阅。
3. DispatcherServlet -> HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从⽽⽀持多种类型的处理器 HandlerAdapter︓本质上是⼀个适配器,可以根据要求找到对应的Handler来运⾏。前端控制器通过处理器映射器找到对应的Handler信息之后,将请求响应和对应的Handler信息交由处理器适配器处理,处理器适配器找到真正handler执⾏后,将结果即model和view返回给前端控制器。
4. DispatcherServlet -> 处理器功能处理⽅法的调⽤,HandlerAdapter会根据适配的结果调⽤真正的处理器的功能处理⽅法,完成功能处理,并返回⼀个ModelAndView对象(包含模型数据、逻辑视图名)。
5. DispatcherServlet -> ViewResolver,ViewResolver将把ModelAndView对象的逻辑视图名解析为具体的View ViewResolver︓本质上也是⼀种映射关系,可以将视图名称映射到真正的视图地址。前端控制器调⽤处理器适配完成后得到model和view,将view信息传给视图解析器得到真正的view。
6. DispatcherServlet -> View渲染,View会根据传进来的Model模型数据进⾏渲染 View︓本质上就是将handler处理器中返回的model数据嵌⼊到视图解析器解析后得到的页⾯中,向客户端做出响应。
7. DispatcherServlet -> ⽤户

一、Spring MVC 自动配置介绍

1.自动配置介绍

在Spring Boot项目中,一旦引入了Web依赖启动器spring-boot-starter-web,那么Spring Boot整合Spring MVC框架默认实现的一些XxxAutoConfiguration自动配置类就会自动生效,几乎可以在无任何额外配置的情况下进行Web开发。

2.Spring Boot整合Spring MVC 的自动化配置功能特性

  1. 内置了两个视图解析器:ContentNegotiatingViewResolver和BeanNameViewResolver
  2. 支持静态资源以及WebJars;
  3. 自动注册了转换器和格式化器;
  4. 支持Http消息转换器;
  5. 自动注册了消息代码解析器;
  6. 支持静态项目首页index.html;
  7. 支持定制应用图标favicon.ico;
  8. 自动初始化Web数据绑定器ConfigurableWebBindingInitializer。

二、Spring MVC 功能拓展实现

1.搭建步骤

步骤如下:

2、功能拓展实现

3、效果测试

1、项目基础环境搭建(示例):

使用Spring Initializr方式创建Spring Boot项目,并在Dependencies依赖选择中选择Web依赖启动器和Thymeleaf依赖启动器:

项目初始化结构图如下: 

2.功能拓展实现

1、注册视图管理器,创建一个实现WebMvcConfigurer接口的配置类MyMVCconfig,用于对MVC框架功能扩展。

@Configuration
public class MyMVCconfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/toLoginPage").setViewName("login");
        registry.addViewController("/login.html").setViewName("login");
    }
}

2.项目启动成功后,在浏览器上分别访问http://localhost:8080/toLoginPagehttp://localhost:8080/login.html 。(如图:

 

3、注册自定义拦截器MyInterceptor,实现HandlerInterceptor 接口,在该类中编写如下方法 

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
    String uri = request.getRequestURI();
    Object loginUser = request.getSession().getAttribute("loginUser");
    if (uri.startsWith("/admin") && null == loginUser) {
        response.sendRedirect("/toLoginPage");
        return false;
    }
    return true;}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
               Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    request.setAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR));
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse
        response, Object handler, @Nullable Exception ex) throws Exception {
}

4、在自定义配置类MyMVCconfig中,重写addInterceptors()方法注册自定义的拦截器 

@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
	registry.addInterceptor(myInterceptor)
	             .addPathPatterns("/**")
                             .excludePathPatterns("/login.html");
}

3.效果测试 

重启项目,启动成功后,在浏览器上访问http://localhost:8080/admin.

三.简单案例

页⾯跳转功能按照之前的例⼦创建项⽬,引⼊依赖(spring web, thymeleaf),在模板⾥创建test1.html,test2.html,之后在config⽂件夹⾥创建MyMvcConfig类

MyMvcConfig类: 


@Configuration
publicclassMyMvcConfigimplementsWebMvcConfigurer{
@Override
publicvoidaddViewControllers(ViewControllerRegistry registry){
        registry.addViewController("/test1").setViewName("test1");
        registry.addViewController("/test111").setViewName("test1");
        registry.addViewController("/test2").setViewName("test2");
    }
}

 拦截器

  1. preHandle:控制器⽅法执⾏之前执⾏preHandle(),其boolean类型的返回值表⽰是否拦截或放⾏,返回true为放⾏,即调⽤控制器⽅法︔返回false表⽰拦截,即不调⽤控制器⽅法;应⽤场景:如⾝份认证,⾝份授权。
  2. postHandle:控制器⽅法执⾏之后执⾏postHandle(),返回ModelAndView之前执⾏应⽤场景:从modelAndView出发,将公⽤模型数据(如菜单导航)在这⾥传到视图,也可以在这⾥统⼀制定视图。
  3. afterComplation:处理完视图和模型数据,渲染视图完毕之后执⾏afterComplatio() 应⽤场景:统⼀⽇志处理,统⼀异常处理 preHandle-->控制器⽅法controller->>postHandle-->模型视图⽅法-->afterComplation 同上述例⼦,在config⽂件夹⾥创建MyMvcConfig类MyInterceptor类

MyMvcConfig类 :

@Configuration
publicclassMyInterceptorimplementsHandlerInterceptor{
@Override
publicbooleanpreHandle(HttpServletRequest request, HttpServletResponse
response, Object handler)throws Exception {
        System.out.println("preHandle");
returntrue;
    }
@Override
publicvoidpostHandle(HttpServletRequest request, HttpServletResponse
response, Object handler, ModelAndView modelAndView)throws Exception {
        System.out.println("postHandle");
    }
@Override
publicvoidafterCompletion(HttpServletRequest request, HttpServletResponse
response, Object handler, Exception ex)throws Exception {
        System.out.println("afterCompletion");
    }
}

 MyInterceptor类:

@Configuration
publicclassMyMvcConfigimplementsWebMvcConfigurer{
@Autowired
private MyInterceptor myInterceptor;
@Override
publicvoidaddInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(myInterceptor)
                .addPathPatterns("/**");
    }
}

访问页⾯查看控制台打印结果。
简单应⽤在之前案例的基础上使⽤拦截器。
⽤户登录:

@Controller
publicclassLoginController{
@GetMapping("/login")
public String login(){
//System.out.println("controller");
return"login";
    }
@PostMapping("/login")
public String loginIn(@RequestParam("username") String username,
@RequestParam("password") String password, HttpSession session){
if (username.equals("xxx") && password.equals("123")) {
            session.setAttribute("username","xxx");
return"redirect:/admin/article";
        }
else
return"login";
    }
}

<!DOCTYPE html>
<htmllang="en"xmlns:th="http://www.thymeleaf.org">
<head>
<metacharset="UTF-8">
<title>用户登录界面</title>
<!-- 新 Bootstrap5 核心 CSS 文件 -->
<linkrel="stylesheet"href="https://cdn.staticfile.org/twitter-
bootstrap/5.1.1/css/bootstrap.min.css">
<!--  popper.min.js 用于弹窗、提示、下拉菜单 -->
<scriptsrc="https://cdn.staticfile.org/popper.js/2.9.3/umd/popper.min.js">
</script>
<!-- 最新的 Bootstrap5 核心 JavaScript 文件 -->
<scriptsrc="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.min.js"></script>
</head>
<body>
<!--  用户登录form表单 -->
<formth:action="@{/login}"method="post">
<divclass="mb-3">
<labelfor="username"class="form-label">用户名</label>
<inputtype="text"class="form-control"id="username"name="username">
</div>
<divclass="mb-3">
<labelfor="password"class="form-label">密码</label>
<inputtype="password"class="form-control"id="password"name="password">
</div>
<buttontype="submit"class="btn btn-primary">登录</button>
</form>
<p><spanth:text="${#dates.createNow()}"></span></p>
</body>
</html>

管理⽂章界⾯: 

@Controller
@RequestMapping("/admin")
publicclassArticleController{
@Autowired
    ArticleService articleService;
@GetMapping("/article")
public String article(Model model){
        List<Article> articleList = articleService.findAll();
        model.addAttribute("articles", articleList);
return"article";
    }
}
<!DOCTYPE html>
<htmllang="en"xmlns:th="http://www.thymeleaf.org">
<head>
<metacharset="UTF-8">
<title>用户登录界面</title>
<!-- 新 Bootstrap5 核心 CSS 文件 -->
<linkrel="stylesheet"href="https://cdn.staticfile.org/twitter-
bootstrap/5.1.1/css/bootstrap.min.css">
<!--  popper.min.js 用于弹窗、提示、下拉菜单 -->
<scriptsrc="https://cdn.staticfile.org/popper.js/2.9.3/umd/popper.min.js">
</script>
<!-- 最新的 Bootstrap5 核心 JavaScript 文件 -->
<scriptsrc="https://cdn.staticfile.org/twitter-
bootstrap/5.1.1/js/bootstrap.min.js"></script>
</head>
<body>
<!--  用户登录form表单 -->
<formth:action="@{/login}"method="post">
<divclass="mb-3">
<labelfor="username"class="form-label">用户名</label>
<inputtype="text"class="form-control"id="username"name="username">
</div>
<divclass="mb-3">
<labelfor="password"class="form-label">密码</label>
<inputtype="password"class="form-control"id="password"name="password">
</div>
<buttontype="submit"class="btn btn-primary">登录</button>
</form>
<p><spanth:text="${#dates.createNow()}"></span></p>
</body>
</html>

拦截器: 

@Configuration
publicclassMyInterceptorimplementsHandlerInterceptor{
@Override
publicbooleanpreHandle(HttpServletRequest request, HttpServletResponse
response, Object handler)throws Exception {
//URI:统一资源标识符,表示Web上每一种可用的资源,如HTML文档,图像,视频片段,程
序等都是由一个URI进行标识的(身份证号)
        String uri = request.getRequestURI();
        Object loginUser = request.getSession().getAttribute("username");
if (uri.startsWith("/admin") && null == loginUser) {
            response.sendRedirect("/login");
returnfalse;
        }
//System.out.println("preHandle");
returntrue;
    }
@Override
publicvoidpostHandle(HttpServletRequest request, HttpServletResponse
response, Object handler, ModelAndView modelAndView)throws Exception {
//request.setAttribute("msg","后置拦截器传递");
//System.out.println("postHandle");
    }
@Override
publicvoidafterCompletion(HttpServletRequest request, HttpServletResponse
response, Object handler, Exception ex)throws Exception {
//System.out.println("afterCompletion");
    }
}

@Configuration
publicclassMyMvcConfigimplementsWebMvcConfigurer{
@Autowired
private MyInterceptor myInterceptor;
@Override
publicvoidaddInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(myInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值