欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringMVC入门案例和常用API使用演示

程序员文章站 2022-03-20 23:03:05
文章目录SpringMVC入门案例文件结构步骤概述步骤实现常用API视图解析具体实现SpringMVC入门案例SpringMVC的创建方式有xml和配置类两种方式这里只记录实际应用中使用的方式搭建SpringMVC工程文件结构步骤概述因为采用父级工程和子工程的方式进行演示,所以此处只对父级pom.xml文件进行修改,添加子工程需要的依赖包以及jdk版本构建配置类WebConfig,扫描Controller层编辑controller层,对页面请求进行处理构建启动类,该启动类继承了Ab...

SpringMVC入门案例

SpringMVC的创建方式有xml和配置类两种方式
这里只记录实际应用中使用的方式搭建SpringMVC工程

文件结构

SpringMVC入门案例和常用API使用演示

步骤概述

  1. 因为采用父级工程和子工程的方式进行演示,所以此处只对父级pom.xml文件进行修改,添加子工程需要的依赖包以及jdk版本
  2. 构建配置类WebConfig,扫描Controller层
  3. 编辑controller层,对页面请求进行处理
  4. 构建启动类,该启动类继承了AbstractAnnotationConfigDispatcherServletInitializer,并通过其下的三个函数对配置类进行解析
  5. 编写需要的前端页面

步骤实现

  • 父级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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.dean</groupId>
  <artifactId>SpringMvcAPi</artifactId>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>mvc-viewResolution</module>
  </modules>
  <packaging>pom</packaging>

  <name>SpringMvcAPi</name>
  <url>http://maven.apache.org</url>

  <!--1、修改父级的pom.xml文件 只需要修改properties和dependencies节点的内容-->
  <!--修改版本-->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <!--添加所有子工程可能用到的依赖包-->
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.3.0</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.0</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.3.0</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>
  </dependencies>
</project>
  • 构建web配置类WebConfig
@ComponentScan("com.dean.controller")
public class WebConfig {
}
  • 编辑前端控制器 controller层
@Controller   //将bean注入到Spring容器
@RequestMapping("/user")     //配置请求映射,在请求时用来区分不同的controller
public class UserController {
    //返回页面有两种写法
    //1、返回页面的文件名,作为字符串,框架会调用ModelAndView进行返回视图
    //实际请求拼接了/user和/hello 从而找到hello方法
    @RequestMapping("/hello")
    public String hello()
    {
        return "/hello.jsp";
    }

    //2、直接设置返回值为ModelAndView
    @RequestMapping("/view")
    public ModelAndView view()
    {
        return new ModelAndView("/view.jsp");
    }
}
  • 编写启动类
public class WebMvcInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    //整合Spring使用的,这里暂不配置
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    //指定SpringMvc的配置类
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    //配置请求映射,这里配置所有请求,即/
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
  • 编写前端页面 index(主页)hello(/user/hello请求页面)view(/user/view请求页面)
    index
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <%--5、编写前端页面  index主页--%>
    <title>主页</title>
</head>
<body>
<h1>
    <a href="/user/hello">hello</a>
</h1>
<h1>
    <a href="/user/view">view</a>
</h1>
</body>
</html>

hello

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <%--5、编写前端页面 hello--%>
    <title>Hello</title>
</head>
<body>
<h1>Hello</h1>
</body>
</html>

view

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <%--5、编写前端页面 view--%>
    <title>View</title>
</head>
<body>
<h1>View</h1>
</body>
</html>

常用API

视图解析

视图解析实质上是利用对方法的后置拦截,在返回视图时进行配置视图解析器,使得在controller层返回参数的时候,只需要返回视图名称,而无需返回后缀名等

具体实现

在上述项目的WebConfig类中注入InternalResourceViewResolver

