SpringMVC

★springMVC表现层框架

什么是MVC?

  • MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范

  • 是将业务逻辑、数据、显示分离的方法来组织代码

  • MVC主要作用是降低了视图与业务逻辑间的双向耦合

  • MVC不是一种设计模式,MVC是一种架构模式,不同的MVC存在差异

Model(模型):数据模型,提供前端要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao)和服务层(行为Service),也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务

View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西

Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示,也就是说控制器做了个调度员的工作

SpringMVC

Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架

Spring MVC的特点:

​ 1、轻量级,简单易学

​ 2、高效,基于请求响应的MVC框架

​ 3、与Spring兼容性好,无缝结合

​ 4、约定优于配置

​ 5、功能强大:RESTful、数据验证、格式化、本地化、主题化等

​ 6、简洁灵活

最开始我们在处理请求和响应是基于servlet的,那servlet是一个规范,不属于框架,springMVC是一个表现层的框架,在底层封装了servlet

MVC实现了视图和业务代码的分离

springMVC核心原理

  1. 用户发送请求给服务器,url:user.do
  2. 服务器收到请求,发现DispatcherServlet可以处理,于是调用DispatcherServlet
  3. DispatcherServlet内部,通过HandlerMappings(处理映射器)检查这个url有没有对应的Controller,如果有,则通HandlerAdapters(处理适配器)调用Controller
  4. Controller开始执行
  5. Controller执行完毕后,如果返回字符串,则ViewResolvers将字符串转化成相应的视图对象,如果返回ModelAndView对象,该对象本身就包含了视图对象信息
  6. DispatcherServlet通过ViewResolvers(视图解析器)将视图对象中的数据输出给服务器
  7. 服务器将数据输出给客户端

springMVC整体调度流程

  • 客户端发送请求给服务端,springMVC框架会通过DispatcherServlet来做一个资源的拦截(http://localhost:8080/servlet/test)
  • DispatcherServlet会调用处理映射器HandlerMappings来完成对地址的解析,然后把解析的信息告诉DispacherServlet
  • DispacherServlet调用处理适配器HandlerAdapters从容器中找到对应的资源(会找到controller对应的资源)
  • HandlerAdapters找到对应资源之后,会去执行具体的Controller(然后会去封装数据,设置视图名称)
  • 执行完逻辑之后会将视图和模块(ModelAndView)返回给DispacherServlet
  • 继续调用视图解析器ViewResolvers视图解析器来解析ModelAndView里面视图名称,然后根据视图解析器内部的匹配规则来定位到具体的前端资源(jsp)
  • ViewResolvers在解析完之后会将解析的信息告诉DispacherServlet,然后会去做具体的页面跳转,数据渲染等工作

配置springMVC

springMVC框架如何去使用,如何去配置?

使用控制器

创建一个TestController类,实现Controller接口

package com.os467.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 TestController implements Controller {

    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

        //创建一个模型视图对象
        ModelAndView modelAndView = new ModelAndView();

        //封装数据
        modelAndView.addObject("name","Hello spring MVC");

        //设置视图名称
        modelAndView.setViewName("test02");

        return modelAndView;

    }

}

我们在定义了一个Controller之后如何通过mvc去访问这个资源?

1、在web.xml中配置DispatcherServlet:mvc框架前端总调度器

具体会去完成web交互时的各自调度工作

  • Spring的web框架围绕DispatcherServlet调度Servlet设计
  • DispatcherServlet的作用是将请求分发到不同的处理器,从Spring2.5开始,使用Java5或者以上版本的用户可以采用基于注解形式进行开发

web.xml中配置前端总调度器,所有的访问请求都会进入此资源

<?xml version="1.0" encoding="UTF-8"?>
<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_4_0.xsd"
         version="4.0">
    
   <!--配置前端总调度器-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        
        <!--拦截所有的客户端的请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

