SpringMVC学习笔记

2023-11-10

springMVC简单入门

快速搭建

pom.xml依赖

  <!-- 导入坐标 springmvc 与 servlet -->
  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.8.RELEASE</version>
    </dependency>

表现层控制类:springmvc\src\main\java\com\mercurows\controller\UserController.java

package com.mercurows.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

// 2.定义controller
// 2.1使用@Controller定义bean
@Controller
// 资源访问前缀
@RequestMapping("/user")
public class UserController {
    // 2.2设置当前操作的访问路径
    @RequestMapping("/save")
    // 2.3设置当前操作的返回值类型
    @ResponseBody
    // 当拦截到"/save"路径时就执行下面的save方法
    public String save() {
        System.out.println("user save .. ");
        // 将响应信息返回给浏览器
        return "{'module':'springmvc'}";
    }
}

springmvc配置类:springmvc\src\main\java\com\mercurows\config\SpringMvcConfig.java

package com.mercurows.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

// 3.创建springmvc的配置文件,加载controller对应的bean
@Configuration
@EnableWebMvc
@ComponentScan("com.mercurows.controller")
public class SpringMvcConfig {
}

这里需要知道的是,springmvc扫描相关的bean例如表现层bean;spring扫描相关的bean例如业务bean service,功能bean DataSource。

springmvc\src\main\java\com\mercurows\config\ServletContainersInitConfig.java

package com.mercurows.config;

import org.springframework.lang.Nullable;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

// // 如何让Tomcat启动时知道spring的配置类在哪里?就要继承下面的类
// // 4.定义一个servlet容器启动的配置类,在里面加载spring的配置
// public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer{

//     // 加载springMVC容器配置
//     @Override
//     protected WebApplicationContext createServletApplicationContext() {
//         AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
//         ctx.register(SpringMvcConfig.class);
//         return ctx;
//     }

//     // 设置那些请求归属springMVC处理
//     @Override
//     protected String[] getServletMappings() {
//         // 所有请求
//         return new String[] {"/"};
//     }

//     // 加载spring容器配置
//     @Override
//     @Nullable
//     protected WebApplicationContext createRootApplicationContext() {
//         return null;
//     }

// }

// 是上面的简化开发版本
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { SpringMvcConfig.class };
    }
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }
}

这样简单的springmvc项目就搭建完毕了。在浏览器中输入:http://localhost:8080/springmvc/user/save 即可在后台控制端看到相关输出:user save ..


请求

get&post的参数传递

为解决post中文参数乱码问题,对文件springmvc\src\main\java\com\mercurows\config\ServletContainersInitConfig.java进行修改

package com.mercurows.config;

import org.springframework.lang.Nullable;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

// 简化开发版本
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { SpringMvcConfig.class };
    }

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

    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    // 处理post中文参数乱码问题
    @Override
    @Nullable
    protected javax.servlet.Filter[] getServletFilters() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        return new javax.servlet.Filter[] { filter };
    }
}

五种参数类型传递

springmvc\src\main\java\com\mercurows\controller\UserController.java

package com.mercurows.controller;

import java.util.Arrays;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mercurows.domain.Book;
import com.mercurows.domain.User;

// 2.定义controller
// 2.1使用@Controller定义bean
@Controller
// 资源访问前缀
@RequestMapping("/user")
public class UserController {
    // 2.2设置当前操作的访问路径
    @RequestMapping("/save")
    // 2.3设置当前操作的返回值类型
    @ResponseBody
    // 当拦截到"/save"路径时就执行下面的save方法
    public String save() {
        System.out.println("user save .. ");
        // 将响应信息返回给浏览器
        return "{'module':'springmvc'}";
    }

    // 普通参数
    @RequestMapping("/commonParam")
    @ResponseBody
    // 与mybatis中一样,这里加上@RequestParam注解
    // 当前端传入的名称为username时就可指定用name参数接受
    // 这里默认前端传的第二个名称为age
    public String commonParam(@RequestParam("username") String name, int age) {
        System.out.println("普通参数传递 name ==> " + name);
        System.out.println("普通参数传递 name ==> " + age);
        return "{'module':'conmmon param'}";
    }

    // POJO参数
    // 前端传入的参数名称与User成员变量的名称一样时
    // 这里为:name 与 age
    // 这些接收到的变量就会自动set进User类里面当成员变量
    @RequestMapping("/pojoParam")
    @ResponseBody
    public String pojoParam(User user) {
        System.out.println("pojo参数传递 user ==> " + user);
        return "{'module':'pojo param'}";
    }

    // 嵌套POJO参数
    // 思路与上面的一致,只不过这里对于嵌套的成员类而言
    // 前端传参时需要:user.age user.name 这样传
    @RequestMapping("/pojoContainPojoParam")
    @ResponseBody
    public String pojoContainPojoParam(Book book) {
        System.out.println("pojo嵌套pojo参数传递 book ==> " + book);
        return "{'module':'pojo contain pojo param'}";
    }

    // 数组参数
    // 前端参数传递时,需要确保传入的参数名称都为likes
    // 这样这些全部名为likes的参数都会被放到likes的数组里面
    @RequestMapping("/arrayParam")
    @ResponseBody
    public String arrayParam(String[] likes) {
        System.out.println("数组参数传递 likes ==> " + Arrays.toString(likes));
        return "{'module':'array param'}";
    }

    // 集合参数
    // 这里默认将List当成pojo并将前端的传入的参数当成其成员变量塞进去
    // 但是List里面的成员变量是length这样之类的属性
    // 因此正确的处理方式是将外面的数据作为集合里面的参数数据而非集合的属性出现
    // 所以需要在前面添加@RequestParam注解将前端的数据当成参数放到集合里面
    @RequestMapping("/listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String> likes) {
        System.out.println("集合参数传递 likes ==> " + likes);
        return "{'module':'list param'}";
    }
}

