Springboot——restful实践后端

数据库文件

--- 创建数据库
CREATE DATABASE IF NOT EXISTS  `db_test`;
USE db_test;
-- 管理员表
CREATE TABLE IF NOT EXISTS `admin`
(
    `aid` INT  NOT NULL AUTO_INCREMENT COMMENT '管理员账号id',
    `name` VARCHAR(20) NOT NULL  COMMENT  '管理员账号id',
    `pwd` VARCHAR(20)  NOT NULL COMMENT '管理员密码',
    PRIMARY KEY `pk_aid` (`aid`)
) ENGINE = InnoDB;

-- 用户表
CREATE TABLE IF NOT EXISTS `user`
(
    `id` INT  NOT NULL AUTO_INCREMENT COMMENT '用户id',
    `username` VARCHAR(20)  NOT NULL COMMENT '账户名',
    `password` VARCHAR(20) NOT NULL COMMENT '密码',
    `sex` CHAR(1) DEFAULT 'M' COMMENT '性别M nan F 女',
    `birth` DATE COMMENT '出生日期',
    PRIMARY KEY `pk_uid` (`id`)
) ENGINE = InnoDB;

INSERT INTO admin VALUES (null,'admin','admin');

SELECT * FROM admin;
插入数据

随机生成数据网站


insert into user (id, username, password, sex, birth) values (1, 'cogles0', 'g9saZ4BJ9Xn', 'M', '2009-06-11');
insert into user (id, username, password, sex, birth) values (2, 'kboor1', 'QxTltEzxz', 'F', '2005-06-23');
insert into user (id, username, password, sex, birth) values (3, 'llongfield2', '5e7TH6lplp', 'F', '2006-05-16');
insert into user (id, username, password, sex, birth) values (4, 'drosentholer3', 'g4f0ZKImxv', 'F', '2016-10-05');
insert into user (id, username, password, sex, birth) values (5, 'asilverthorne4', 'Z5UjjX3', 'M', '2011-11-24');
insert into user (id, username, password, sex, birth) values (6, 'ndigan5', 'UC7pnoJW', 'M', '2013-01-09');
insert into user (id, username, password, sex, birth) values (7, 'mbriddock6', '8Ujnm0c0', 'F', '2019-06-30');
insert into user (id, username, password, sex, birth) values (8, 'dsueter7', 'LpluQlPoN2kl', 'F', '2018-02-08');
insert into user (id, username, password, sex, birth) values (9, 'eberzons8', 'GsEG3O1USej', 'F', '2017-08-27');
insert into user (id, username, password, sex, birth) values (10, 'mkelmere9', 'gjyWR8f9f9', 'M', '2010-06-19');

SELECT * FROM user;

项目结构

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.antRain</groupId>
    <artifactId>restful</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>restful</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions> <!--去除之前对老版本log4j的依赖-->
                <exclusion>
                    <artifactId>org.springframework.boot</artifactId>
                    <groupId>spring.boot.starter-logging</groupId>
                </exclusion>
        </exclusions>
    </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 验证码 -->
        <dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3.2</version>
        </dependency>

        <!--日志框架-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!-- 没有该配置,devtools 不生效 -->
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

  • java文件
    在这里插入图片描述
  • 资源文件
    在这里插入图片描述

配置文件

  • application.properties
#配置端口号
server.port = 8080
server.tomcat.uri-encoding=UTF-8

#禁用缓存
spring.thymeleaf.cache=false
spring.thymeleaf.encoding=UTF-8


#配置数据源
spring.datasource.name=springboot-site-datasource
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db_test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=654321