2、由于MVC框架属于spring的功能模块,所以必须得有核心容器的支持,要去创建spring配置文件springMVC.xml

创建springMVC.xml配置文件,引入springMVC的xml约束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
</beans>

web.xml中注册配置文件位置,核心容器对象可以交给DispacherServlet去创建,需要指定配置文件的位置,以及设置启动级别

<!--配置前端总调度器-->
 <servlet>
     <servlet-name>dispatcherServlet</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

     <!--绑定springMVC的配置文件-->
     <init-param>
         <param-name>contextConfigLocation</param-name>
         <!--配置文件的路径-->
         <param-value>classpath:xml/springMVC.xml</param-value>
     </init-param>

     <!--设置启动级别,需要在tomcat服务器启动的时候就去加载核心容器对象-->
     <load-on-startup>1</load-on-startup>

 </servlet>

继续配置springMVC.xml,注册controller组件,视图解析器实例

<!--注册controller组件-->
<bean id="/controller1" class="com.os467.controller.TestController"></bean>

<!--处理映射器和适配器可以不做注册,这里仅作演示-->
<!--注册一个处理映射器-->
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>

<!--注册一个处理适配器-->
<bean id="handlerAdapter" class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>

<!--必须要配置视图解析器-->
<!--注册一个视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">

    <!--设置视图的前缀-->
    <property name="prefix" value="/jsp/"></property>

    <!--设置视图的后缀-->
    <property name="suffix" value=".jsp"></property>

</bean>

SpringMVC基于注解

<mvc:default-servlet-handler/>

让SpringMVC不处理静态资源

<mvc:annotation-driven/>

支持mvc注解驱动

InternalResourceViewResolver

视图解析器

配置xml,开启对注解的支持

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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">

    <!--开启扫描包-->
    <context:component-scan base-package="com.os467"></context:component-scan>

    <!--过滤静态资源-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>

    <!--支持mvc注解的驱动-->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!--配置视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">

        <!--设置前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"></property>

        <!--设置后缀-->
        <property name="suffix" value=".jsp"></property>

    </bean>

</beans>

@Controller注解

这个注解如果只是在spring框架中使用的话,就是将当前类的实例存到容器中
但是如果在springMVC中去使用,它不仅可以存实例到容器,还能够将该类下任意一个方法的返回值是String
的方法,返回值会作为视图名称,用于视图跳转

@RequestMapping注解

用于地址的映射,可以修饰类也可以修饰方法,也可以只在方法上使用,能够体现层级关系

@Controller
@RequestMapping("user")
public class UserController {

    @RequestMapping("test")
    public String getTest(){

        return "test";

    }

}

此时在前端访问:http://localhost:8080/springMVC/user/test 测试资源

@ResponseBody注解

让当前视图失效,并且会直接返回数据

springMVC如何去接收前端传递过来的值

​ springMVC可以支持参数接值,你在前端需要传递的数据,后端mvc可以使用参数进行接收

可以在接收参数的时候接收HttpServletrequest,再接收Parameter值

也可以在参数中根据对应参数名接值

//前端测试:http://localhost:8080/springMVC/user/test03?username=jack001&password=123456&i=10&d=3.14
@RequestMapping("test03")
public String getTest03(String username,String password,int i,double d){

    System.out.println(username+" "+password+" "+i+" "+d);

    return "test";

}

springMVC在参数列表中可以通过实体进行接值

mvc会根据接收实例的属性名称来接收对应的前端数据,并且封装成java对象

@RequestMapping("test04")
public String getTest04(MvcVo mvcVo){

    System.out.println(mvcVo);

    return "test";

}

springMVC如何将封装好的数据存到Model中

在参数中接收一个Model接口的实例,是由springMVC提供的,底层封装了request域

通过返回字符串的方式

@RequestMapping("test05")
public String getTest05(MvcVo mvcVo, Model model){

    //把实体存到Model中,底层封装了一个request域
    model.addAttribute("mcvVo",mvcVo);

    return "test02";

}