JSON格式数据传递

pojo类

springmvc\src\main\java\com\mercurows\domain\User.java

package com.mercurows.domain;

public class User {
    private String name;
    private int age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }
}

springmvc\src\main\java\com\mercurows\domain\Book.java

package com.mercurows.domain;

public class Book {
    private User user;
    private int id;
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Override
    public String toString() {
        return "Book [user=" + user + ", id=" + id + "]";
    }
}

springmvc\src\main\java\com\mercurows\controller\UserController.java

package com.mercurows.controller;

import java.util.Arrays;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mercurows.domain.Book;
import com.mercurows.domain.User;

// 2.定义controller
// 2.1使用@Controller定义bean
@Controller
// 资源访问前缀
@RequestMapping("/user")
public class UserController {
    // 2.2设置当前操作的访问路径
    @RequestMapping("/save")
    // 2.3设置当前操作的返回值类型
    @ResponseBody
    // 当拦截到"/save"路径时就执行下面的save方法
    public String save() {
        System.out.println("user save .. ");
        // 将响应信息返回给浏览器
        return "{'module':'springmvc'}";
    }

    // 普通参数
    @RequestMapping("/commonParam")
    @ResponseBody
    // 与mybatis中一样,这里加上@RequestParam注解
    // 当前端传入的名称为username时就可指定用name参数接受
    // 这里默认前端传的第二个名称为age
    public String commonParam(@RequestParam("username") String name, int age) {
        System.out.println("普通参数传递 name ==> " + name);
        System.out.println("普通参数传递 name ==> " + age);
        return "{'module':'conmmon param'}";
    }

    // POJO参数
    // 前端传入的参数名称与User成员变量的名称一样时
    // 这里为:name 与 age
    // 这些接收到的变量就会自动set进User类里面当成员变量
    @RequestMapping("/pojoParam")
    @ResponseBody
    public String pojoParam(User user) {
        System.out.println("pojo参数传递 user ==> " + user);
        return "{'module':'pojo param'}";
    }

    // 嵌套POJO参数
    // 思路与上面的一致,只不过这里对于嵌套的成员类而言
    // 前端传参时需要:user.age user.name 这样传
    @RequestMapping("/pojoContainPojoParam")
    @ResponseBody
    public String pojoContainPojoParam(Book book) {
        System.out.println("pojo嵌套pojo参数传递 book ==> " + book);
        return "{'module':'pojo contain pojo param'}";
    }

    // 数组参数
    // 前端参数传递时,需要确保传入的参数名称都为likes
    // 这样这些全部名为likes的参数都会被放到likes的数组里面
    @RequestMapping("/arrayParam")
    @ResponseBody
    public String arrayParam(String[] likes) {
        System.out.println("数组参数传递 likes ==> " + Arrays.toString(likes));
        return "{'module':'array param'}";
    }

    // 集合参数
    // 这里默认将List当成pojo并将前端的传入的参数当成其成员变量塞进去
    // 但是List里面的成员变量是length这样之类的属性
    // 因此正确的处理方式是将外面的数据作为集合里面的参数数据而非集合的属性出现
    // 所以需要在前面添加@RequestParam注解将前端的数据当成参数放到集合里面
    @RequestMapping("/listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String> likes) {
        System.out.println("集合参数传递 likes ==> " + likes);
        return "{'module':'list param'}";
    }

    // 集合参数:json格式
    // 与上面集合类型一样都需要添加参数注解
    // 不过由于json的数据是在请求体里面的所以要添加的是@RequestBody
    @RequestMapping("/listParamForJson")
    @ResponseBody
    public String listParamForJson(@RequestBody List<User> likes) {
        System.out.println("list commmon(json)参数传递 list ==> " + likes);
        return "{'module':'list common for json param'}";
    }

    // POJO参数:json格式
    @RequestMapping("/pojoParamForJson")
    @ResponseBody
    public String pojoParamForJson(@RequestBody Book book) {
        System.out.println("pojo(json)传递参数 book ==> " + book);
        return "{'module':'pojo for json param'}";
    }
}

// 普通参数

image-20230807090725066

// POJO参数

image-20230807090916891

// 嵌套POJO参数

image-20230807091235772

// 数组参数

image-20230807091427222

//集合参数

image-20230807091718312

// 集合参数:json格式

image-20230807091830436

// POJO参数:json格式

image-20230807092144570

响应

springmvc\src\main\java\com\mercurows\controller\UserController.java

package com.mercurows.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mercurows.domain.Book;
import com.mercurows.domain.User;

@Controller
@RequestMapping("/user")
public class UserController {
    // 响应格式↓↓↓↓↓↓↓↓

    // 响应页面/跳转页面
    @RequestMapping("/toJumpPage")
    public String toJumpPage() {
        System.out.println("跳转页面");
        return "redirect:/page.jsp";
    }

    // 响应文本数据
    @RequestMapping("/toText")
    // 添加@ResponseBody注释说明返回的是String而不是页面
    @ResponseBody
    public String toText() {
        System.out.println("返回纯文本数据");
        return "response text";
    }

    // 响应pojo对象
    @RequestMapping("/toJsonPOJO")
    @ResponseBody
    public User toJsonPOJO() {
        System.out.println("返回json对象数据");
        User user = new User();
        user.setName("mercurows");
        user.setAge(15);
        return user;
    }

    // 响应pojo集合对象
    @RequestMapping("/toJsonList")
    @ResponseBody
    public List<User> toJsonList() {
        System.out.println("返回json集合数据");
        User user1 = new User();
        user1.setName("AAA");
        user1.setAge(11);

        User user2 = new User();
        user2.setName("BBB");
        user2.setAge(22);

        List<User> userList = new ArrayList<>();
        userList.add(user1);
        userList.add(user2);

        return userList;
    }
}

REST风格

image-20230807213642724

