博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring初步学习——Spring MVC
阅读量:4100 次
发布时间:2019-05-25

本文共 10594 字,大约阅读时间需要 35 分钟。

MVC 设计概述

 

在早期Java Web的开发中,统一把显示层,控制层,数据层全部交给JSP或者JavaBean来进行处理,就像下图所示:

【弊端】:

  • JSP和Java Bean之间严重耦合,java代码和HTML代码也耦合在了一起
  • 要求开发者不仅要掌握java,还要有高水平的前端技术
  • 前段和后端相互依赖,前段需要等待后端完成,后端也要依赖前端完成,才能进行有效的测试
  • 代码难以复用

正是因为上面的弊端,所以很快就被Servlet+JSP+Java Bean所取代,早期的MVC模型如下:

首先用户的请求会到达Servlet,然后根据请求调用相应的Java Bean,并把显示结果交给JSP去完成,这样的模式我们称为MVC模式:

M 代表 模型(Model)

模型是什么呢? 模型就是数据,就是 dao,bean
V 代表 视图(View)
视图是什么呢? 就是网页, JSP,用来展示模型中的数据
C 代表 控制器(controller)
控制器是什么? 控制器的作用就是把不同的数据(Model),显示在不同的视图(View)上,Servlet 扮演的就是这样的角色

Spring MVC架构

使用XML配置Spring MVC

为解决持久层一直未处理好的数据库事务的编程,又为了迎合NoSQL的强势崛起,Spring MVC给出了方案

传统的业务层被拆分为业务层(Service)和数据访问层(Dao),在Service下可以通过Spring的声明式事务操作数据访问层,而在业务上还允许我们访问NoSQL,这样就能够满足异军突起的NoSQL的使用,它可以大大提高互联网系统的性能

特点:

  • 结构松散,几乎可以在Spring MVC中使用各类视图
  • 松耦合,各模块分离
  • 与Spring无缝集成

接下来我们再来实战一下:

1、在IDEA中新建Spring MVC项目,取名为【HelloSpringMVC】,IDEA会自动为我们下载必要的jar包,并且为我们创建好一些默认的目录和文件

2、修改web.xml文件,如下所示:

   
dispatcher
   
/

3、编辑dispatcher-servlet.xml,这是Spring MVC的映射配置文件,我们编辑如下:

   
       
           
               
               
helloController
           
       
   
   

4、编写HelloController,在Package【controller】下新建【HelloController】类,并实现

org.springframework.web.servlet.mvc.Controller接口:package controller;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;public class HelloController implements Controller{    @Override    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {        return null;    }}

Note:这个时候会出现报错问题,提示javax.servlet包找不到,将Tomcat目录下【lib】lib文件夹下的servlet-api.jar包拷贝到工程【lib】文件夹下,添加依赖Spring MVC通过ModelAndView对象把模型和视图结合在一起

package controller;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.mvc.Controller;public class HelloController implements Controller {    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {        ModelAndView mav = new ModelAndView("index.jsp");        mav.addObject("message", "Hello Spring MVC");        return mav;    }}

5、准备index.jsp,将index.jsp的内容修改为

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8" isELIgnored="false"%> 

${message}

跟踪Spring MVC的请求:

每当用户在Web浏览器中点击链接或者提交表单的时候,请求就开始工作了,想邮递员一样,从离开浏览器开始到响应返回,它会经历很多站点,在每一个站点都会留下一些信息同时也会带上一些其他的信息,下图为Spring MVC的请求流程:

1》第一站:DispatcherServlet

从请求离开浏览器以后,第一站到达的就是DispatcherServlet,看名字就知道是一个Servlet,通过J2EE的学习,我们知道Servlet可以拦截并处理HTTP请求,DispatcherServlet会拦截所有请求,并且将这些请求发送给Spring MVC控制器

DispatcherServlet的任务就是拦截请求发送给Spring MVC控制器

   
dispatcher
   
org.springframework.web.servlet.DispatcherServlet
   
1
   
dispatcher
   
   
/

2》第二站:处理器映射(HandlerMapping)

问题:典型的应用程序中可能会有多个控制器,这些请求到底应该发给哪一个控制器呢?

所以DispatcherServlet会查询一个或多个处理器映射来确定请求的下一站在哪里,处理器映射会根据请求携带的URL信息来进行决策,例如上面的例子中我们通过simpleUrlHandlerMapping来将/hello地址交给helloController处理

3》控制器

一旦选择合适的控制器,DispatcherServlet会将请求发送给选中的控制器,到了控制器,请求会卸下负载(用户提交的请求)等待控制器处理这些信息:

4》返回DispatcherServlet