@ComponentScan("com.dean.controller")
public class WebConfig {
    //添加视图解析器
    @Bean
    public InternalResourceViewResolver viewResolver()
    {
        InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
        //设置视图路径前缀
        viewResolver.setPrefix("/");
        //设置视图路径的后缀
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}

controller层的代码返回值的更改

@Controller   //将bean注入到Spring容器
@RequestMapping("/user")     //配置请求映射,在请求时用来区分不同的controller
public class UserController {
    @RequestMapping("/hello")
    public String hello()
    {
        //配置视图解析器之前
        //return "/hello.jsp";

        //配置视图解析器后
        return "hello";
    }

    @RequestMapping("/view")
    public ModelAndView view()
    {
        //配置视图解析器之前
        //return new ModelAndView("/view.jsp");

        //配置视图解析器之后
        return new ModelAndView("view");
    }

}

视图解析器会使springmvc获取到controller方法的返回值,然后与前缀后缀拼接得到完整的视图路径

但上述的视图解析器配置的是放在根路径下,从外部可以直接访问,在安全性上较差,servlet对此有所改进,将视图放在WEB-INF目录下,在该目录下的视图只能从内部访问,而无法从外部直接访问
改进后的文件结构如下:
SpringMVC入门案例和常用API使用演示

改进后的视图解析器代码如下:

@ComponentScan("com.dean.controller")
public class WebConfig {
    //添加视图解析器
    @Bean
    public InternalResourceViewResolver viewResolver()
    {
        InternalResourceViewResolver viewResolver=
        				new InternalResourceViewResolver();
        //直接放在根目录下不安全,改进版
        //设置视图路径前缀
        viewResolver.setPrefix("/WEB-INF/view/");
        //设置视图路径后缀
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}

参数传递(等同于servlet中的request.getAttribute())

在Servlet中参数的传递通过request.getAttribute()方法,返回值是string,使用时需要自行转换
springMvc简化了这一过程,具有自动参数转化功能

基本数据类型 & String类型

主要核心代码在Controller层

@Controller
@RequestMapping("/user")
public class UserController {
    //value是请求映射
    //method是请求方法  类似servlet的doPost方法
    @RequestMapping(value = "/addUser",method = RequestMethod.POST)
    public ModelAndView addUser(
            //@RequestParam 说明该参数是请求参数
            //name 指明参数名称 与表单中标签的名称一致   未指定时默认与形参变量名相同
            //required 确定参数是否必须传递 未指定时默认为true
            //defaultValue 当参数不是一定要传递时,可以设定参数的默认值
            @RequestParam(name="username",required = true) String name,
            @RequestParam(required = false,defaultValue = "21") Integer age,
            String phone
    )
    {
        System.out.println(name+"\t"+age+"\t"+phone);
        return new ModelAndView("success");
    }
}

请求页面使用表单完成

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>主页</title>
</head>
<body>
<h1>基本数据类型 & String</h1>
<form action="/user/addUser" method="post">
    <p>
        <label for="username">username:</label>
        <input type="text" id="username" name="username">
    </p>

    <p>
        <label for="age">age:</label>
        <input type="text" id="age" name="age">
    </p>

    <p>
        <label for="phone">phone:</label>
        <input type="text" id="phone" name="phone">
    </p>
    <button type="submit">add</button>
</form>
</body>
</html>

对象类型(自动装箱)

当传递的参数是自定义的对象类型时,SpringMVC采用了自动装箱技术,会去自动匹配POJO类型(pojo是简单java对象,即javaBean,只是叫了不同的名字)
对象类型Pet

public class Pet {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Pet{" +
                "name='" + name + '\'' +
                '}';
    }
}

Person类

public class Person {
    private String name;
    private Integer age;
    private Pet pet;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Pet getPet() {
        return pet;
    }