springmvc\src\main\java\com\mercurows\domain\Brand.java

package com.mercurows.domain;

public class Brand {
    private int id;
    private String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Brand [id=" + id + ", name=" + name + "]";
    }
}

springmvc\src\main\java\com\mercurows\controller\BrandController.java

package com.mercurows.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mercurows.domain.Brand;

@Controller
public class BrandController {

    // 1.设定http的请求动作:method =
    @RequestMapping(value = "/brands",method = RequestMethod.POST)
    @ResponseBody
    public String save() {
        System.out.println("brand save... ");
        return "{'module':'brand save'}";
    }

    // 传入参数形式:1.后面value中的{}加上对应方法形参
    // 2.由于地址参数并不是id=这样的格式,所以方法不是加上注解@RequestParam而是加上@PathVariable
    @RequestMapping(value = "/brands/{id}" ,method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable Integer id) {
        System.out.println("brand delete.. " + id);
        return "{'module':'brand delete'}";
    }

    // 引用对象使用RequestBody注解
    @RequestMapping(value = "/brands",method = RequestMethod.PUT)
    @ResponseBody
    public String update(@RequestBody Brand brand) {
        System.out.println("brand update.." + brand);
        return "{'module':'brand update'}";
    }

    @RequestMapping(value = "/brands/{id}",method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable Integer id) {
        System.out.println("brand getById.." + id);
        return "{'module':'brand getById'}";
    }

    @RequestMapping(value = "/brands",method = RequestMethod.GET)
    @ResponseBody
    public String getAll() {
        System.out.println("brand getAll..");
        return "{'module':'brand getAll'}";
    }
}

REST简化开发

上面的REST代码有许多重复的部分,因此可以将其提取出来放到类名前面

springmvc\src\main\java\com\mercurows\controller\BrandController.java

package com.mercurows.controller;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.mercurows.domain.Brand;

// rest风格简化↓↓↓ 将公共部分提取出来放到类前面
// 例如方法前面都有@ResponseBody,可以提出来
// 注意:如果原本没有该注解的,在类前面写上这个注解则会报错
// @ResponseBody
// @Controller
// @RestController合并了:@ResponseBody与@Controller
@RestController
// 由于前面都有这个所以可以提取出来,但是参数格式得要保留:/{id}
@RequestMapping("/brands")
public class BrandController {

    // 1.设定http的请求动作:method =
    // @RequestMapping(value = "/brands",method = RequestMethod.POST)
    // 上面方法的简化
    @PostMapping
    public String save() {
        System.out.println("brand save... ");
        return "{'module':'brand save'}";
    }

    // 传入参数形式:1.后面value中的{}加上对应方法形参
    // 2.由于地址参数并不是id=这样的格式,所以方法不是加上注解@RequestParam而是加上@PathVariable
    // @RequestMapping(value = "/{id}" ,method = RequestMethod.DELETE)
    @DeleteMapping(value = "/{id}")
    public String delete(@PathVariable Integer id) {
        System.out.println("brand delete.. " + id);
        return "{'module':'brand delete'}";
    }

    // 引用对象使用RequestBody注解
    // @RequestMapping(method = RequestMethod.PUT)
    @PutMapping
    public String update(@RequestBody Brand brand) {
        System.out.println("brand update.." + brand);
        return "{'module':'brand update'}";
    }

    // @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    @GetMapping("/{id}")
    public String getById(@PathVariable Integer id) {
        System.out.println("brand getById.." + id);
        return "{'module':'brand getById'}";
    }

    // @RequestMapping(method = RequestMethod.GET)
    @GetMapping
    public String getAll() {
        System.out.println("brand getAll..");
        return "{'module':'brand getAll'}";
    }
}

异常处理

Spring MVC的异常处理思想是将异常处理的职责从业务逻辑和数据层转移到控制层,以提供更好的用户体验和错误处理机制。

springmvc_ssm\src\main\java\com\mercurows\controller\Code.java

package com.mercurows.controller;

//错误代码
public class Code {
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;

    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;

    public static final Integer SYSTEM_ERR = 50001;
    public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
    public static final Integer SYSTEM_UNKNOW_ERR = 59999;

    public static final Integer BUSINESS_ERR = 60002;

}

自定义结果:前后端协议

springmvc_ssm\src\main\java\com\mercurows\controller\Result.java

package com.mercurows.controller;

public class Result {
    private Object data; // 数据
    private Integer code; // 状态码
    private String msg; // 出错时的信息

    public Result(Integer code, Object data, String msg) {
        this.data = data;
        this.code = code;
        this.msg = msg;
    }

    public Result(Integer code, Object data) {
        this.data = data;
        this.code = code;
    }

    public Result() {
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

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

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

}

控制层中对自定义异常类的处理类:

springmvc_ssm\src\main\java\com\mercurows\controller\ProjectExceptionAdvice.java

package com.mercurows.controller;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.mercurows.exception.BusinessException;
import com.mercurows.exception.SystemException;

// 处理异常类
@RestControllerAdvice
public class ProjectExceptionAdvice {
    // 定义当前类是用来处理异常的
    @ExceptionHandler(SystemException.class)
    public Result doSystemException(SystemException ex) {
        // 记录日志
        // 发送消息给运维
        // 发送邮件給开发人员

        // 规范统一结果
        return new Result(ex.getCode(), null, ex.getMessage());
    }

    @ExceptionHandler(BusinessException.class)
    public Result doBusinessException(BusinessException ex) {
        // 规范统一结果
        return new Result(ex.getCode(), null, ex.getMessage());
    }

    // 处理第三方异常
    @ExceptionHandler(Exception.class)
    public Result doException(Exception ex) {
        // 规范统一结果
        return new Result(Code.SYSTEM_UNKNOW_ERR, null, "捕获到异常");
    }
}
//SystemException 与 BusinessException为自定义异常类

自定义异常类

springmvc_ssm\src\main\java\com\mercurows\exception\BusinessException.java

package com.mercurows.exception;

public class BusinessException extends RuntimeException {
    private Integer code;

    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