当控制器在完成逻辑处理后,通常会产生一些信息,这些信息就是需要返回给用户并在浏览器上显示的信息,他们被称为模型(Model)。仅仅返回原始的信息是不够的——这些信息需要以用户友好的方式进行格式化,一般会是HTML,所以,信息需要发送给一个视图(view),通常是JSP

控制器所做的最后一件事就是将模型打包,并且表示出用于渲染输出的视图名(逻辑视图名)。他接下来会将请求连同模型和视图名发送回DispatcherServlet

5》视图解析器

这样的话,控制器就不会和特定的视图相耦合,传递给DispatcherServlet的视图名并不直接表示某个特定的JSP,他仅仅传递是一个逻辑名称,这个名称将会用来查找产生结果的真正视图

DispatcherServlet将会使用视图解析器(view resolver)来将逻辑视图名匹配为一个特定的视图实现,它可能也不是JSP

6》视图

既然DispatcherServlet已经知道由哪个视图渲染结果了,那请求的任务基本上也就完成了

它的最后一站是视图的实现,在这里他交付模型数据,请求的任务也就完成了,视图使用模型数据渲染出结果,这个结果会通过响应对象传递给客户端

使用注解配置Spring MVC

上面的例子我们采用了XML配置的方式,接下来我们看看基于注解应该怎么完成上述程序的配置

1、为HelloController添加注解

package controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;@Controllerpublic class HelloController{    @RequestMapping("/hello")    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {        ModelAndView mav = new ModelAndView("index.jsp");        mav.addObject("message", "Hello Spring MVC");        return mav;    }}

@Controller注解:是用来声明控制器的

@RequestMapping:表示路径/hello会映射到该方法上

2、取消之前的XML注解

在dispatcher-servlet.xml文件中,注释掉之前的配置,然后增加一句组件扫描

   
                                       
   
           
               
               
           
       
   
   
   
   

3、重启服务器,运行

@RequestMapping注解

作用在类上:相当于给该类所有配置的映射地址前加了一个地址

@Controller@RequestMapping("/wmyskxz")public class HelloController {    @RequestMapping("/hello")    public ModelAndView handleRequest(....) throws Exception {        ....    }}

则,访问地址变为:localhost/wmyskxz/hello

配置视图解析器:

视图解析器负责定位视图,他接受一个由DispatcherServlet传递的逻辑视图名来匹配一个特定的视图

需求:有些视图我们不希望用户直接访问到,例如有重要数据的页面,有模型数据支撑的页面

解决方案:我们将JSP文件配置在【WEB-INF】文件夹中的【page】文件夹下,【WEB-INF】是java Web中默认的安全目录,是不允许用户直接访问的

但是我们需要将这告诉视图解析器,我们在dispatcher-servlet.xml文件中做如下配置:

   
   

这里配置了一个Spring MVC内置的一个视图解析器,该解析器是遵循着一种约定:会在视图名上添加前缀和后缀,进而确定一个Web应用中视图资源的物理路径,我们再来重新配置一下:

1、将HelloController的index.jsp修改为index

2、配置视图解析器

   
                                       
   
           
               
               
           
       
   
   
   
   
   
       
       
   

3、在【WEB-INF】文件夹下新建一个【page】文件夹,并将【index.jsp】文件剪贴到里面

4、更新资源重启服务器

访问localhost/hello路径,仍可以看到上面的界面

原理:

Note:此时的配置仅是在dispatcher-servlet.xml下的

控制器接收请求数据

使用控制器接收参数往往是Spring MVC开发业务逻辑的第一步,为探索Spring MVC的传参方式,为此我们先来创建一个简单的表单用于提交数据:

<%@ page language="java" contentType="text/html; charset=UTF-8"         pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>    
    Spring MVC 传参方式
    用户名:
    密码:
   

1》使用servlet原生API实现:

从上面的代码我们可以看出,表单是会提交到/param这个目录,我们先来使用Servlet原生API看看能能获取到数据

@RequestMapping("/param")public ModelAndView getParam(HttpServletRequest request,                         HttpServletResponse response) {    String userName = request.getParameter("userName");    String password = request.getParameter("password");    System.out.println(userName);    System.out.println(password);    return null;}

2》使用同名匹配规则:

@RequestMapping("/param")public ModelAndView getParam(String userName,String password) {    System.out.println(userName);    System.out.println(password);    return null;}//使用@RequestParam("前台参数名")来注入,从而实现解耦@RequestMapping("/param")public ModelAndView getParam(@RequestParam("username") String userName,@RequestParam("password") String password) {    System.out.println(userName);    System.out.println(password);    return null;}

3》使用模型传参

要求:前台参数名字必须和模型中的字段名一样

我们先来为我们的表单创建一个User模型:

package pojo;public class User {        String userName;    String password;    /* getter and setter */}@RequestMapping("/param")public ModelAndView getParam(User user) {    System.out.println(userName);    System.out.println(password);    return null;}