    public void setPet(Pet pet) {
        this.pet = pet;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", pet=" + pet +
                '}';
    }
}

Controller

@Controller
@RequestMapping("/user")
public class UserController {
    //对象类型自动装箱
    @RequestMapping(value = "/addPerson",method = RequestMethod.POST)
    public ModelAndView addPerson(
            /*
            会去自动找Person类,调用setter方法
             */
            Person person
    )
    {
        System.out.println(person);
        return new ModelAndView("success");
    }

}

前端页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>主页</title>
</head>
<body>
<h1>对象类型 自动装箱</h1>
<form action="/user/addPerson" method="post">
    <p>
        <label for="name">Person-name:</label>
        <input type="text" name="name" id="name">
    </p>

    <p>
        <label for="age">Age:</label>
        <input type="text" name="age" id="age">
    </p>

    <p>
        <label for="pet-name">Pet-name:</label>
        <input type="text" name="pet.name" id="pet-name">
    </p>

    <button type="submit">add</button>
</form>
</body>
</html>

日期类型

针对日期类型,主要依靠两个注解
@EnableWebMvc 和 @DateTimeFormat
两步搞定
1、在WebConfig上添加注解@EnableWebMvc
2、在形参或成员变量上添加注解@DateTimeFormat
具体代码如下:
WebConfig

@ComponentScan("com.dean.controller")
@EnableWebMvc    //开启转换器 便于将表单提交的String类型的数据转换为Date类型
public class WebConfig {
    @Bean
    public InternalResourceViewResolver viewResolver()
    {
        InternalResourceViewResolver resolver=new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/view/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

UserController

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping(value = "/date",method = RequestMethod.GET)
    public ModelAndView getDate(@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss") Date date)
    {
        System.out.println(date);
        return new ModelAndView("success");
    }

}

前端页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>主页</title>
</head>
<body>
<h1>日期类型</h1>
<form action="/user/date" method="get">
    <p>
        <label for="date">Date:</label>
        <input type="text" id="date" name="date">
    </p>
    <button type="submit">submit</button>
</form>
</body>
</html>

参数乱码

在web的启动类处添加过滤器Filter进行编码设置
SpringMVC入门案例和常用API使用演示

返回参数(等同于servlet中的request.setAttribute(“key”,value))

在servlet里,通过request.setAttribute()在后端设置参数,在前端页面通过ER表达式获取参数的值显示在界面上

但在SpringMVC中有非常多的方式返回参数,然后在前端页面通过ER表达式进行渲染数据

方式1:ModelAndView+ModelAndView.addObject()

代码如下:
前端页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="false" %>
<%--使用ER表达式 引入taglib--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <%--6、前端页面  返回页面--%>
    <title>返回页面</title>
</head>
<body>
    <table>
        <thead>
        <tr>
            <th>id</th>
            <th>name</th>
            <th>age</th>
        </tr>
        </thead>
        <tbody>
        <c:forEach var="user" items="${users}">
            <tr>
                <td>${user.id}</td>
                <td>${user.name}</td>
                <td>${user.age}</td>
            </tr>
        </c:forEach>
        </tbody>
    </table>
</body>
</html>

前端控制器:

@Controller
@RequestMapping("/user")
public class UserController {
    //addObject方式
    @RequestMapping("/find-one")
    public ModelAndView findOne()
    {
        //使用list模拟数据库数据
        List<User> users=new ArrayList<>();
        users.add(new User("1", "小海", 22));
        users.add(new User("2", "小白", 18));
        users.add(new User("3", "zz", 26));
        users.add(new User("4","鲸鱼",28));

        ModelAndView mv=new ModelAndView();
        //相当于request.setAttribute("users",users);
        mv.addObject("users",users);
        //设置返回视图
        mv.setViewName("userView");
        return mv;
    }
}

方式2:ModelAndView+Model.addAttribute()

前端页面与上述一致
前端控制器代码如下:

@Controller
@RequestMapping("/user")
public class UserController {
    //addAtribute方式
    @RequestMapping("/find-two")
    public ModelAndView findTwo(Model model)
    {
        //使用list模拟数据库数据
        List<User> users=new ArrayList<>();
        users.add(new User("1", "小海", 22));
        users.add(new User("2", "小白", 18));
        users.add(new User("3", "zz", 26));
        users.add(new User("4","鲸鱼",28));

        //依然是request.setAttribute("users",users);
        model.addAttribute("users",users);
        //返回视图
        return new ModelAndView("userView","model",model);
    }

}

方式3:ModelAndView+Map

前端页面与上述一致
前端控制器代码如下:

@Controller
@RequestMapping("/user")
public class UserController {
  
    //ModelAndView+Map
    @RequestMapping("/find-three")
    public ModelAndView findThree(Map<String, Object> map)
    {
        //使用list模拟数据库数据
        List<User> users=new ArrayList<>();
        users.add(new User("1", "小海", 22));
        users.add(new User("2", "小白", 18));
        users.add(new User("3", "zz", 26));
        users.add(new User("4","鲸鱼",28));
        //将数据放入map
        map.put("users",users);

        //返回视图
        return new ModelAndView("userView",map);
    }

}

方式4:String+Map

前端页面与之前一致
前端控制器代码如下:

@Controller
@RequestMapping("/user")
public class UserController {
  
   //String+Map
    @RequestMapping("/find-four")
    public String findFour(Map<String, Object> model)
    {
        //使用list模拟数据库数据
        List<User> users=new ArrayList<>();
        users.add(new User("1", "小海", 22));
        users.add(new User("2", "小白", 18));
        users.add(new User("3", "zz", 26));
        users.add(new User("4","鲸鱼",28));
        //将数据放入map
        model.put("users",users);

        return "userView";
    }

}

方式5:Web原生对象:传递形参(HttpServletRequest,HttpServletResponse)

前端页面代码同上
前端控制器代码如下:

@Controller
@RequestMapping("/user")
public class UserController {
   //Web原生对象 传参
    @RequestMapping("/find-web")
    public String findWeb(HttpServletRequest req, HttpServletResponse resp)
    {
        //使用list模拟数据库数据
        List<User> users=new ArrayList<>();
        users.add(new User("1", "小海", 22));
        users.add(new User("2", "小白", 18));
        users.add(new User("3", "周周", 26));
        users.add(new User("4","鲸鱼",28));

        //使用Web原生对象HttpServletRequest设置参数
        req.setAttribute("users",users);
        return "userView";
    }
}

方式6:Web原生对象:创建ServletRequestAttributes

通过自行创建ServletRequestAttributes对象获取原生参数
前端页面代码同上
前端控制器代码如下:

@Controller
@RequestMapping("/user")
public class UserController {
   //创建ServletRequestAttributes对象
    @RequestMapping("/webObj")
    public String webObj()
    {
        //使用list模拟数据库数据
        List<User> users=new ArrayList<>();
        users.add(new User("1", "周周", 26));
        users.add(new User("2","鲸鱼",28));
        users.add(new User("3", "小海", 22));
        users.add(new User("4", "小白", 18));


        ServletRequestAttributes requestAttributes= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //通过ServletRequestAttributes实例获取参数对象
        //ServletRequestAttributes可以获取HttpServletRequest HttpServletResponse HttpSession对象
        HttpServletRequest req = requestAttributes.getRequest();
        //通过request设置参数
        req.setAttribute("users",users);

        //返回视图
        return "userView";
    }
}

JSON数据处理

核心步骤

  • pom.xml文件中添加json的依赖包
  • WebConfig中添加@EnableWebMvc 并配置不要将静态资源的加载当作请求
  • 在controller层添加注解 @ResponseBody 并编写方法进行传递数据
  • 在前端页面引入jquery并编写Ajax请求

具体实现

  • pom.xml添加的依赖包
<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.12.0-rc2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.0-rc2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.12.0-rc2</version>
        </dependency>
  • WebConfig代码
@ComponentScan("com.dean.controller")
@EnableWebMvc  //一定要添加
public class WebConfig implements WebMvcConfigurer {
    //添加默认请求的视图返回  可以没有
    //即请求/时 返回index.html页面
 @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
    }

    //配置静态资源
    //使加载静态资源时,不被当作请求处理
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}
  • Controller层代码
@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping(value = "/findUser",method = RequestMethod.POST)
    @ResponseBody   //帮助使用HttpServletResponse返回数据
    //采用形参传参,前端页面设置的参数将会传到后端
    public List<User>  findUser(User user)
    {
        //前端Ajax请求的数据
        System.out.println(user);
        //后端发送的数据
        List<User> users=new ArrayList<>();
        users.add(new User("1", "周周", 26));
        users.add(new User("2", "小海", 22));
        users.add(new User("3", "小白", 18));

        return users;
    }
}