    public Integer getCode() {
        return code;
    }

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

}

springmvc_ssm\src\main\java\com\mercurows\exception\SystemException.java

package com.mercurows.exception;

public class SystemException extends RuntimeException {
    private Integer code;

    public SystemException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public SystemException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

    public Integer getCode() {
        return code;
    }

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

}

在业务层模拟的异常就会被打包成自定义的异常发送给控制层处理

springmvc_ssm\src\main\java\com\mercurows\service\impl\StudentServiceImpl.java

package com.mercurows.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mercurows.controller.Code;
import com.mercurows.dao.StudentDao;
import com.mercurows.domain.Student;
import com.mercurows.exception.BusinessException;
import com.mercurows.exception.SystemException;
import com.mercurows.service.StudentService;

@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    StudentDao studentDao;

    @Override
    public Student getById(Integer id) {
        // 模拟异常
        if (id == 1) {
            //打包成自定义的类
            throw new BusinessException(Code.BUSINESS_ERR, "系统繁忙,请稍后重试");
        }
        try{
            int i = 1/0;
        } catch (Exception e) {
            //打包成自定义的类
            throw new SystemException(Code.SYSTEM_TIMEOUT_ERR, "服务器访问超时,请重试", e);
        }
        return studentDao.getById(id);
    }
}

拦截器

拦截器与过滤器的区别

  • 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术
  • 拦截内容不同:Filter对所有访问进行增强,Interceptor仅对SpringMVC访问进行增强

springmvc_ssm\src\main\java\com\mercurows\config\SpringMvcSupport.java

package com.mercurows.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import com.mercurows.controller.interceptor.ProjectInterceptor;

// 此类需要SpringMvcConfig类ComponentScan扫描到
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Autowired
    private ProjectInterceptor projectInterceptor;

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    }

    // 配置拦截器
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(projectInterceptor).addPathPatterns("/sudents", "/students/**");
		//这里的/sudents是StudentController.java里的资源访问前缀
        // 表示路径后面最后为/sudents或是包含/students之后的任意内容都将会被拦截器拦截
        // 别忘了要让SpringMvcConfig扫描ComponentScan加载该文件
    }
}

springmvc_ssm\src\main\java\com\mercurows\config\SpringMvcConfig.java

package com.mercurows.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@ComponentScan("com.mercurows.config" )
// 扫描config文件夹是为了扫描到:SpringMvcSupport文件
@EnableWebMvc
public class SpringMvcConfig {
}

springmvc_ssm\src\main\java\com\mercurows\controller\interceptor\ProjectInterceptor.java

package com.mercurows.controller.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

// 使其受是springMVC管理,能让springmvc加载该类
@Component
public class ProjectInterceptor implements HandlerInterceptor {

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
            @Nullable Exception ex) throws Exception {
                System.out.println("afterCompletion");
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            @Nullable ModelAndView modelAndView) throws Exception {
                System.out.println("postHandle");
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 获取请求头
        String contenType = request.getHeader("Content-Type");
        // 获取调用的方法
        HandlerMethod hm = (HandlerMethod) handler;
        System.out.println("preHandle==>" + contenType + hm);
        return true;
        // 如果是false,将终止原始操作
        // 只会执行preHandle方法,而postHandle与afterCompletion都不会执行
    }
}

springmvc_ssm\src\main\java\com\mercurows\controller\StudentController.java

package com.mercurows.controller;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.mercurows.domain.Student;
import com.mercurows.service.StudentService;

@RestController
@RequestMapping("/students")
public class StudentController {
    @Autowired
    StudentService studentService;

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        boolean flag = studentService.delete(id);
        return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, flag);
    }

    @GetMapping
    public Result getAll() {
        List<Student> students = studentService.getAll();
        Integer code = students == null ? Code.GET_ERR : Code.GET_OK;
        String msg = students == null ? "数据错误,请重试" : "";
        return new Result(code, students, msg);
    }

    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id) {
        // int i = 1 / 0;
        Student student = studentService.getById(id);
        Integer code = student == null ? Code.GET_ERR : Code.GET_OK;
        String msg = student == null ? "数据错误,请重试" : "";
        System.out.println(student);
        return new Result(code, student, msg);
    }

    @PostMapping
    public Result save(@RequestBody Student student) {
        boolean flag = studentService.save(student);
        return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, flag);
    }

    @PutMapping
    public Result update(@RequestBody Student student) {
        boolean flag = studentService.update(student);
        return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR, flag);
    }
}

SpringMVC整合SSM

MVC

pom.xml依赖

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.1</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.8.RELEASE</version>
    </dependency>

    <!-- spring单元测试 -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.2.8.RELEASE</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.8.RELEASE</version>
    </dependency>

  <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
  </dependency>

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.6</version>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.30</version>
    </dependency>

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.16</version>
    </dependency>

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>

    <!-- 导入jason的包 -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.15.2</version>
    </dependency>
  </dependencies>

Spring配置部分

springmvc_ssm\src\main\java\com\mercurows\config\JdbcConfig.java

package com.mercurows.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;

public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userNaem;
    @Value("${jdbc.password}")
    private String passWord;

    @Bean
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(userNaem);
        dataSource.setPassword(passWord);
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager dstm = new DataSourceTransactionManager(dataSource);
        return dstm;
    }
}

springmvc_ssm\src\main\java\com\mercurows\config\MyBatisConfig.java

package com.mercurows.config;

import javax.sql.DataSource;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;

public class MyBatisConfig {

    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setTypeAliasesPackage("com.mercurows.domain");
        return sessionFactoryBean;
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.mercurows.dao");
        return msc;
    }
}