#需要实时更新的目录
spring.devtools.restart.enabled=true
spring.devtools.restart.additional-paths=resources/**,static/**,templates/**

#配置mapper映射文件
#mybatis.mapper-locations=classpath:mapper/*Mapper.xml
#mybatis.type-aliases-package=com.antrain.play.bean


spring.jackson.date-format=yyyy-MM-dd 
spring.jackson.time-zone=GMT+8

mybatis.configuration.log-prefix=org.apache.ibatis.logging.log4j2.Log4j2Impl

# 指定log4j2作为日志记录
logging.config= classpath:log4j2-dev.xml
logging.level.com.antrain.restful.mapper =


# 版本需要手动开启配置 restful put delete 有效
spring.mvc.hiddenmethod.filter.enabled = true

<?xml version="1.0" encoding="UTF-8"?>
        <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
        <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration monitorInterval="5">
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--变量配置-->
<Properties>
    <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
    <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
    <property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
    <!-- 定义日志存储的路径,不要配置相对路径 -->
    <property name="FILE_PATH" value="./logs/" />
    <property name="FILE_NAME" value="lipstick_backend" />
</Properties>

<appenders>

    <console name="Console" target="SYSTEM_OUT">
        <!--输出日志的格式-->
        <PatternLayout pattern="${LOG_PATTERN}"/>
        <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
        <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
    </console>

    <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
    <File name="Filelog" fileName="${FILE_PATH}/test.log" append="false">
        <PatternLayout pattern="${LOG_PATTERN}"/>
    </File>

    <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
    <RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
        <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
        <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
        <PatternLayout pattern="${LOG_PATTERN}"/>
        <Policies>
            <!--interval属性用来指定多久滚动一次,默认是1 hour-->
            <TimeBasedTriggeringPolicy interval="1"/>
            <SizeBasedTriggeringPolicy size="10MB"/>
        </Policies>
        <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
        <DefaultRolloverStrategy max="15"/>
    </RollingFile>

    <!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
    <RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
        <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
        <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
        <PatternLayout pattern="${LOG_PATTERN}"/>
        <Policies>
            <!--interval属性用来指定多久滚动一次,默认是1 hour-->
            <TimeBasedTriggeringPolicy interval="1"/>
            <SizeBasedTriggeringPolicy size="10MB"/>
        </Policies>
        <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
        <DefaultRolloverStrategy max="15"/>
    </RollingFile>

    <!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
    <RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
        <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
        <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
        <PatternLayout pattern="${LOG_PATTERN}"/>
        <Policies>
            <!--interval属性用来指定多久滚动一次,默认是1 hour-->
            <TimeBasedTriggeringPolicy interval="1"/>
            <SizeBasedTriggeringPolicy size="10MB"/>
        </Policies>
        <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
        <DefaultRolloverStrategy max="15"/>
    </RollingFile>
</appenders>

<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
    <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
    <logger name="org.mybatis" level="info" additivity="false">
        <AppenderRef ref="Console"/>
    </logger>

    <!--监控系统信息-->
    <!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
    <Logger name="org.springframework" level="info" additivity="false">
        <AppenderRef ref="Console"/>
    </Logger>

    <!--配置输出sql语句-->
    <logger name="org.apache.ibatis" level="DEBUG"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>

    <root level="info">
        <appender-ref ref="Console"/>
        <appender-ref ref="Filelog"/>
        <appender-ref ref="RollingFileInfo"/>
        <appender-ref ref="RollingFileWarn"/>
        <appender-ref ref="RollingFileError"/>
    </root>
</loggers>
</configuration>

启动

package com.antrain.restful;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.antrain.restful.mapper")
@SpringBootApplication
public class RestfulApplication {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(RestfulApplication.class);
        application.setBannerMode(Banner.Mode.OFF);//关闭
        application.run(args);
    }

}

工具类utils

  • PageResult
package com.antrain.restful.util;

import java.io.Serializable;
import java.util.List;

public class PageResult implements Serializable {
    private int totalCount; //总记录数
    private int pageSize; //每页记录数
    private int totalPage;//总页数
    private int currPage;//当前页数
    private List<?> list;//列表数据
    /**
     * 分页
     *
     * @param list       列表数据
     * @param totalCount 总记录数
     * @param pageSize   每页记录数
     * @param currPage   当前页数
     */
    public PageResult(List<?> list, int totalCount, int pageSize, int currPage) {
        this.list = list;
        this.totalCount = totalCount;
        this.pageSize = pageSize;
        this.currPage = currPage;
        this.totalPage = (int) Math.ceil((double) totalCount / pageSize);
    }

    public int getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getTotalPage() {
        return totalPage;
    }

    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }

    public int getCurrPage() {
        return currPage;
    }

    public void setCurrPage(int currPage) {
        this.currPage = currPage;
    }

    public List<?> getList() {
        return list;
    }

    public void setList(List<?> list) {
        this.list = list;
    }

    @Override
    public String toString() {
        return "PageResult{" +
                "totalCount=" + totalCount +
                ", pageSize=" + pageSize +
                ", totalPage=" + totalPage +
                ", currPage=" + currPage +
                ", list=" + list +
                '}';
    }
}

  • PageUtil