  • 前端页面
    前端页面会返回一个包含后端传入数据的表格
<!DOCTYPE html>
<html lang="en">
<head>
    <!--6、编写前端页面-->
    <meta charset="UTF-8">
    <title>主页</title>
    <!--引入jquery-->
    <script src="/static/jquery-2.1.1.js"></script>
</head>
<body>
<h1>Html</h1>
<button onclick=findUser()>findUser</button>
<table id="table">
</table>
<script>
    function findUser() {
        $.ajax({
            url:"/user/findUser",
            method:"post",
            dataType:"json",
            data:{id:4,name:"鲸鱼",age:22},
            success:function (data) {
                //$('#table').empty();  //清空原表格
                $('#table').append("<tr><th>id</th><th>name</th><th>age</th></tr>");
                // let html="<tr><th>id</th><th>name</th><th>age</th></tr>";
                $.each(data,function (i,item) {
                    html="<tr>" +
                            "<td>"+item['id']+"</td>"+
                            "<td>"+item['name']+"</td>"+
                            "<td>"+item['age']+"</td>"+
                        "</tr>"
                    $('#table').append(html);
                });
                // $('#table').html(html);

            }
        })
    }
</script>
</body>
</html>

RestFul请求

将前后端分离,在处理请求时,后端只返回数据(即只提供资源)给前端页面,只渲染数据,不再渲染标签
前端和后端设置不同的端口号,部署在不同的服务器上
RestFul的状态转换(GET POST Delete Put)对应着对于资源的CRUD操作
RestFul中有一个重要的概念:幂等性(即无论请求多少次,资源都是相同的)

核心步骤