springmvc_ssm\src\main\java\com\mercurows\config\Springconfig.java

package com.mercurows.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@ComponentScan({ "com.mercurows.service" })
@PropertySource("classpath:jdbc.properties")
@Import({ JdbcConfig.class, MyBatisConfig.class })
@EnableTransactionManagement

public class Springconfig {
}

springmvc_ssm\src\main\resources\jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/jdbc
jdbc.username=root
jdbc.password=5508769123

Servlet配置部分

Servlet和Spring MVC DispatcherServlet的配置

springmvc_ssm\src\main\java\com\mercurows\config\ServletConfig.java

package com.mercurows.config;

import org.springframework.lang.Nullable;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer{

    @Override
    @Nullable
    protected Class<?>[] getRootConfigClasses() {
        // 根配置
        return new Class[] { Springconfig.class };
    }

    @Override
    @Nullable
    protected Class<?>[] getServletConfigClasses() {
        // web请求专门配置
        // SpringMvcConfig容器可以访问Springconfig的容器反之不行
        return new Class[] { SpringMvcConfig.class };
    }

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

    // 处理post中文参数乱码问题
    protected javax.servlet.Filter[] getServletFilters() {
        CharacterEncodingFilter filter = new CharacterEncodingFilter();
        filter.setEncoding("UTF-8");
        return new javax.servlet.Filter[] { filter };
    }
}

SpringMVC配置部分

springmvc_ssm\src\main\java\com\mercurows\config\SpringMvcConfig.java

package com.mercurows.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@ComponentScan({ "com.mercurows.controller", "com.mercurows.config" })
// 扫描config文件夹是为了扫描到:SpringMvcSupport文件
@EnableWebMvc
public class SpringMvcConfig {
}

拦截器,资源处理

springmvc_ssm\src\main\java\com\mercurows\config\SpringMvcSupport.java

package com.mercurows.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import com.mercurows.controller.interceptor.ProjectInterceptor;

// 此类需要SpringMvcConfig类ComponentScan扫描到
@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {
    @Autowired
    private ProjectInterceptor projectInterceptor;

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 设置放行路径:让tomcat管理而不是让mvc拦截
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");

    }

    // 配置拦截器
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(projectInterceptor).addPathPatterns("/sudents", "/students/**");
        // 表示路径后面最后为/sudents或是包含/students之后的任意内容都将会被拦截器拦截
        // 别忘了要让SpringMvcConfig扫描ComponentScan加载该文件
    }
}

数据层

springmvc_ssm\src\main\java\com\mercurows\dao\StudentDao.java

package com.mercurows.dao;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;

import com.mercurows.domain.Student;

public interface StudentDao {

    //返回更新的行数用于判断操作是否失败
    @Insert("insert into student (name_ch,sex,age,name_en) values(#{nameCh},#{sex},#{age},#{nameEn})")
    public int save(Student student);

    @Update("update student set name_ch = #{nameCh}, sex = #{sex}, age = #{age}, name_en = #{nameEn} where id = #{id}")
    public int update(Student student);

    @Delete("delete from student where id = #{id}")
    public int delete(Integer id);

    @Results({
        @Result(property = "nameCh", column = "name_ch"),
        @Result(property = "nameEn", column = "name_en")
        // property:成员变量名字,column:数据库列名
        // 按照类成员变量名和数据库列名的对应关系添加 @Result 注解
    })
    @Select("select * from student where id = #{id}")
    public Student getById(Integer id);

    // 对于变量名与数据库列名不一致的还可以直接用取相同别名的方式
    @Select("select id,name_ch as nameCh,sex,age,name_en as nameEn from student")
    public List<Student> getAll();
}

domain层

springmvc_ssm\src\main\java\com\mercurows\domain\Student.java

package com.mercurows.domain;

public class Student {
    private Integer id;
    private String nameCh;
    private String nameEn;
    private String sex;
    private Integer age;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getNameCh() {
        return nameCh;
    }
    public void setNameCh(String nameCh) {
        this.nameCh = nameCh;
    }
    public String getNameEn() {
        return nameEn;
    }
    public void setNameEn(String nameEn) {
        this.nameEn = nameEn;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "student [id=" + id + ", nameCh=" + nameCh + ", nameEn=" + nameEn + ", sex=" + sex + ", age=" + age
                + "]";
    }
}

数据访问层

springmvc_ssm\src\main\java\com\mercurows\dao\StudentDao.java

package com.mercurows.dao;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;

import com.mercurows.domain.Student;

public interface StudentDao {

    //返回更新的行数用于判断操作是否失败
    @Insert("insert into student (name_ch,sex,age,name_en) values(#{nameCh},#{sex},#{age},#{nameEn})")
    public int save(Student student);

    @Update("update student set name_ch = #{nameCh}, sex = #{sex}, age = #{age}, name_en = #{nameEn} where id = #{id}")
    public int update(Student student);

    @Delete("delete from student where id = #{id}")
    public int delete(Integer id);

    @Results({
        @Result(property = "nameCh", column = "name_ch"),
        @Result(property = "nameEn", column = "name_en")
        // property:成员变量名字,column:数据库列名
        // 按照类成员变量名和数据库列名的对应关系添加 @Result 注解
    })
    @Select("select * from student where id = #{id}")
    public Student getById(Integer id);

    // 对于变量名与数据库列名不一致的还可以直接用取相同别名的方式
    @Select("select id,name_ch as nameCh,sex,age,name_en as nameEn from student")
    public List<Student> getAll();
}

业务逻辑层

springmvc_ssm\src\main\java\com\mercurows\service\StudentService.java

package com.mercurows.service;

import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import com.mercurows.domain.Student;

@Transactional
public interface StudentService {

    // 保存
    public boolean save(Student student);

    // 修改
    public boolean update(Student student);

    // 根据id删除
    public boolean delete(Integer id);

    // 根据id获取
    public Student getById(Integer id);