通过返回ModelAndView的方式

@RequestMapping("list")
public ModelAndView getEmpList(){

    ModelAndView modelAndView = new ModelAndView();

    List<Emp> empList = empService.getEmpList();

    //访问持久层查询数据
    modelAndView.addObject("empList",empList);

    //设置视图名称
    modelAndView.setViewName("list");

    return modelAndView;
}

通过SpringMVC来实现转发和重定向

默认是定位视图资源

forward 转发

在MVC框架中视图跳转默认就是请求转发 forward:t8

redirect 重定向

都是根据内部资源跳转,如果不写则是要去定位视图 redirect:t8

//从t9重定向到t8
@RequestMapping("/t9")
public String test09(){
    
    return "redirect:t8"
    
}

支持mvc返回对象给客户端

会自动将对象转成json,然后再响应

导入下面pom坐标

<!-- jackson依赖 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.11.3</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.3</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.11.3</version>
</dependency>

项目

通过spring + springMVC + jdbcTemplate 来搭建一个web项目,完成员工列表

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<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_4_0.xsd"
         version="4.0">
    <!--配置前端总控制器-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--绑定核心配置容器-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:xml/springMVC.xml</param-value>
        </init-param>

        <!--设置启动级别-->
        <load-on-startup>1</load-on-startup>

    </servlet>


    <!--拦截客户端所有请求-->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

springMVC.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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">

    <!--开启扫描包-->
    <context:component-scan base-package="com.os467"></context:component-scan>

    <!--过滤静态资源-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>

    <!--开启mvc注解的支持-->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!--配置视图解析器-->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--设置前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <!--设置后缀-->
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--配置一个持久层的实例-->
    <bean id="empDao" class="com.os467.dao.impl.EmpDaoImpl">
        
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
        
    </bean>

    <!--注册数据源实例-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

        <!--注入数据源-->
        <property name="url" value="jdbc:mysql://localhost:3306/web_test?serverTimezone=GMT&amp;characterEncoding=utf-8"></property>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>

    </bean>

    <!--注册jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

        <!--注入数据源数据-->
        <property name="dataSource" ref="dataSource"></property>
        
    </bean>

</beans>

表现层(控制器)

package com.os467.controller;

import com.os467.pojo.Emp;
import com.os467.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import java.util.List;

@Controller
@RequestMapping("emp")
public class EmpController {

    @Autowired
    private EmpService empService;

    //建立视图层级关系,添加资源路径
    @RequestMapping("/list")
    public String getEmpList(Model model){

        List<Emp> empList = empService.getEmpList();

        //访问持久层查询数据
        model.addAttribute("empList",empList);

        return "list";

    }

    //建立视图层级关系,添加资源路径
    @RequestMapping("/add")
    public String getAddPage(){

        //跳转添加页面
        return "add";

    }

    @ResponseBody
    //建立视图层级关系,添加资源路径
    @RequestMapping("/addSave")
    public String addSave(Emp emp){

        boolean b = empService.addSave(emp);

        //返回信息
        return b?"1":"0";
    }

    @ResponseBody
    //建立视图层级关系,添加资源路径
    @RequestMapping("/deleteByEid")
    public String deleteByEid(Integer eid){

        boolean b = empService.deleteByEid(eid);

        //返回信息
        return b?"1":"0";
    }

    //建立视图层级关系,添加资源路径
    @RequestMapping("/getUpdate")
    public String getUpdate(Integer eid,Model model){

        Emp emp = empService.getUpdate(eid);

        model.addAttribute("emp",emp);

        //跳转编辑页面
        return "update";
    }

    @ResponseBody
    //建立视图层级关系,添加资源路径
    @RequestMapping("/updateSave")
    public String updateSave(Emp emp){

        boolean b = empService.updateSave(emp);

        //返回信息
        return b?"1":"0";
    }


}

