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

SpringMVC入门案例

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

文件结构

在这里插入图片描述

步骤概述

  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目录下,在该目录下的视图只能从内部访问,而无法从外部直接访问
改进后的文件结构如下:
在这里插入图片描述

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

@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进行编码设置
在这里插入图片描述

返回参数(等同于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上
具体实现

后端
文件结构
在这里插入图片描述


  • 修改pom.xml
    在这里插入图片描述
  • SpringMvc配置类
@ComponentScan("com.dean.controller")
@EnableWebMvc
public class WebConfig {
}
  • 前端控制器
    添加的注释
    在这里插入图片描述

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
    在这里插入图片描述
  • 编写前端界面
<!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中添加依赖
    在这里插入图片描述

  • 编写配置类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首页
    在这里插入图片描述
    成功返回页面
    在这里插入图片描述
    发生错误后返回的页面
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值