    // 获取全部
    public List<Student> getAll();
}

springmvc_ssm\src\main\java\com\mercurows\service\impl\StudentServiceImpl.java

package com.mercurows.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mercurows.controller.Code;
import com.mercurows.dao.StudentDao;
import com.mercurows.domain.Student;
import com.mercurows.exception.BusinessException;
import com.mercurows.exception.SystemException;
import com.mercurows.service.StudentService;

@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    StudentDao studentDao;

    @Override
    public boolean delete(Integer id) {
        System.out.println("studentserviceImpl delete ...");
        return studentDao.delete(id) > 0;
    }

    @Override
    public List<Student> getAll() {
        return studentDao.getAll();
    }

    @Override
    public Student getById(Integer id) {
        // 模拟异常
       // if (id == 1) {
       //     throw new BusinessException(Code.BUSINESS_ERR, "系统繁忙,请稍后重试");
      //  }
        // try{
        //     int i = 1/0;
        // } catch (Exception e) {
        //     throw new SystemException(Code.SYSTEM_TIMEOUT_ERR, "服务器访问超时,请重试", e);
        // }
        return studentDao.getById(id);
    }

    @Override
    public boolean save(Student student) {
        return studentDao.save(student) > 0;
    }

    @Override
    public boolean update(Student student) {
        return studentDao.update(student) > 0;
    }
}

表现层

拦截器层

springmvc_ssm\src\main\java\com\mercurows\controller\interceptor\ProjectInterceptor.java

package com.mercurows.controller.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

// 使其受是springMVC管理,能让springmvc加载该类
@Component
public class ProjectInterceptor implements HandlerInterceptor {

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
            @Nullable Exception ex) throws Exception {
                System.out.println("afterCompletion");
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            @Nullable ModelAndView modelAndView) throws Exception {
                System.out.println("postHandle");
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 获取请求头
        String contenType = request.getHeader("Content-Type");
        // 获取调用的方法
        HandlerMethod hm = (HandlerMethod) handler;
        System.out.println("preHandle==>" + contenType + hm);
        return true;
        // 如果是false,将终止原始操作
        // 只会执行preHandle方法,而postHandle与afterCompletion都不会执行
    }
}

控制器层

springmvc_ssm\src\main\java\com\mercurows\controller\Code.java

package com.mercurows.controller;

public class Code {
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;

    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;

    public static final Integer SYSTEM_ERR = 50001;
    public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
    public static final Integer SYSTEM_UNKNOW_ERR = 59999;

    public static final Integer BUSINESS_ERR = 60002;

}

springmvc_ssm\src\main\java\com\mercurows\controller\Result.java

package com.mercurows.controller;

public class Result {
    private Object data; // 数据
    private Integer code; // 状态码
    private String msg; // 出错时的信息

    public Result(Integer code, Object data, String msg) {
        this.data = data;
        this.code = code;
        this.msg = msg;
    }

    public Result(Integer code, Object data) {
        this.data = data;
        this.code = code;
    }

    public Result() {
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

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

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

}

springmvc_ssm\src\main\java\com\mercurows\controller\ProjectExceptionAdvice.java

package com.mercurows.controller;

import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.mercurows.exception.BusinessException;
import com.mercurows.exception.SystemException;

// 处理异常类
@RestControllerAdvice
public class ProjectExceptionAdvice {
    // 定义当前类是用来处理异常的
    @ExceptionHandler(SystemException.class)
    public Result doSystemException(SystemException ex) {
        // 记录日志
        // 发送消息给运维
        // 发送邮件給开发人员

        // 规范统一结果
        return new Result(ex.getCode(), null, ex.getMessage());
    }

    @ExceptionHandler(BusinessException.class)
    public Result doBusinessException(BusinessException ex) {
        // 规范统一结果
        return new Result(ex.getCode(), null, ex.getMessage());
    }

    // 处理第三方异常
    @ExceptionHandler(Exception.class)
    public Result doException(Exception ex) {
        // 规范统一结果
        ex.printStackTrace();
        return new Result(Code.SYSTEM_UNKNOW_ERR, null, "捕获到异常");
    }
}

springmvc_ssm\src\main\java\com\mercurows\controller\StudentController.java

package com.mercurows.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.mercurows.domain.Student;
import com.mercurows.service.StudentService;

@RestController
@RequestMapping("/students")
public class StudentController {
    @Autowired
    StudentService studentService;

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id) {
        boolean flag = studentService.delete(id);
        return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR, flag);
    }

    @GetMapping
    public Result getAll() {
        List<Student> students = studentService.getAll();
        Integer code = students == null ? Code.GET_ERR : Code.GET_OK;
        String msg = students == null ? "数据错误,请重试" : "";
        return new Result(code, students, msg);
    }

    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id) {
        // int i = 1 / 0;
        Student student = studentService.getById(id);
        Integer code = student == null ? Code.GET_ERR : Code.GET_OK;
        String msg = student == null ? "数据错误,请重试" : "";
        System.out.println(student);
        return new Result(code, student, msg);
    }

    @PostMapping
    public Result save(@RequestBody Student student) {
        boolean flag = studentService.save(student);
        return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR, flag);
    }

    @PutMapping
    public Result update(@RequestBody Student student) {
        boolean flag = studentService.update(student);
        return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR, flag);
    }
}

异常处理层

springmvc_ssm\src\main\java\com\mercurows\exception\BusinessException.java

package com.mercurows.exception;

public class BusinessException extends RuntimeException {
    private Integer code;

    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

    public Integer getCode() {
        return code;
    }

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

springmvc_ssm\src\main\java\com\mercurows\exception\SystemException.java

package com.mercurows.exception;

public class SystemException extends RuntimeException {
    private Integer code;

    public SystemException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public SystemException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }

    public Integer getCode() {
        return code;
    }

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

测试

springmvc_ssm\src\test\java\service\StudentServiceTest.java

package service;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.mercurows.config.Springconfig;
import com.mercurows.domain.Student;
import com.mercurows.service.StudentService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Springconfig.class)
public class StudentServiceTest {
    @Autowired
    private StudentService service;

    @Test
    public void testGetById() {
        Student student = service.getById(1);
        System.out.println(student);
    }

    @Test
    public void testGetAll() {
        List<Student> all = service.getAll();
        System.out.println(all);
    }
}

项目结构

image-20230815114544306

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringMVC学习笔记 的相关文章

  • Java 错误和警告列表

    在哪里 如何获得所有 java 和 javac 的错误和警告消息的列表 This http mindprod com jgloss compileerrormessages html我认为页面是您所需要的
  • 二元运算符 >=、-、* 的错误操作数类型

    我无法弄清楚如何修复代码中不断出现的这些错误 import java util Scanner public class Unit02Prog1 public static void main String args Scanner inp
  • 使用 Spring MVC 在 jar 文件中显示 jsp 页面

    我正在使用 Spring MVC 3 2 2 在 java 中开发一个 Web 应用程序 我在从 jar 文件中加载 jsp 页面时遇到问题 Spring MVC Web应用程序具有以下结构 META INF WEB INF spring
  • 无法在 Intellij 中运行主类[重复]

    这个问题在这里已经有答案了 我有以下项目结构 ProjectRoot src Main examples libs My src文件夹被标记为sources在 Intellij 中 现在 当我想运行 Main 类时 出现以下错误 Excep
  • Jenkins 未显示 Maven 编译器错误

    在 Jenkins 中构建多模块 maven 3 项目时 如果出现构建错误 我们会收到一条神秘消息 表明 Maven 编译器插件失败 这在上周才刚刚开始发生 INFO BUILD FAILURE INFO INFO Total time 1
  • Android 信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR) libwebviewchromium.so

    对于 android 4 4 我多次收到 Native crash at system lib libwebviewchromium so 错误 以下是设备包括 Xperia Z1 SO 01F 16 30 2 Galaxy Tab4 7
  • Spring 从 JBoss 上下文加载 PropertySourcesPlaceholderConfigurer

    我有一个使用 PropertySourcesPlaceholderConfigurer 的 spring 3 1 应用程序加载设置 我想管理测试和生产环境 只需从服务器上下文加载设置覆盖本地文件属性中指定的设置 下一个示例在 Tomcat
  • 是否可以使用 Apache Tika 提取表信息?

    我正在寻找 pdf 和 MS Office 文档格式的解析器 以从文件中提取表格信息 当我看到 Apache Tika 时 正在考虑编写单独的实现 我能够从任何这些文件格式中提取全文 但我的要求是提取表格数据 我希望有 2 列采用键值格式
  • 在 Eclipse 中删除空块之前的新行

    我更喜欢奥尔曼式 http en wikipedia org wiki Brace style Allman style大括号 例如 if foo magical prancing unicorn stuff 而不是 if foo unma
  • 生成一定长度的所有排列

    假设我们有一个字母表 abcdefghiklimnop 如何以有效的方式以五个一组的形式重复该字母表来递归生成排列 几天来我一直在为此苦苦挣扎 任何反馈都会有帮助 本质上这与 生成给定字符串的所有排列 https stackoverflow
  • 我的 Kafka 流应用程序刚刚退出,代码为 0,什么也不做

    为了尝试 Kafka 流 我这样做了 public static void main String args final StreamsBuilder builder new StreamsBuilder final Properties
  • 为什么要为 id 设置DisallowedFields? -- Spring 宠物诊所示例

    从 Spring API 中 我了解到 InitBinder用于初始化一些绑定规则 在宠物诊所的例子中 为什么我们有setdisallowed id 当id不显示在表单上时 InitBinder public void setAllowed
  • React Native v0.71.8 React-native-vector-icons 你看不到的图标

    我在用react native版本v0 71 8 我安装了react native vector icons库 但图标未显示 似乎链接在最新版本的 React Native 中不再起作用 所以我按照说明进行操作 但它不再编译 出现以下错误
  • 向Java类库添加函数

    我使用的 Java 类库在很多方面都不完整 有很多类我认为应该内置其他成员函数 但是 我不确定添加这些成员函数的最佳实践 让我们调用不足的基类A class A public A long arbitrary arguments publi
  • 线程数组?

    所以我在理解如何避免线程的顺序执行时遇到了问题 我试图创建一个线程数组并在单独的循环中执行 start 和 join 函数 这是我现在拥有的代码示例 private static int w static class wThreads im
  • 为什么/何时应该使用泛型方法?

    学习Java的时候遇到过通用方法 public
  • ebean 映射到 BYTEA 的数据类型是什么?

    我有一个游戏 2 0 2 需要在数据库中存储一些文件的应用程序 我们使用 Ebean 作为 ORM 我相信我的数据库中需要一个 BYTEA 列来存储该文件 但我不确定在我的模型中使用什么数据类型 我应该使用某种Blob 或者只是一个byte
  • 使用 Hibernate Envers 的复合表

    我有一个带有复合表的应用程序 其中包含一个额外的列 一切正常 直到我们添加 Hibernate Envers Audited org hibernate MappingException 无法读取 no pack response Resp
  • 用于生成 ISO 文件的 Maven 插件

    有没有可以生成ISO镜像的maven插件 我需要获取一些模块的输出 主要是包含 jar 的 zip 文件 并将它们组合成一个 ISO 映像 Thanks 现在有一个 ISO9660 maven 插件可以完成这项工作 https github
  • FragmentMap + ActionBar 选项卡

    我一直在尝试插入一个MapView进入一个ActionBar Tab 但我什至无法解决问题 即使谷歌搜索 这是主要活动 Override public void onCreate Bundle savedInstanceState supe