  • 在项目的pom.xml中添加依赖
  • 编写Spring MVC的配置类 (核心 @EnableWebMvc
  • 编写前端控制器 UserController,开启同源策略,编写请求 (核心 **@CrossOrigin ** @GetMapping @PostMapping @PutMapping @DeleteMapping@RequestMapping+@ResponseBody )
  • 模拟数据,设计响应数据的格式
  • 编写启动类
  • 使用WebStorm编写前端页面
  • 将前端页面部署到nginx上

具体实现

后端
文件结构
SpringMVC入门案例和常用API使用演示


  • 修改pom.xml
    SpringMVC入门案例和常用API使用演示
  • SpringMvc配置类
@ComponentScan("com.dean.controller")
@EnableWebMvc
public class WebConfig {
}
  • 前端控制器
    添加的注释
    SpringMVC入门案例和常用API使用演示

Get请求
@Controller+@ResponseBody版本

//Get请求
    //url: /user/1 (查询id=1的用户信息)
    //响应类型: application/json
    //返回数据:{"id":1,"name":"string","age":int}
      @RequestMapping(value = "{id}",method = RequestMethod.GET)
      @ResponseBody
    public ResultEntity getUserById(@PathVariable(value = "id") String id)
    {
        //从数据库请求数据
        User user=users.get(id);
        return new ResultEntity(200,"ok",true,user);
    }

@RestController版本

//Get请求
    //url: /user/1 (查询id=1的用户信息)
    //响应类型: application/json
    //返回数据:{"id":1,"name":"string","age":int}
    @GetMapping("{id}")  //等同于@RequestMapping(value = "{id}",method = RequestMethod.GET)
    public ResultEntity getUserById(@PathVariable(value = "id") String id)
    {
        //从数据库请求数据
        User user=users.get(id);
        return new ResultEntity(200,"ok",true,user);
    }

Post请求
@Controller+@ResponseBody版本

//Post请求
    //url: /user   新增一个用户
    //参数类型:application/json
    //参数: {"id":1,"name":"string","age":int} 自动装箱
    //响应类型:application/json
    //响应数据:{}
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public ResultEntity addUser(@RequestBody User user)
    {
        users.put(user.getId(),user);
        System.out.println(user);
        return new ResultEntity(200,"ok",true,null);
    }

@RestController版本

//Post请求
    //url: /user   新增一个用户
    //参数类型:application/json
    //参数: {"id":1,"name":"string","age":int} 自动装箱
    //响应类型:application/json
    //响应数据:{}
    @PostMapping
    public ResultEntity addUser(@RequestBody User user)
    {
        users.put(user.getId(),user);
        System.out.println(user);
        return new ResultEntity(200,"ok",true,null);
    }

Put请求
@Controller+@ResponseBody版本

//Put请求
    //url: /user/1  修改id=1的用户信息
    //参数类型:application/json
    //参数格式:{"name":"string","age":int}
    //响应类型:application/json
    //响应数据:{}
    @RequestMapping(value = "{id}",method = RequestMethod.PUT)
    @ResponseBody
    public ResultEntity updateUser(@PathVariable String id,@RequestBody User user)
    {
        user.setId(id);
        users.put(id,user);
        System.out.println(users);
        return new ResultEntity(200,"update success",true,"{}");
    }

@RestController版本

//Put请求
    //url: /user/1  修改id=1的用户信息
    //参数类型:application/json
    //参数格式:{"name":"string","age":int}
    //响应类型:application/json
    //响应数据:{}
    @PutMapping("{id}")
    public ResultEntity updateUser(@PathVariable String id,@RequestBody User user)
    {
        user.setId(id);
        users.put(id,user);
        System.out.println(users);
        return new ResultEntity(200,"update success",true,"{}");
    }

Delete请求
@Controller+@ResponseBody版本

//Delete请求
    //url: /user/1 删除id=1的用户
    //响应类型:application/json
    //响应数据:{}
    @RequestMapping(value = "{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public ResultEntity delUser(@PathVariable(value = "id") String uid)
    {
        users.remove(uid);
        return new ResultEntity(200,"delete success",true,"{}");
    }

@RestController版本

//Delete请求
    //url: /user/1 删除id=1的用户
    //响应类型:application/json
    //响应数据:{}
    @DeleteMapping("{id}") //等同于@RequestMapping(value = "{id}",method = RequestMethod.DELETE)
    public ResultEntity delUser(@PathVariable(value = "id") String uid)
    {
        users.remove(uid);
        return new ResultEntity(200,"delete success",true,"{}");
    }
  • 模拟数据User 设计响应数据格式
    User
public class User {
    private String id;
    private String name;
    private Integer age;

    public User() {
    }

    public User(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

响应数据格式(仿照http的响应数据格式)

/**
 * {
 *     "code":200,  状态码
 *     "message":"string",  提示信息
 *     "flag":"boolean",   执行状况
 *     "data":"object(json)"  数据
 * }
 */
public class
ResultEntity {
    private Integer code;
    private String message;
    private Boolean flag;
    private Object data;

    public ResultEntity() {

    }

    public ResultEntity(Integer code, String message, Boolean flag, Object data) {
        this.code = code;
        this.message = message;
        this.flag = flag;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Boolean getFlag() {
        return flag;
    }

    public void setFlag(Boolean flag) {
        this.flag = flag;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}
  • 启动类
public class WebServerInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

前端

  • 引入vue.js和jquery.js
    SpringMVC入门案例和常用API使用演示
  • 编写前端界面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
    <!--引入jquery和vue-->
    <script src="./static/vue.js"></script>
    <script src="./static/jquery-2.1.1.js"></script>
</head>
<body>
<div id="app">
    <!--显示所有用户-->
    <table style="width: 500px;text-align: center;border-color: cornflowerblue" border="1">
        <thead>
        <tr>
            <th>id</th>
            <th>name</th>
            <th>age</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="user in users" :key="user.id">
            <td>{{user.id}}</td>
            <td>{{user.name}}</td>
            <td>{{user.age }}</td>
        </tr>
        </tbody>
    </table>
    <!--新增用户-->
    <div id="add-user">
        <p>
            <label for="add-user-id">id:</label>
            <input type="text" id="add-user-id" v-model="addUser.id">
        </p>
        <p>
            <label for="add-user-name">name:</label>
            <input type="text" id="add-user-name" v-model="addUser.name">
        </p>
        <p>
            <label for="add-user-age">age:</label>
            <input type="text" id="add-user-age" v-model="addUser.age">
        </p>
        <button @click="_addUser()">addUser</button>
        <button @click="_updateUser()">updateUser</button>
    </div>
    <hr>
    <p>
        <label for="del-user-id">id:</label>
        <input type="text" id="del-user-id" v-model="addUser.id">
    </p>
    <button @click="_deleteUser">deleteUser</button>
</div>
<script>
    let vm=new Vue({
        el:"#app",
        data:{
            users:[],
            addUser:{
                id:"",
                name:"",
                age:""
            }
        },
        //生命钩子
        created(){
            //查询所有用户
             this._findAllUsers();
        },
        methods:{
            //查找所有用户
            _findAllUsers(){
                let this_=this;
                //编写ajax请求
                $.ajax({
                    url:"http://localhost:8090/user/",  //请求url
                    method:"get",
                    dataType:"json",   //返回数据格式
                    contentType:"application/json", //网页文件的类型和网页编码格式
                    success:function (resp) {
                        this_.users=resp.data;
                    }
                })
                return null;
            },

            //新增用户
            _addUser(){
                let this_=this;
                //编写ajax请求
                $.ajax({
                    url:"http://localhost:8090/user/",
                    method:"post",
                    data:JSON.stringify(this_.addUser),  //将参数对象转换为Json格式
                    dataType:"json",
                    contentType:"application/json",
                    success:function (resp) {
                        this_._findAllUsers(); //刷新页面
                    }
                })
            },

            //修改用户
            _updateUser(){
                let id=this.addUser.id;
                let user={
                    name:this.addUser.name,
                    age:this.addUser.age
                }
                let this_=this;
                //编写ajax请求
                $.ajax({
                    url:"http://localhost:8090/user/"+id,
                    method:"put",
                    data:JSON.stringify(user),  //将参数对象转换为Json格式
                    dataType:"json",
                    contentType:"application/json",
                    success:function (resp) {
                        this_._findAllUsers(); //刷新页面
                    }
                })
            },

            //删除用户
            _deleteUser()
            {
                let id=this.addUser.id;
                let this_=this;
                //编写ajax请求
                $.ajax({
                    url:"http://localhost:8090/user/"+id,
                    method:"delete",
                    data:JSON.stringify(this_.addUser),  //将参数对象转换为Json格式
                    dataType:"json",
                    contentType:"application/json",
                    success:function (resp) {
                        this_._findAllUsers(); //刷新页面
                    }
                })
            }
        }
    })
</script>
</body>
</html>
  • 将页面部署在nginx上
    即将页面和static文件复制在nginx的html文件夹里,删除原有的index.html文件

统一异常处理

核心步骤

  • controller里模拟抛出异常
  • 编写统一异常处理器CustomException
  • WebConfig(配置类),WebServerInit(启动类)和之前一致

具体实现

  • Controller
@Controller
@RequestMapping("user")
public class UserController {
    @RequestMapping("main")
    public ModelAndView getMain(String name, Model model)
    {
        if("admin".equals(name))
        {
        	//模拟抛出异常
            throw new RuntimeException("不能使用admin登录");
        }
        model.addAttribute("name",name);
        return new ModelAndView("main");
    }
}
  • 统一异常处理器CustomException
@ControllerAdvice
public class CustomException {
    //指定处理RuntimeException类的异常
    @ExceptionHandler(RuntimeException.class)
    public ModelAndView exception (Exception e, Model model)
    {
        System.out.println(e.getMessage());
        model.addAttribute("message",e.getMessage());
        return new ModelAndView("error");
    }

}

拦截器

Filter:过滤器 过滤的是url
intercepter:拦截器 面向方法的代理模式
主要是WebConfig和自定义的拦截器UserInterceptor

  • WebConfig
@ComponentScan("com.dean.controller")
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    //添加视图解析器
    @Bean
    public InternalResourceViewResolver viewResolver()
    {
        InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/view/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    //配置静态资源
    //相当于xml中的<mvc:default-servlet-handler>
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }


    //添加拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //创建一个自定义的拦截器,加入容器
        registry.addInterceptor(new UserInterceptor());
    }
}

  • UserInterceptor
public class UserInterceptor implements HandlerInterceptor {

    //controller目标方法之前执行
    //适合做权限的控制
    //形参Object handler实际指的是目标方法对象
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod method= (HandlerMethod) handler;
        //method.getMethod().getName() 获取到目标方法名
        System.out.println("目标方法执行前"+method.getMethod().getName());
        return true;
    }

    //controller目标方法成功执行之后执行
    //适合做日志的管理
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //modelAndView.getViewName()  获取到返回的页面名
        System.out.println("目标方法成功执行之后"+modelAndView.getViewName());
    }

    //最终方法,目标方法执行结束后(不论是否抛出异常)
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //ex.getMessage() 获取到异常信息
        System.out.println("目标方法执行之后"+ex.getMessage());
    }
}

Struts2

SpringMvc是基于方法开发的,较快,通过形参传参,可以进行单例开发
Struts2是基于类开发的,较慢,通过类的成员变量传参,无法进行单例开发

虽然很少有人用,但了解还是要了解的

核心步骤

  • pom.xml中添加依赖
  • 编写配置类web.xml
  • 编写核心类Action
  • 编写核心文件,配置请求返回视图,struts.xml
  • 编写前端页面

具体实现

  • pom.xml中添加依赖
    SpringMVC入门案例和常用API使用演示

  • 编写配置类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_3_1.xsd"
         version="3.1">
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

  • 编写核心类Action
public class UserAction {
    //基于类的编程 参数通过成员变量传递
    public String message;

    public void setMessage(String message) {
        this.message = message;
    }

    public String hello()
    {
        System.out.println(message);
        return "SUCCESS";
    }

    public String login()
    {
        if("admin".equals(message))
            return "ERROR";
        return "SUCCESS";
    }

}

  • 编写核心文件,配置请求返回视图,struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
        "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
    <!-- 请求参数的编码方式 -->
    <constant name="struts.i18n.encoding" value="utf-8"/>
    <package name="USER" extends="struts-default" namespace="/user"> <!--请求由namespace和name拼接组成-->
        <action name="hello" class="com.dean.action.UserAction" method="hello">  <!--和action中的方法对应-->
            <result name="SUCCESS">/main.jsp</result>   <!--配置返回页面-->
        </action>
        <action name="login" class="com.dean.action.UserAction" method="login">
            <result name="SUCCESS">/main.jsp</result>
            <result name="ERROR">/error.jsp</result>
        </action>
    </package>
</struts>    
  • 编写前端页面
    index首页
    SpringMVC入门案例和常用API使用演示
    成功返回页面
    SpringMVC入门案例和常用API使用演示
    发生错误后返回的页面
    SpringMVC入门案例和常用API使用演示

本文地址:https://blog.csdn.net/Dean_xiu/article/details/109750409

相关标签: 框架 springmvc