数据库文件
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 ;
项目结构
<?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/>
</ 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>
< 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>
< fork> true</ fork>
< addResources> true</ addResources>
</ configuration>
</ plugin>
</ plugins>
</ build>
</ project>
java文件 资源文件
配置文件
#配置端口号
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 monitorInterval = " 5" >
< Properties>
< 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}" />
< ThresholdFilter level = " info" onMatch = " ACCEPT" onMismatch = " DENY" />
</ console>
< File name = " Filelog" fileName = " ${FILE_PATH}/test.log" append = " false" >
< PatternLayout pattern = " ${LOG_PATTERN}" />
</ File>
< RollingFile name = " RollingFileInfo" fileName = " ${FILE_PATH}/info.log" filePattern = " ${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz" >
< ThresholdFilter level = " info" onMatch = " ACCEPT" onMismatch = " DENY" />
< PatternLayout pattern = " ${LOG_PATTERN}" />
< Policies>
< TimeBasedTriggeringPolicy interval = " 1" />
< SizeBasedTriggeringPolicy size = " 10MB" />
</ Policies>
< DefaultRolloverStrategy max = " 15" />
</ RollingFile>
< RollingFile name = " RollingFileWarn" fileName = " ${FILE_PATH}/warn.log" filePattern = " ${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz" >
< ThresholdFilter level = " warn" onMatch = " ACCEPT" onMismatch = " DENY" />
< PatternLayout pattern = " ${LOG_PATTERN}" />
< Policies>
< TimeBasedTriggeringPolicy interval = " 1" />
< SizeBasedTriggeringPolicy size = " 10MB" />
</ Policies>
< DefaultRolloverStrategy max = " 15" />
</ RollingFile>
< RollingFile name = " RollingFileError" fileName = " ${FILE_PATH}/error.log" filePattern = " ${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz" >
< ThresholdFilter level = " error" onMatch = " ACCEPT" onMismatch = " DENY" />
< PatternLayout pattern = " ${LOG_PATTERN}" />
< Policies>
< TimeBasedTriggeringPolicy interval = " 1" />
< SizeBasedTriggeringPolicy size = " 10MB" />
</ Policies>
< DefaultRolloverStrategy max = " 15" />
</ RollingFile>
</ appenders>
< loggers>
< logger name = " org.mybatis" level = " info" additivity = " false" >
< AppenderRef ref = " Console" />
</ logger>
< Logger name = " org.springframework" level = " info" additivity = " false" >
< AppenderRef ref = " Console" />
</ Logger>
< 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
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;
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 +
'}' ;
}
}
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
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) ;
}
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
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 {
@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 ;
}
}
@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) {
registry. addInterceptor ( adminLoginInterceptor) . addPathPatterns ( "/admin/**" )
. excludePathPatterns ( "/admin/login" ) ;
}
@Override
public void addResourceHandlers ( ResourceHandlerRegistry registry) {
registry. addResourceHandler ( "/static/**" ) . addResourceLocations ( "classpath:/static/" ) ;
}
}
controller
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. 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" ;
}
}
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" ;
}