package com.antrain.restful.util;

import java.util.LinkedHashMap;
import java.util.Map;

public class PageUtil extends LinkedHashMap<String, Object> {
    private int offset;//偏移量
    private int page;//当前页码
    private int limit;//每页条数

    public PageUtil(Map<String, Object> params) {
        this.putAll(params);

        //分页参数
        this.offset = Integer.parseInt(params.get("offset").toString());
        this.limit = Integer.parseInt(params.get("limit").toString());
        this.page = offset/(limit+1);
        this.put("offset", offset);
        this.put("page", page);
        this.put("limit", limit);
    }


    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getLimit() {
        return limit;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }

    public int getOffset() {
        return offset;
    }

    public void setOffset(int offset) {
        this.offset = offset;
    }

    @Override
    public String toString() {
        return "PageUtil{" +
                "offset=" + offset +
                ", page=" + page +
                ", limit=" + limit +
                '}';
    }
}

mapper

  • AdminMapper.java
package com.antrain.restful.mapper;

import com.antrain.restful.entity.Admin;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;

@Component
public interface AdminMapper {

    @Select("SELECT * FROM admin WHERE name=#{name} AND pwd =#{pwd}")
    Admin login(String name, String pwd);
}
  • UserMapper.java
package com.antrain.restful.mapper;

import com.antrain.restful.entity.User;
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.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

@Component
public interface UserMapper  {

    @Insert("insert into "+
            " user(id, username, password, sex, birth)"+
            "values (null, #{username,jdbcType=VARCHAR}, " +
            "#{password,jdbcType=VARCHAR}, #{sex,jdbcType=CHAR},#{birth, jdbcType=DATE} );")
    int insert(User user);

    @Delete("DELETE FROM user WHERE id=#{id};")
    int del(int id);

    @Update("UPDATE user SET username=#{username,jdbcType=VARCHAR}, password=#{password,jdbcType=VARCHAR} ,"+
            " sex= #{sex,jdbcType=CHAR},birth=#{birth,jdbcType=DATE} WHERE id=#{id,jdbcType=INTEGER};")
    int update(User user);

    @Select("SELECT * FROM user WHERE id=#{id};")
    User queryById(int id);

    @Select("SELECT * FROM user ;")
    List<User> queryAll();

    @Select(" <script>" +
            " SELECT * FROM user " +
            "<if test=\"offset!=null and limit!=null\">"+
            "limit #{offset},#{limit}"+
            "</if>"+
            " </script>")
    List<User> getBatch(Map params);

    @Select("select count(*) from user")
    int getTotal();
}

  • 实体层参考数据库表,service 方法跟mapper差不多

service

  • UserServiceImpl.java
package com.antrain.restful.service.impl;

import com.antrain.restful.entity.User;
import com.antrain.restful.mapper.UserMapper;
import com.antrain.restful.service.UserService;
import com.antrain.restful.util.PageResult;
import com.antrain.restful.util.PageUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Override
    public int insert(User user) {
        return userMapper.insert(user);
    }

    @Override
    public int del(int id) {
        return userMapper.del(id);
    }

    @Override
    public int update(User user) {
        return userMapper.update(user);
    }

    @Override
    public User queryById(int id) {
        return userMapper.queryById(id);
    }

    @Override
    public List<User> queryAll() {
        return userMapper.queryAll();
    }

    @Override
    public PageResult queryUsers(PageUtil pageUtil) {
        List<User> users = userMapper.getBatch(pageUtil);
        int total = userMapper.getTotal();
        PageResult pageResult = new PageResult(users, total, pageUtil.getLimit(), pageUtil.getPage());
        return pageResult;
    }
}

filter

  • AdminLoginInterceptor.java
AdminLoginInterceptor
package com.antrain.restful.filter;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

@Component
public class AdminLoginInterceptor implements HandlerInterceptor {

