springboot整合MyBatisPlus和Shiro

    科技2025-12-27  8

    个人博客项目搭建笔记

    springboot整合mybatisplus

    1.初始化项目

    创建项目的时候勾选

    webmysql

    两个模块

    2.在pom文件中引入mybatisplus包

    <!--引入mybatisplus配置--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> <!--引入阿里巴巴的Druid连接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.19</version> </dependency> <!--导入配置文件处理器,配置文件进行绑定就会有提示--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <!--可以为类创建get,set等的方法--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <!--可以匹配数据校验--> <dependency> <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> <version>2.0.2</version> </dependency>

    3.在application文件上设置mapper映射文件夹

    @MapperScan("com.myblogs.test.mapper")//设置mapper文件夹位置,会自动那招报的名称映射到对应的表中 //如果是mybatis需要在主程序中扫描,但是mybatisplus不需要扫描(我们的接口继承的basemapper类已经注入到容器里面了,如果还写上扫描就注入两次了) @SpringBootApplication public class AppApplication { public static void main(String[] args) { SpringApplication.run(AppApplication.class, args); } }

    4.编写一个controller

    @Controller//标注这个类是一个controller类 public class TestBlogsController { @ResponseBody//把结果返回页面,不加的话会自动拼接字符串找到hello world.html页面 @RequestMapping("/hello")//控制浏览器对哪些请求有响应 //如果浏览器返回的数据是json数据建议在hello(@RequestBody String str),这样springboot就可以自动封装json数据了。 public String hello(){ return "hello world!"; } }

    5.配置相应的mytatis数据源

    #配置服务器启动的端口号 server.port=8088 #配置数据源类型为aliba的数据连接池 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #配置数据的用户名 spring.datasource.username=root #配置数据库用户密码 spring.datasource.password=123456 #配置后天链接数据库的地址,这个地址是虚拟机中docker容器运行的mysql地址 spring.datasource.url=jdbc:mysql://192.168.247.130:3306/myblogs #配置数据库链接的驱动器 spirng.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #决定数据库初始化的方式,是一个枚举类型有always和EMBEDDED,NEVER spring.datasource.initialization-mode=always

    也可以使用yaml配置文件

    spring: datasource: # 数据源基本配置 username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/ssm_crud type: com.alibaba.druid.pool.DruidDataSource # 数据源其他配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

    6.链接虚拟机中的docker容器中的mysql数据库并创建一张user表

    /* Navicat Premium Data Transfer Source Server : docker01 Source Server Type : MySQL Source Server Version : 50562 Source Host : 192.168.247.130:3306 Source Schema : myblogs Target Server Type : MySQL Target Server Version : 50562 File Encoding : 65001 Date: 01/07/2020 15:16:15 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(15) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `age` int(15) NULL DEFAULT NULL, `birthday` date NULL DEFAULT NULL, `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `identity` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `gender` int(15) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; SET FOREIGN_KEY_CHECKS = 1;

    7,在entity文件夹中创建对应的User类

    /** * 下面介绍几个常用的 lombok 注解: *   @Data :注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法 *   @Setter:注解在属性上;为属性提供 setting 方法 *   @Getter:注解在属性上;为属性提供 getting 方法 *   @Log4j :注解在类上;为类提供一个 属性名为log 的 log4j 日志对象 *   @NoArgsConstructor:注解在类上;为类提供一个无参的构造方法 *   @AllArgsConstructor:注解在类上;为类提供一个全参的构造方法 * 将配置文件中配置的每一个属性的值,映射到这个组件中 * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定; * prefix = "person":配置文件中哪个下面的所有属性进行一一映射 * * 只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能; * */ @Component @ConfigurationProperties(prefix = "user") @Data @AllArgsConstructor @NoArgsConstructor @ToString @Accessors(chain =true) @Validated//说明需要进行数据校验,不知道为什么不能和configurationProperties一起使用。 public class User { //在不开启@ConfigurationProperties中可以使用@Value()进行文件的自动匹配 @TableId(value = "id",type= IdType.AUTO) private Integer id; private String name; private String password; private Integer age; private Date birthday; @Email private String email; private String identity; private Integer gender; }

    8.创建对应的Mapper类

    package com.myblogs.test.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.myblogs.test.entity.User; public interface UserMapper extends BaseMapper<User> { }

    9.创建Service类

    @Service public class UserService { @Autowired UserMapper userMapper; //查找所有的用户数据 public List<User> selectFindAll(){ List<User> userlist = userMapper.selectList(null); userlist.forEach(user -> System.out.println(user.toString())); return userlist; } }

    10.在controller中使用service中的方法。

    @Autowired UserService userService; @ResponseBody @RequestMapping("/adminuser") public List<User> allUser(){ return userService.selectFindAll(); }

    11. 也可以使用xml文件来配置mybatis的使用

    在properties文件或者yml文件做好mybaits的映射

    mybatis-plus: #除了mybatisplus提供给我们的自定义的crud功能,我们可能也需要写自己的crud,这时需要配置我们的mapper接口与mapper.xml的映射路径 mapper-locations: mybatis/**/*Mapper.xml typeAliasesPackage: com.myblogs.**.entity

    然后在UserMapper接口中写出新的查找方法,再在xml文件中配置

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.myblogs.test.mapper.UserMapper"> <select id="get" resultType="com.myblogs.test.entity.User"> select * from user where id = #{value} </select> </mapper>

    之后放到service中使用就好了。

    mybatis-plus分页查询

    1,配置mybaitis的配置类

    @EnableTransactionManagement// 启注解事务管理,等同于xml配置方式的 <tx:annotation-driven /> @Configuration @MapperScan("com.myblogs.test.mapper") public class MybaitsPlusConfig { @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false // paginationInterceptor.setOverflow(false); // 设置最大单页限制数量,默认 500 条,-1 不受限制 // paginationInterceptor.setLimit(500); // 开启 count 的 join 优化,只针对部分 left join paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); return paginationInterceptor; } }

    2.使用多表查询

    //分页查询的使用 public void testFindPage(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); //queryWrapper.eq("age",23);//一个判断条件,从符合条件的数据中分页 IPage<User> page = new Page<>(1,2);//控制着显示第几页,这一页有多少数据。 IPage<User> userIPage = userDAO.selectPage(page, queryWrapper); long total = userIPage.getTotal(); System.out.println(total); userIPage.getRecords().forEach(user-> System.out.println(user)); }

    配置文件的使用

    springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件

    –file:./config/

    –file:./

    –classpath:/config/

    –classpath:/

    优先级由高到底,高优先级的配置会覆盖低优先级的配置;

    SpringBoot会从这四个位置全部加载主配置文件;互补配置;

    我们还可以通过spring.config.location来改变默认的配置文件位置

    项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;

    java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties

    1、外部配置加载顺序

    SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置

    1.命令行参数

    所有的配置都可以在命令行上进行指定

    java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc

    多个配置用空格分开; --配置项=值

    2.来自java:comp/env的JNDI属性

    3.Java系统属性(System.getProperties())

    4.操作系统环境变量

    5.RandomValuePropertySource配置的random.*属性值

    由jar包外向jar包内进行寻找;

    优先加载带profile

    6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件

    7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件

    再来加载不带profile

    8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件

    9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件

    10.@Configuration注解类上的@PropertySource

    11.通过SpringApplication.setDefaultProperties指定的默认属性

    所有支持的配置加载来源;

    参考官方文档

    配置日志系统

    1.springboot默认配置

    springboot默认配置符合我们的要求可以在项目中直接使用

    Logger logger = LoggerFactory.getLogger(getClass()); @Test public void contextLoads() { //System.out.println(); //日志的级别; //由低到高 trace<debug<info<warn<error //可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效 logger.trace("这是trace日志..."); logger.debug("这是debug日志..."); //SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别 logger.info("这是info日志..."); logger.warn("这是warn日志..."); logger.error("这是error日志..."); }

    可以在yml或者properties文件中设置日志输出等级来控制日志输出

    #配置日志输出等级 logging: level: #配置根目录下的所有文件日志输出等级为info级别 root: info #配置所有com.hdeasy目录下的所有文件日志输出等级为debug com.hdeasy.hdeasyproject: debug 日志输出格式: %d表示日期时间, %thread表示线程名, %-5level:级别从左显示5个字符宽度 %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息, %n是换行符 --> %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n

    SpringBoot修改日志的默认配置

    logging.level.com.atguigu=trace #logging.path= # 不指定路径在当前项目下生成springboot.log日志 # 可以指定完整的路径; #logging.file=G:/springboot.log # 在当前磁盘的根路径下创建spring文件夹和里面的log文件夹;使用 spring.log 作为默认文件 logging.path=/spring/log # 在控制台输出的日志的格式 logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n # 指定文件中日志输出的格式 logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} ==== %msg%n logging.filelogging.pathExampleDescription(none)(none)只在控制台输出指定文件名(none)my.log输出日志到my.log文件(none)指定目录/var/log输出到指定目录的 spring.log 文件中

    logback.xml:直接就被日志框架识别了;

    logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能

    <springProfile name="staging"> <!-- configuration to be enabled when the "staging" profile is active --> 可以指定某段配置只在某个环境下生效 </springProfile>

    如:

    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <!-- 日志输出格式: %d表示日期时间, %thread表示线程名, %-5level:级别从左显示5个字符宽度 %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息, %n是换行符 --> <layout class="ch.qos.logback.classic.PatternLayout"> <springProfile name="dev"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern> </springProfile> <springProfile name="!dev"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern> </springProfile> </layout> </appender>

    如果使用logback.xml作为日志配置文件,还要使用profile功能,会有以下错误

    no applicable action for [springProfile]

    2、切换日志框架

    可以按照slf4j的日志适配图,进行相关的切换;

    slf4j+log4j的方式;

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>logback-classic</artifactId> <groupId>ch.qos.logback</groupId> </exclusion> <exclusion> <artifactId>log4j-over-slf4j</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency>

    切换为log4j2

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</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-log4j2</artifactId> </dependency>

    SpringMVC,前端资源配置

    1、前端模板和资源映射的配置(感觉用了vue这些都没用了)

    1)、引入webjar

    <!--引入jquery-webjar-->在访问的时候只需要写webjars下面资源的名称即可 <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.5.1</version> </dependency>

    2)、springboot默认配置的静态资源映射文件夹

    "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" "/":当前项目的根路径

    3)、springboot自动映射默认静态文件夹下的index.html作为主页面

    访问localhost:8088会默认访问localhost:8088/index.html

    4)、springboot默认配置网页图标为 **/favicon.ico在默认的静态文件夹目录中寻找;

    #自己定义静态资源文件夹 #自己定义后自动定义的就么有用了 #自己定义静态资源文件夹之后系统配置的文件夹就会失效,需要的时候可以手动配置回来。 spring.resources.static-locations=classpath:/hello,classpath:/atguigu

    5)、引入模板引擎thymelea

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <!--2.1.6--> </dependency> <!--切换thymeleaf版本--> <properties> <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version> <!-- 布局功能的支持程序 thymeleaf3主程序 layout2以上版本 --> <!-- thymeleaf2 layout1--> <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version> </properties>

    thymelea模板引擎在2.0版本之前校验规则比较严谨。而且不支持什么玩意来着忘记了,但是用2.x的引擎然后用3.x的thymeleaf就好了

    只要我们把HTML页面放在classpath:/templates/,thymeleaf就能自动渲染;

    使用:

    1、导入thymeleaf的名称空间

    <html lang="en" xmlns:th="http://www.thymeleaf.org">

    2、使用thymeleaf语法;

    <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>成功!</h1> <!--th:text 将div里面的文本内容设置为 --> <div th:text="${hello}">这是显示欢迎信息</div> </body> </html>

    具体语法参考官方文档

    2、springMvc配置(感觉配置了shiro之后验证之类的完全可以交给shiro,过滤器之类的还有存在的必要么?)

    Spring Boot 自动配置好了SpringMVC

    以下是SpringBoot对SpringMVC的默认配置:(WebMvcAutoConfiguration)

    我们可以对springmvc进行扩展

    使用注解进行扩展编写一个@Configuration,是WebMvcConfigureAdapter类型,不能标注@EnableWebMvc;

    @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Bean public WebMvcConfigurer webMvcConfigurer() { WebMvcConfigurer webMvc = new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { //配置跨域请求 registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") .maxAge(3600) .allowCredentials(true); } @Override public void addViewControllers(ViewControllerRegistry registry) { //配置相应的视图解析器用来做转发和跳转 } }; return webMvc; } }

    可以在视图解析器的地方添加视图解析。

    配置拦截器进行登录检查

    /*** * 登录检查 */ public class LoginHandlerInterceptor implements HandlerInterceptor { //目标方法执行之前 /*** * preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理; * postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView (这个博主就基本不怎么用了); * afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面); */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object logUser = request.getSession().getAttribute("logUser"); if(logUser == null){ //未登录,返回登录页面 request.setAttribute("msg","没有权限请先登录"); request.getRequestDispatcher("/index.html").forward(request,response); return false; }else{ //已经登录,放行请求 return true; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }

    拦截器配置完成后在webmvc中注册进去

    package com.myblogs.test.config; import com.myblogs.test.compoent.LoginHandlerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.servlet.config.annotation.*; import java.nio.charset.Charset; import java.util.List; @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Bean public WebMvcConfigurer webMvcConfigurer() { WebMvcConfigurer webMvc = new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { //配置跨域请求 registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") .maxAge(3600) .allowCredentials(true); } @Override public void addViewControllers(ViewControllerRegistry registry) { //配置相应的视图解析器用来做转发和跳转 registry.addViewController("/main.html").setViewName("emp/dashboard"); registry.addViewController("/").setViewName("index"); registry.addViewController("/index.html").setViewName("index"); } @Override public void addInterceptors(InterceptorRegistry registry) { //拦截所以的访问会把静态资源一起拦截把静态资源文件夹全部除掉 registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login","/webjars/**","/asserts/**"); } @Bean public HttpMessageConverter<String> responseBodyConverter() { StringHttpMessageConverter converter = new StringHttpMessageConverter(Charset.forName("UTF-8")); return converter; } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { WebMvcConfigurer.super.configureMessageConverters(converters); converters.add(responseBodyConverter()); } @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false); } }; return webMvc; } }

    3、定制错误页面

    springboot默认配置好了错误页面,会相应error下的4XX和5XXhtml文件。

    如果想要自定义错误页面信息需要做下面操作啊

    1)、如何定制错误的页面;

    ​ 1)、有模板引擎的情况下;error/状态码; 【将错误页面命名为 错误状态码.html 放在模板引擎文件夹里面的 error文件夹下】,发生此状态码的错误就会来到 对应的页面;

    ​ 我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html);

    ​ 页面能获取的信息;

    ​ timestamp:时间戳

    ​ status:状态码

    ​ error:错误提示

    ​ exception:异常对象

    ​ message:异常消息

    ​ errors:JSR303数据校验的错误都在这里

    ​ 2)、没有模板引擎(模板引擎找不到这个错误页面),静态资源文件夹下找;

    ​ 3)、以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面;

    2)、如何定制错误的json数据;

    ​ 1)、自定义异常处理&返回定制json数据;

    @ControllerAdvice public class MyExceptionHandler { @ResponseBody @ExceptionHandler(UserNotExistException.class) public Map<String,Object> handleException(Exception e){ Map<String,Object> map = new HashMap<>(); map.put("code","user.notexist"); map.put("message",e.getMessage()); return map; } } //没有自适应效果...

    ​ 2)、转发到/error进行自适应响应效果处理

    @ExceptionHandler(UserNotExistException.class) public String handleException(Exception e, HttpServletRequest request){ Map<String,Object> map = new HashMap<>(); //传入我们自己的错误状态码 4xx 5xx,否则就不会进入定制错误页面的解析流程 /** * Integer statusCode = (Integer) request .getAttribute("javax.servlet.error.status_code"); */ request.setAttribute("javax.servlet.error.status_code",500); map.put("code","user.notexist"); map.put("message",e.getMessage()); //转发到/error return "forward:/error"; }

    3)、将我们的定制数据携带出去;

    出现错误以后,会来到/error请求,会被BasicErrorController处理,响应出去可以获取的数据是由getErrorAttributes得到的(是AbstractErrorController(ErrorController)规定的方法);

    ​ 1、完全来编写一个ErrorController的实现类【或者是编写AbstractErrorController的子类】,放在容器中;

    ​ 2、页面上能用的数据,或者是json返回能用的数据都是通过errorAttributes.getErrorAttributes得到;

    ​ 容器中DefaultErrorAttributes.getErrorAttributes();默认进行数据处理的;

    自定义ErrorAttributes

    //给容器中加入我们自己定义的ErrorAttributes @Component public class MyErrorAttributes extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) { Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace); map.put("company","atguigu"); return map; } }

    最终的效果:响应是自适应的,可以通过定制ErrorAttributes改变需要返回的内容

    serverlet定制

    1、修改和server有关的配置(ServerProperties【也是EmbeddedServletContainerCustomizer】);

    server.port=8081 server.context-path=/crud server.tomcat.uri-encoding=UTF-8 //通用的Servlet容器设置 server.xxx //Tomcat的设置 server.tomcat.xxx

    2、编写一个EmbeddedServletContainerCustomizer:嵌入式的Servlet容器的定制器;来修改Servlet容器的配置

    //在springboot新版本中以前的Em.....类被下面的类代替了所以使用下面的代码才可以运行 @Bean //一定要将这个定制器加入到容器中 public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){ return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() { @Override public void customize(ConfigurableWebServerFactory factory) { factory.setPort(8083); } }; }

    2)、注册Servlet三大组件【Servlet、Filter、Listener】

    由于SpringBoot默认是以jar包的方式启动嵌入式的Servlet容器来启动SpringBoot的web应用,没有web.xml文件。

    首先创建一个MyServerConfig类,然后在对应的文件夹中常见对应的servlet,linser,filter

    @Configuration public class MyServerConfig { //注册listener类 @Bean public ServletListenerRegistrationBean myListener(){ ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener()); return registrationBean; } //注册filter @Bean public FilterRegistrationBean myFilter(){ FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new MyFilter()); registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet")); return registrationBean; } //注册servlet @Bean public ServletRegistrationBean myServlet(){ ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new Myservlet(),"/myServlet"); return servletRegistrationBean; } @Bean public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){ return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() { @Override public void customize(ConfigurableWebServerFactory factory) { factory.setPort(8083); } }; } }

    注册三大组件用以下方式

    ServletRegistrationBean

    //注册三大组件 @Bean public ServletRegistrationBean myServlet(){ ServletRegistrationBean registrationBean = new ServletRegistrationBean(new MyServlet(),"/myServlet"); return registrationBean; } --------------------------------- //servlet类 package com.hdeasy.hdeasyspringboot03.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class Myservlet extends HttpServlet { //配置嵌入式的servlet容器 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("Hello MyServlet"); } }

    FilterRegistrationBean

    @Bean public FilterRegistrationBean myFilter(){ FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(new MyFilter()); registrationBean.setUrlPatterns(Arrays.asList("/hello","/myServlet")); return registrationBean; } -------------------- //filter类 package com.hdeasy.hdeasyspringboot03.filter; import javax.servlet.*; import java.io.IOException; public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("MyFilter process..."); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }

    ServletListenerRegistrationBean

    @Bean public ServletListenerRegistrationBean myListener(){ ServletListenerRegistrationBean<MyListener> registrationBean = new ServletListenerRegistrationBean<>(new MyListener()); return registrationBean; } ------------------------- //listener类 package com.hdeasy.hdeasyspringboot03.listener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("当前项目启动"); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("当前项目报销"); } }

    4、配置国际化

    创建国际化的配置文件

    然后配置国际化的文件路径

    #指定国际化的配置文件在哪个文件夹 spring.messages.basename=i18n.index #开启springmvc的过滤 spring.mvc.hiddenmethod.filter.enabled=true

    为了实现点击切换国际化的方法编写一个类,然后注册到容器中

    @Component public class MyError extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) { Map<String,Object>map=super.getErrorAttributes(webRequest,options); map.put("company","atguigu"); Map<String,Object> ext = (Map<String, Object>) webRequest.getAttribute("ext",0); map.put("ext",ext); return map; } }

    在某一个控制类中注入他

    @Bean public LocaleResolver LocaleResolver(){ return new MyLocaleResolver(); }

    shiro与springboot整合

    1.编写一个realm类

    public class MyRealm1 extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了授权逻辑"); return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行了认证逻辑"); String name = "root"; String password="123456"; UsernamePasswordToken token1 = (UsernamePasswordToken) token; if(!token1.getUsername().equals(name)){ System.out.println("没有获取到对应值"); return null; } System.out.println("获取到了对应值"); return new SimpleAuthenticationInfo("",password,""); //返回的三个参数第一个是类,第二个是密码,第三个是当前的realm的名称 } }

    2.编写一个配置类

    @Configuration public class shiroConfig { //创建shiorFilterFactoryBean //@Qualifier控制需要注入的注解的bean的名字 @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //设置安全管理器 shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); //设置shiro内置过滤器 /*** * Shiro内置过滤器,可以实现权限相关的拦截器 * 常用的过滤器: * anon:无需认证就可以访问 * authc: 必须认证才可以访问 * user: 如果使用rememberMe的功能可以直接访问 * perms: 该资源必须得到资源权限可以访问 * role: 该资源必须得到角色权限才可以访问 */ Map<String,String> filterMap = new LinkedHashMap<>(); filterMap.put("/testTheymeleaf","anon"); filterMap.put("/loginuser","anon"); filterMap.put("/*","authc"); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); return shiroFilterFactoryBean; } @Bean(name="securityManager") //创建DefaultWebSecurityManager public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("myRealm1") MyRealm1 myRealm1){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //关联realm securityManager.setRealm(myRealm1); return securityManager; } @Bean(name="myRealm1") public MyRealm1 getRealm(){ return new MyRealm1(); } }

    3.编写一个controller类来控制访问

    在配置之前先要把之前TestBlogsController里面的/user/login类注释掉,这样才可以使用shiro来控制登录验证。

    @Controller public class shiroController { @PostMapping("/user/login") public String loginuser(String username, String password, Model model, HttpSession session){ System.out.println(username+password); //获取subject对象 Subject subjct = SecurityUtils.getSubject(); //封装数据 UsernamePasswordToken token = new UsernamePasswordToken(username,password); //注册用户 try{ subjct.login(token); System.out.println("注册成功了"); }catch (UnknownAccountException e) { model.addAttribute("msg","用户名不存在"); return "redirect:/login"; }catch (IncorrectCredentialsException e) { model.addAttribute("msg","密码错误"); // e.printStackTrace(); return "redirect:/login"; } session.setAttribute("logUser",username); return "redirect:/main.html"; } }
    Processed: 0.018, SQL: 9