中文乱码问题,我们可以通过配置Spring MVC字符编码过滤器来完成,在web.xml中添加如下代码:

   
CharacterEncodingFilter
   
org.springframework.web.filter.CharacterEncodingFilter
   
       
encoding
       
       
utf-8
   
   
CharacterEncodingFilter
   
/*

控制器回显数据

通过上面的学习,我们知道了怎么接受请求数据,并且能够解决POST乱码问题,那么我们怎么回显数据呢?接下来先新建一个【test2.jsp】

<%@ page language="java" contentType="text/html; charset=UTF-8"         pageEncoding="UTF-8" import="java.util.*" isELIgnored="false" %>    Spring MVC 数据回显

回显数据:${message}

1》使用Servlet原生API来实现

@RequestMapping("/value")public ModelAndView handleRequest(HttpServletRequest request,                                  HttpServletResponse response) {    request.setAttribute("message","成功!");    return new ModelAndView("test1");}

在浏览器中输入:localhost/value 测试,能够显示成功

2》使用Spring MVC所提供的ModelAndView对象

@RequestMapping("/value")public ModelAndView handleRequest(HttpServletRequest req,HttpServletResponse resp){    ModelAndView mav = new ModelAndView("test1");    mav.addObject("message","成功");    return mav;}

3》使用Model对象

//在Spring MVC中可以使用这样的方式来绑定数据@RequestMapping("/value")public String handleRequest(Model  model){    model.addAttribute("message","成功!");    return "test1";}

4》使用@ModelAttribute注解

@ModelAttributepublic void model(Model model) {    model.addAttribute("message", "注解成功");}@RequestMapping("/value")public String handleRequest() {    return "test1";}//这样写的话就会在访问控制器方法handlerRequest()时,先调用model()方法,//将message添加至页面参数中,在视图中直接调用,但是这样写会导致控制器的所有//方法都会调用model()方法

客户端跳转:

前面的不管是地址/hello跳转到index.jsp环视/test跳转到etst.jsp,这些都是服务器的跳转,也就是

request.getRequestDispatcher(“地址”).forward(request,response);

我们继续HelloController中编写,实现客户端跳转:

@RequestMapping("/hello")public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {    ModelAndView mav = new ModelAndView("index");    mav.addObject("message", "Hello Spring MVC");    return mav;}@RequestMapping("/jump")public ModelAndView jump() {    ModelAndView mav = new ModelAndView("redirect:/hello");    return mav;}//也可以这么写@RequestMapping("/jump")public String jump() {    return "redirect: ./hello";}

Note:我们使用 redirect:/hello 表示我们要跳转到/hello这个路径,我们重启服务器,在地址栏输入localhost/jump,会自动跳转到 /hello 路径下

Spring MVC中的文件上传和下载

首先导入jar包,commons-io-1.3.2.jar和commons-fileupload-1.2.1.jar两个包,接下来举例说明:

1、配置上传解析器

在dispatcher-servlet.xml中新增如下这句,开启对上传功能的支持

2、编写JSP

文件名为upload.jsp,仍创建在【page】下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>    测试文件上传
   
   

3、编写控制器

在Package【controller】下新建【UploadController】类:

package controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.multipart.MultipartFile;import org.springframework.web.servlet.ModelAndView;@Controllerpublic class UploadController {    @RequestMapping("/upload")    public void upload(@RequestParam("picture") MultipartFile picture) throws Exception {        System.out.println(picture.getOriginalFilename());    }    @RequestMapping("/test2")    public ModelAndView upload() {        return new ModelAndView("upload");    }}

4、测试,在浏览器地址栏输入:localhost/test2,选择文件点击上传

转载:

欢迎大家一起来交流学习哦,如果有错误的地方欢迎指出!谢谢

你可能感兴趣的文章
拉格朗日对偶问题详解
查看>>
MFC矩阵运算
查看>>
最小二乘法拟合:原理,python源码,C++源码
查看>>
ubuntu 安装mysql
查看>>
c# 计算器
查看>>
C# 简单的矩阵运算
查看>>
gcc 常用选项详解
查看>>
c++输入文件流ifstream用法详解
查看>>
c++输出文件流ofstream用法详解
查看>>
字符编码:ASCII,Unicode 和 UTF-8
查看>>
QT跨MinGW和MSVC两种编译器的解决办法
查看>>
firewalld的基本使用
查看>>
Linux下SVN客户端使用教程
查看>>
i2c-tools
查看>>
Linux分区方案
查看>>
nc 命令详解
查看>>
如何使用 systemd 中的定时器
查看>>
git命令速查表
查看>>
linux进程监控和自动重启的简单实现
查看>>
OpenFeign学习(三):OpenFeign配置生成代理对象
查看>>