    /**
     * 在DispatcherServlet之前执行。
     * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        String uri = request.getRequestURI();
        if (uri.startsWith("/admin") && null == request.getSession().getAttribute("loginUser")&&uri.endsWith("/admin/login")==false) {
            request.getSession().setAttribute("errorMsg", "请重新登陆");
            response.sendRedirect(request.getContextPath() + "/admin/login");
            return false;
        } else {
            request.getSession().removeAttribute("errorMsg");
            return true;
        }
    }

    /**
     * 在controller执行之后的DispatcherServlet之后执行。
     * */
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    /**
     * 在页面渲染完成返回给客户端之前执行。一般用于资源清理操作
     * */
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

config

  • SiteWebMvcConfigurer.java
package com.antrain.restful.config;

import com.antrain.restful.filter.AdminLoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;

@Configuration
public class SiteWebMvcConfigurer implements WebMvcConfigurer {


    private final AdminLoginInterceptor adminLoginInterceptor;

    @Autowired
    public SiteWebMvcConfigurer(AdminLoginInterceptor adminLoginInterceptor) {
        this.adminLoginInterceptor = adminLoginInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加一个拦截器,拦截以/admin为前缀的url路径
        registry.addInterceptor(adminLoginInterceptor).addPathPatterns("/admin/**")
                .excludePathPatterns("/admin/login");
    }


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //使外部能访问静态资源
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }

}

controller

  • AdminController.java
package com.antrain.restful.controller;

import com.antrain.restful.entity.Admin;
import com.antrain.restful.service.AdminService;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;

@Controller
@RequestMapping("/admin")
public class AdminController {

    @Resource
    private AdminService adminService;

    @GetMapping("/login")
    public String login(){
        return "admin/login";
    }

    @PostMapping("/login")
    public String login(@RequestParam("userName") String userName,
                        @RequestParam("password") String password,
                        Map<String,Object> map, HttpSession session){
        if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
            map.put("errorMsg", "用户名或密码不能为空");
            return "admin/login";
        }
        Admin adminUser = adminService.login(userName, password);
        if (adminUser != null) {
            session.setAttribute("loginUser", adminUser.getName());
            session.setAttribute("loginUserId", adminUser.getAid());
            //session过期时间设置为7200秒 即两小时
            session.setMaxInactiveInterval(60 * 60 * 2);
            return "redirect:/admin/index";
        } else {
            map.put("errorMsg", "登陆失败");
            return "admin/login";
        }
    }

    @GetMapping({"", "/", "/index", "/index.html"})
    public String index(HttpServletRequest request) {
        request.setAttribute("path", "index");
        return "admin/index";
    }

}

  • UserController.java
package com.antrain.restful.controller;

import com.antrain.restful.entity.User;
import com.antrain.restful.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

@Controller
@RequestMapping("/admin")
public class UserController {

    @Resource
    private UserService userService;

    @GetMapping("/users")
    public String list(Model model){
        model.addAttribute("users",userService.queryAll());
        return "admin/list";
    }

    @GetMapping("/user")
    public  String toAdd(Model model){
        return "admin/add";
    }

    @PostMapping("/user")
    public String add(User user){
        System.out.println(user);
        userService.insert(user);
        return "redirect:/admin/users";
    }

    @GetMapping("/user/{id}")
    public String toEdit(@PathVariable("id") Integer id, Model model){
        model.addAttribute("user",userService.queryById(id));
        return "admin/add";
    }

    @PutMapping("/user")
    public String update(@RequestBody User user){
        System.out.println(user);
        userService.update(user);
        System.out.println("修改");
        return "redirect:/admin/users";
    }

    @DeleteMapping("/user/{id}")
    public String del(@PathVariable("id") Integer id){
        userService.del(id);
        return "redirect:/admin/users";
    }
}

问题日志

  • Request method ‘POST’ not supported
1. 原因:使用restful的put delete 方法无效
2. 解决:在配置加入:
# 版本需要手动开启配置 restful put delete 有效
spring.mvc.hiddenmethod.filter.enabled = true
  • Content type ‘application/x-www-form-urlencoded;charset=UTF-8’ not supported
// 问题代码
    @PutMapping("/user")
    public String update(@RequestBody User user){
        userService.update(user);
        return "redirect:/admin/users";
    }
 // 参考:https://blog.csdn.net/feiyst/article/details/88431621
 // 解决:去掉@RequestBody即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值