随机推荐

  • 在Linux的Ubuntu系统下安装QT及相关环境配置

    安装QT 从官网下载QT的安装包 在本地安装 本次使用的是Ubuntu18 06以及QT5 14 2 下文皆使用此版本作为示例 首先安装QT 具体操作如下 1 使用cd命令 cd home usr download 切换至安装包所在的目录下
  • Proteus仿真时数码管不能动态显示的问题及解决方法

    今天做Proteus仿真时遇到了数码管不能动态显示的问题 我的程序是用单片机P1口控制数码管段选 P2口低四位控制数码管位选 数码管1ms显示一位 全部刷新需要4ms 正常情况下人眼是感受不到这个速度下数码管的刷新过程的 所以他应该是这个样
  • 【图文解析 】Java中的Liu、继承、组合

    Alt Shift s 快捷键
  • Vue Element-ui el-table sortablejs 表格拖拽排序

    首先要在项目中本地安装 sortablejs 执行 npm install sortablejs save 然后在要实现表格拖拽的 vue文件中 引入 sortablejs import Sortable from sortablejs 基
  • PPPOE协议工作流程

    PPPoE Point to Point Protocol over Ethernet 基于以太网的点对点协议 的工作流程包含发现 Discovery 和会话 Session 两个阶段 发现阶段是无状态的 目的是获得PPPoE 终端 在局端
  • A5M2使用

    目录 一 修改语言 二 连接数据库 三 SQL相关 3 1 新建SQL 3 2 生成增删改查SQL 方式一 方式二 3 3 生成批量插入insert语句 3 4 生成DDL 3 5 SQL整形 3 6 SELECT 之后修改数据 3 7 生
  • 网络编程的无冕之王-Netty入门和核心组件介绍

    最近我在研究Netty 之前只是经常听说 并没有实际做过研究 为什么突然要好好研究一下它 主要是因为前段时间 我在看RocketMQ底层原理的时候发现它的底层的网络通信都是基于Netty 然后网上一查 果然 大家太多的耳熟能详的工具组件 都
  • 物理射线、导航网格寻路

    每日一句 努力追上你的每天都是美好的 因为未来可期 目录 射线检测 需求1 物体射线到一定距离会改变物体状态 降落伞 需求2 鼠标点哪走哪 寻路 射线 点击小地图 人物到达指定位置 需求3 做准心效果 射线碰到物体有UI跟随效果 寻路系统
  • C语言绘图EasyX图形库基础(笔记)

    在电脑已经安装了vs编译器的情况下在浏览器输入EasyX的官网网址http easyx cn下载EasyX图形库根据安装提示对应VS版本安装即可 EasyX cpp 此文件包含 main 函数 程序执行将在此处开始并结束 在电脑已经安装了v
  • 【前端】node、npm、pnpm部署react项目过程中问题记录

    最近在重新部署一个前后端分离的项目时 在前端环境这里遇到了一些麻烦 通过百度找到的node npm pnpm的处理情况不尽相同 没能很准确地解决到问题 经过多次的尝试才自己得到结论 现在记录一下操作过程中遇到的问题 1 目标是成功安装pnp
  • this action could not be completed. Try again

    问题描述 直接在organiser点击upload to app store出现 this action could not be completed Try again 解决办法 1 打开xcode 2 选择xcode gt open d
  • 基于Ambari 2.6 hdp2.6 集成Redis5.0.0

    1 将Redis组件纳入Amabri集群 查看hdp版本 hdp select status hadoop client 得到hadoop client 2 6 5 0 292 可知hdp版本为2 6 主节点上 cd var lib amb
  • Elasticsearch 搜索数量不能超过10000的解决方案

    目录 一 问题描述 二 问题分析 三 解决方案 3 1 调大index max result window 不推荐 3 2 cardinality 不推荐 3 3 track total hits 推荐 一 问题描述 开发环境 JDK1 8
  • 【STM32F4】STM32F407+ESP8266连接机智云过程详解

    要求 通过手机上的机智云通用APP 点亮开发板载LED0 LED1 摘要 硬件组成 STM32F407ZGT6 esp8266 乐鑫 软件APP 机智云开发都者中心下载的通用APP Demo Xcom串口调试助手 Keil V5 调试过程详
  • mui实现表格

    mui的css文档中没有向bootstrap中类似的写好的样式供调用 但是用table显示表格本身就不难看 再写一些CSS类完全可以放到网页中 下面提供代码
  • ROS2中创建 Python 和 C++包

    创建 Python 包 在本教程中 您将学习如何创建和设置 ROS2 Python 包 我将向您展示每一步 并解释文件之间的关系 在哪里编写节点 如何添加启动文件等 设置 ROS2 Python 包 Python包内文件说明 package
  • 进程管理详解

    1 进程 进程就是出于执行期的程序 但是进程并不仅仅局限于一段可执行的代码 通常进程还要包括其他资源 像打开的文件 挂起的信号 内核内部数据 处理器状态 一个或多个具有内存映射的内存地址空间及一个或多个执行线程 当然还包括用来存放全局变量的
  • idea工具基础配置(Mac)

    用于个人在初次使用idea时 做一些基础配置 便于后续快速开发 此文章不涉及快捷键设置 若需要快捷键设置可查看其他链接 idea Mac 快捷方式设置 快捷键改为eclipse 1 idea背景颜色 intelliJ IDEA gt pre
  • (每日一练)MATLAB数据拟合

    今天就的学习内容是数据拟合 数据拟合也称为曲线拟合 是一种把现有数据透过数学方法来代入一条数式的表示方式 科学和工程问题可以通过诸如采样 实验等方法获得若干离散的数据 根据这些数据 我们往往希望得到一个连续的函数 也就是曲线 或者更加密集的
  • SpringMVC学习笔记

    springMVC简单入门 快速搭建 pom xml依赖