业务层

package com.os467.service.impl;

import com.os467.dao.EmpDao;
import com.os467.pojo.Emp;
import com.os467.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class EmpServiceImpl implements EmpService {

    @Autowired
    private EmpDao empDao;

    @Override
    public List<Emp> getEmpList() {

        return empDao.getEmpList();
    }

    @Override
    public boolean addSave(Emp emp) {
        return empDao.addSave(emp);
    }

    @Override
    public boolean deleteByEid(Integer eid) {
        return empDao.deleteByEid(eid);
    }

    @Override
    public Emp getUpdate(Integer eid) {
        return empDao.getUpdate(eid);
    }

    @Override
    public boolean updateSave(Emp emp) {
        return empDao.updateSave(emp);
    }
}

持久层

package com.os467.dao.impl;

import com.os467.dao.EmpDao;
import com.os467.pojo.Emp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@Repository
public class EmpDaoImpl implements EmpDao {

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 获取员工列表的方法
     * @return
     */
    @Override
    public List<Emp> getEmpList() {
        return jdbcTemplate.query("select * from emp", new RowMapper<Emp>() {
            @Override
            public Emp mapRow(ResultSet resultSet, int i) throws SQLException {

                Emp emp = new Emp();

                emp.setEmpName(resultSet.getString("emp_name"));
                emp.setAge(resultSet.getInt("age"));
                emp.setEid(resultSet.getInt("eid"));
                emp.setSex(resultSet.getInt("sex"));
                emp.setSalary(resultSet.getInt("salary"));
                emp.setBirthday(resultSet.getString("birthday"));

                return emp;
            }
        });
    }

    /**
     * 保存用户数据
     * @return
     * @param emp
     */
    @Override
    public boolean addSave(Emp emp) {

        int i = jdbcTemplate.update("insert into emp(emp_name,age,sex,salary,birthday)values(?,?,?,?,?)", emp.getEmpName(),
                emp.getAge(), emp.getSex(), emp.getSalary(), emp.getBirthday());

        return i>0?true:false;
    }

    @Override
    public boolean deleteByEid(Integer eid) {

        int i = jdbcTemplate.update("delete from emp where eid = ?", eid);

        return i>0?true:false;
    }

    /**
     * 回显用户信息的方法
     * @return
     */
    @Override
    public Emp getUpdate(Integer eid) {

        List<Emp> empList = jdbcTemplate.query("select * from emp where eid = ?", new RowMapper<Emp>() {


            @Override
            public Emp mapRow(ResultSet resultSet, int i) throws SQLException {

                Emp emp = new Emp();

                emp.setEmpName(resultSet.getString("emp_name"));
                emp.setAge(resultSet.getInt("age"));
                emp.setEid(resultSet.getInt("eid"));
                emp.setSex(resultSet.getInt("sex"));
                emp.setSalary(resultSet.getInt("salary"));
                emp.setBirthday(resultSet.getString("birthday"));

                return emp;
            }
        }, eid);

        return empList.get(0);
    }

    /**
     * 编辑用户信息的方法
     * @return
     */
    @Override
    public boolean updateSave(Emp emp) {

        int i = jdbcTemplate.update("update emp set emp_name = ?,age = ?,sex = ?,salary = ?,birthday = ? where eid = ?",
                emp.getEmpName(), emp.getAge(), emp.getSex(), emp.getSalary(), emp.getBirthday(),emp.getEid());

        return i>0?true:false;
    }
}

springMVC能够高效的去处理请求和响应,还支持参数接值,也可以支持注解的方式来映射资源路径


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com

文章标题:SpringMVC

字数:4.4k

本文作者:Os467

发布时间:2022-07-23, 21:35:21

最后更新:2022-09-05, 00:09:26

原始链接:https://os467.github.io/2022/07/23/springMVC/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

×

喜欢就点赞,疼爱就打赏