SpringMVC学习笔记

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/75685.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

回归预测 | MATLAB实现GRNN广义回归神经网络多输入多输出预测

回归预测 | MATLAB实现GRNN广义回归神经网络多输入多输出预测 目录 回归预测 | MATLAB实现GRNN广义回归神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 MATLAB实现GRNN广义回归神经网络多输入多输出预测&#xff0c;输入10个特征&#x…

re学习(32)【绿城杯2021】babyvxworks(浅谈花指令)

链接&#xff1a;https://pan.baidu.com/s/1msA5EY_7hoYGBEema7nWwA 提取码&#xff1a;b9xf wp:首先找不到main函数&#xff0c;然后寻找特殊字符串&#xff0c; 交叉引用 反汇编 主函数在sub_3D9当中&#xff0c;但是IDA分析错了 分析错误后&#xff0c;删除函数 创建函数 操…

从零构建深度学习推理框架-8 卷积算子实现

其实这一次课还蛮好理解的&#xff1a; 首先将kernel展平&#xff1a; for (uint32_t g 0; g < groups; g) {std::vector<arma::fmat> kernel_matrix_arr(kernel_count_group);arma::fmat kernel_matrix_c(1, row_len * input_c_group);for (uint32_t k 0; k < k…

UI美工设计岗位的基本职责概述(合集)

UI美工设计岗位的基本职责概述1 1、有良好的美术功底、设计新颖&#xff0c;整体配色及设计创意理念&#xff0c;能够独立完成整个网站页面设计及制作; 2、熟练运用DIV CSS&#xff0c;HTML 设计制作网页 ; 3、熟练运用Photoshop,Dreamweaver,Coreldraw(或Illustrator),Fla…

LabVIEW控制通用工作台

LabVIEW控制通用工作台 用于教育目的的计算机化实验室显着增长&#xff0c;特别是用于运动控制的实验室。它们代表了各种工业应用中不断扩大的领域&#xff0c;并成为以安全的方式使用通常昂贵或独特的实验室设备进行实时实验的宝贵工具。NI LabVIEW等软件应用程序的开发和不断…

【数据结构OJ题】反转链表

原题链接&#xff1a;https://leetcode.cn/problems/reverse-linked-list/description/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 方法一&#xff1a;三指针翻转法 使用三个结构体指针n1&#xff0c;n2&#xff0c;n3&#xff0c;原地修改结点…

开发过程中遇到的问题以及解决方法

巩固基础&#xff0c;砥砺前行 。 只有不断重复&#xff0c;才能做到超越自己。 能坚持把简单的事情做到极致&#xff0c;也是不容易的。 开发过程中遇到的问题以及解决方法 简单易用的git命令 git命令&#xff1a; 查看有几个分支&#xff1a;git branch -a 切换分支&#…

【分布式存储】数据存储和检索~倒排索引pageRank

为什么需要倒排索引 通过前两篇的文章介绍&#xff0c;B树主要针对的是读多写少的场景&#xff0c;而LSM针对的是写多读少的场景&#xff0c;其实在日常开发中&#xff0c;我们会将数据存储到搜索引擎中&#xff0c;然后进行数据的搜索&#xff0c;这种场景其实针对的是快速根…

【Linux】邮件服务器搭建 postfix+dovecot+mysql (终极版 超详细 亲测多遍无问题)

&#x1f341;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; 文章目录 前言基础原理准备工作一 、安装关于权…

Android布局【TableLayout】

文章目录 说明常见属性子控件设置属性 项目结构主要代码 说明 TableLayout也称为表格布局 常见属性 android:collapseColumns&#xff1a;设置需要被隐藏的列的序列号&#xff0c;从0开始android:stretchColumns&#xff1a;设置允许被拉伸的列的列序号&#xff0c;从0开始&…

同步、异步、协程

目录 同步异步https 异步请求&#xff1a; 协程1.为什么会要协程?2.异步的运行流程是什么3.协程的原语操作4.协程的定义?5.调度器的定义?6.调度的策略?7. api封装, hook8.多核的模式?9.协程的性能?10.要有哪些案例?nty_servernty_ mysql_client.cnty_ mysql oper.cnty_ …

Oracle 开发篇+Java通过HiKariCP访问Oracle数据库

标签&#xff1a;HikariCP、数据库连接池、JDBC连接池、释义&#xff1a;HikariCP 是一个高性能的 JDBC 连接池组件&#xff0c;号称性能最好的后起之秀&#xff0c;是一个基于BoneCP做了不少的改进和优化的高性能JDBC连接池。 ★ Java代码 import java.sql.Connection; impor…

MATLAB实现两组数据的延时对齐效果

博主在某次实验中&#xff0c;相同的实验条件下分别采集了两组数据&#xff0c;发现两组数据存在一个延时&#xff0c;如下图所示&#xff1a; 本文记录消除这个延时&#xff0c;实现相同数据状态的对齐效果&#xff0c;采用MATLAB自带的xcorr函数实现&#xff0c;具体步骤如下…

Ansible 进阶

Ansible 进阶 ⤴️Ansible 入门看这篇文章⤵️Ansible 实战看这篇文章 一.Ansible 中的 Playbook 1.1 Playbook 介绍 如下图&#xff0c;ansible 在整个管理过程中使用 playbook 的大体流程。 Playbook 中包含多个 role&#xff0c;每个 role 对应于在远程主机完成某个比较复…

【JavaEE基础学习打卡02】是时候了解Java EE了!

目录 前言一、为什么要学习Java EE二、Java EE规范介绍1.什么是规范&#xff1f;2.什么是Java EE规范&#xff1f;3.Java EE版本 三、Java EE应用程序模型1.模型前置说明2.模型具体说明 总结 前言 &#x1f4dc; 本系列教程适用于 Java Web 初学者、爱好者&#xff0c;小白白。…

编程小白的自学笔记十三(python办公自动化读写文件)

系列文章目录 编程小白的自学笔记十二&#xff08;python爬虫入门四Selenium的使用实例二&#xff09; 编程小白的自学笔记十一&#xff08;python爬虫入门三Selenium的使用实例详解&#xff09; 编程小白的自学笔记十&#xff08;python爬虫入门二实例代码详解&#xff09;…

scope穿透(二)

上篇文章已经讲了,如何穿透样式,今天我们进入element-ui官网进行大规模的穿透处理。 1.输入框 <template><div class""><el-input v-model"input" placeholder"请输入内容"></el-input></div> </template>…

使用插件实现pdf,word预览功能

效果 代码&#xff1a; 插件地址&#xff1a; https://github.com/501351981/vue-office <a-modalv-model:visible"visible":title"title"ok"handleOk":bodyStyle"bodyStyle":width"1200":maskClosable"false"…

WebRTC | SDP详解

目录 一、SDP标准规范 1. SDP结构 2. SDP内容及type类型 二、WebRTC中的SDP结构 1. 媒体信息描述 &#xff08;1&#xff09;SDP中媒体信息格式 i. “artpmap”属性 ii. “afmtp”属性 &#xff08;2&#xff09;SSRC与CNAME &#xff08;3&#xff09;举个例子 &…

〔011〕Stable Diffusion 之 解决绘制多人或面部很小的人物时面部崩坏问题 篇

✨ 目录 &#x1f388; 脸部崩坏&#x1f388; 下载脸部修复插件&#x1f388; 启用脸部修复插件&#x1f388; 插件生成效果&#x1f388; 插件功能详解 &#x1f388; 脸部崩坏 相信很多人在画图时候&#xff0c;特别是画 有多个人物 图片或者 人物在图片中很小 的时候&…