SpringBoot_第六章(知识点总结)

news2024/11/26 19:42:27

目录

1:拦截器(Interceptor)

1.1:拦截器代码实现

1.2:拦截器源码分析和流程总结

2:过滤器(Filter)、自定义(Servlet)、监听器(Listener)

3:文件上传

3.1:文件上传代码实现

3.2:文件上传源码分析

4:整合druid数据源

4.1:整合德鲁伊

4.2:德鲁伊监控页面

5:Spingboot指标监控

6:整合mybatis、mybatis-plus

6.1:整合mybatis

6.2:整合mybatis-plus

7:整合redis集群

8:错误处理

8.1:请求不存在的controller

8.2:请求存在但是代码错误的controller

8.3:前后端未分离

8.4: 前后端分析,全局异常


1:拦截器(Interceptor)

1.1:拦截器代码实现

拦截器是Spring容器进行管理的,对请求路径进行动态的拦截,可以进行各种权限日志等等骚操作。

代码实现第一步:自己实现HandlerInterceptor接口

/**
 * 登录检查 拦截器
 *
 * 1:写拦截器代码逻辑
 * 2  配置拦截器拦截 那些请求
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * controller方法 执行之前
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        log.info("拦截请求{}"+request.getRequestURI());
        User user = (User) request.getSession().getAttribute("loginUser");
        if (user == null) {
            System.out.println("拦截器重定向");
            //如果session不存在登录信息,重定向到登录页面
            request.setAttribute("msg","拦截器拦截未登录");
            request.getRequestDispatcher("/").forward(request,response);
            return false;
        }
        return true;//返回true 程序接着执行
    }


    /**
     * controller方法执行之后,在页面渲染之前
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           @Nullable ModelAndView modelAndView) throws Exception {
        log.info("controller方法执行之后{}",modelAndView);
    }
    /**
     * 页面渲染之后
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                                @Nullable Exception ex) throws Exception {
        log.info("页面渲染之后{}",ex);
    }

}

代码实现第二步:自定义拦截器拦截路径和放行路径

/**
 * 实现WebMvcConfigurer接口 改变MVC行为
 * 使用addInterceptors 接口添加拦截器
 */
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/*") //  /**拦截所有请求,包含静态页面  /*:只拦截后面一级 /**:拦截内容包含多个层级
                .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/*","/js/**");//过滤掉登录请求和静态资源
    }
}

1.2:拦截器源码分析和流程总结

所以真正的执行步骤如下:

2:过滤器(Filter)、自定义(Servlet)、监听器(Listener)

Filter、servlet是Servlet规范,拦截的是自定义的请求。因为DispatcherServlet拦截的是/

但是Filter、servlet可以自定义拦截请求,根据匹配规则,他们会自己处理请求。

Filter代码实现:

/**
 * 继承Filter
 * 不会经过拦截器
 * 拦截/*所有请求 不管get post
 * 
 * 使用次注解生效
 * @ServletComponentScan(basePackages = "com.example.springboot2_web03")
 */
@WebFilter(urlPatterns = "/*",filterName = "MyFilter")
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        String name = request.getParameter("name");
        System.out.println("执行MyFilter无论什么get、post方法:"+name);
        chain.doFilter(request,response);//调用链
    }
}

Servlet代码实现: 

/**
 * 继承HttpServlet类,可以重写各种get post put 等等方法
 *
 * 使用次注解生效
 * @ServletComponentScan(basePackages = "com.example.springboot2_web03")
 *
 * servlet 拦截/s1(精度高 优先匹配)  就不会进入DispatcherServlet拦截/
 */
@WebServlet(urlPatterns = "/s1",name = "MyServlet")
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        System.out.println("执行MyServlet请求get:"+name);
        resp.getWriter().write("get请求MyServlet拦截/s1请求:"+name);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        System.out.println("执行MyServlet请求post:"+name);
        resp.getWriter().write("post请求MyServlet拦截/s1请求:"+name);
    }
}

监听器代码实现:

/**
 * 继承ServletContextListener
 * 容器启动的时候生效
 * 
 * 使用次注解生效
 * @ServletComponentScan(basePackages = "com.example.springboot2_web03")
 */
@WebListener(value = "MyListener")
public class MyListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("MyListener监听ServletContext初始化,容器启动的时候输出");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("MyListener监听ServletContext销毁");
    }
}

 

3:文件上传

3.1:文件上传代码实现

第一步:html文件

<!--文件上传必须是post和enctype="multipart/form-data"-->
<form role="form" th:action="@{/fileUpload}" method="post" enctype="multipart/form-data">
    <div class="form-group">
        <label for="exampleInputEmail1">邮箱</label>
        <input type="email" name="email" class="form-control" id="exampleInputEmail1" placeholder="Enter email">
    </div>
    
    <div class="form-group">
        <label for="exampleInputPassword1">名字</label>
        <input type="text" name="username" class="form-control" id="exampleInputPassword1" placeholder="Password">
    </div>
    <div class="form-group">
        <label for="exampleInputFile">头像</label>
        <!--type="file" 没有multiple代表 单个文件-->
        <input type="file" name="headerImg" id="exampleInputFile">
    </div>
    
    <div class="form-group">
        <label for="exampleInputFile">生活照</label>
        <!--type="file" multiple代表多文件上传 -->
        <input type="file" name="photos" multiple>
    </div>
   
    <button type="submit" class="btn btn-primary">提交</button>
</form>

第二步Java代码实现:

 /**
     * 文件上传
     * @param files
     * @return
     */
    @PostMapping(value = "/fileUpload")
    public String fileUpload(@RequestParam(value = "username") String username,
                             @RequestParam(value = "email")String email,
                             @RequestParam(value = "headerImg") MultipartFile headerImg,
                             @RequestParam(value = "photos") MultipartFile[] photos,
                             Files files) throws IOException {
        if (!headerImg.isEmpty()){
            System.out.println("username:"+username);
            System.out.println("email:"+email);
            System.out.println("files:"+files);
            //headerImg 单文件
            System.out.println("headerImg名字:"+ headerImg.getOriginalFilename());
            System.out.println("headerImg大小:"+ headerImg.getSize());
            System.out.println("headerImg文件类型:"+ headerImg.getContentType());
            String newFileHeaderImg="A"+headerImg.getOriginalFilename();
            headerImg.transferTo(new File("/Users/huyiju/Desktop/upload/"+newFileHeaderImg));
        }

        if (photos.length>0){
            //photos多文件用MultipartFile[]数组
            for (MultipartFile photo : photos) {
                File file=new File("","");
                String newFilePhotos="B"+photo.getOriginalFilename();
                photo.transferTo(new File("/Users/huyiju/Desktop/upload/"+newFilePhotos));

            }
        }

        return "/form/form_layouts";
    }

 第三步配置文件设置文件上传大小

#单个文件上限
spring.servlet.multipart.max-file-size=10MB
#多个文件请求上限
spring.servlet.multipart.max-request-size=100MB

3.2:文件上传源码分析

首先查看源码MultipartAutoConfiguration的自动装配

有了文件上传解析器,我们在配置文件中设置上传文件大小配置,默认是1MB(单个文件)和10MB(最大请求)

然后查看源码

//for循环将controller的参数逐个绑定
args[i] = this.resolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);


//根据请求multipartRequest获取MultipartFile 并将返回值 
//赋值给 controller中的MultipartFile 类型的参数 
//
List<MultipartFile> files = multipartRequest.getFiles(name);
			return (!files.isEmpty() ? files.toArray(new MultipartFile[0]) : null);

4:整合druid数据源

4.1:整合德鲁伊

1:导入依赖

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

        <!--德鲁伊操作数据库-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.16</version>
        </dependency>

2:配置数据库信息和连接池

#德鲁伊数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/W1?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
#连接池信息
spring.datasource.type= com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.max-active=20
spring.datasource.druid.min-idle=5
spring.datasource.druid.initial-size=5
spring.datasource.druid.max-wait=60000

3:代码测试(未使用mybatis,所以这里使用了jdbcTemplate)

 @Autowired
    JdbcTemplate jdbcTemplate;
    /**
     * druid测试
     */
    @Test
    void starter_jdbc() {
        String sql="select * from t1";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
        maps.forEach(map -> System.out.println(map));
    }

4:结果查看(图片里边初始化的德鲁伊连接池)

4.2:德鲁伊监控页面

德鲁伊的依赖包含监控页面功能,只是没有开启我们只需要配置文件开启监控页面就可以

1:配置监控页面信息

# StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
#是否启用StatViewServlet(监控页面)默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.reset-enable=false
spring.datasource.druid.stat-view-servlet.login-username=root
spring.datasource.druid.stat-view-servlet.login-password=123456

### WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter
spring.datasource.druid.web-stat-filter.enabled=true
spring.datasource.druid.web-stat-filter.url-pattern=/*
spring.datasource.druid.web-stat-filter.session-stat-enable=true
spring.datasource.druid.web-stat-filter.session-stat-max-count=1000
spring.datasource.druid.filters=stat,wall
spring.datasource.druid.filter.stat.slow-sql-millis=1000
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.enabled=true

2:页面验证

登录页面,输入账户密码root、123456

http://localhost:8080/druid/login.html

5:Spingboot指标监控

6:整合mybatis、mybatis-plus

6.1:整合mybatis

1:导入依赖

 <!-- springboot——整合mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>

2:配置mapper映射位置

#mybatis配置 config-location配置mybatis文件地址  mapper-locations mapper地址
mybatis.config-location=classpath:mybatis-config.xml
mybatis.mapper-locations=classpath:mapper/*.xml

3:接口

package com.example.springboot2_web03.mapper;

import com.example.springboot2_web03.entity.T1;

@Mapper
public interface T1Mapper {
     List<T1> selectAll();
     T1 selectById(@Param(value = "id") int id);

     @Select("select * from t1 where id=#{id}")
     T1 selectById1(@Param(value = "id") int id);
}

4:mapper配置文件

<?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.example.springboot2_web03.mapper.T1Mapper">
    <!--查询全部-->
    <select id="selectAll" resultType="com.example.springboot2_web03.entity.T1">
        select * from t1
    </select>

    <!--根据id查询-->
    <select id="selectById" resultType="com.example.springboot2_web03.entity.T1">
        select * from t1 where id=#{id}
    </select>
</mapper>

代码测试:

 @Autowired
    T1Mapper t1Mapper;
    /**
     * mybatis测试
     */
    @Test
    void mybatis_test() {
        List<T1> t1s = t1Mapper.selectAll();
        for (T1 t1 : t1s) {
            System.out.println("查询数据:"+t1);
        }

        T1 t1 = t1Mapper.selectById1(1);
        System.out.println("根据id查询:"+t1);
    }

6.2:整合mybatis-plus

1:导入依赖

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

        <!--德鲁伊操作数据库-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.16</version>
        </dependency>

        <!-- springboot——整合mybatis-->
        <!--        <dependency>-->
        <!--            <groupId>org.mybatis.spring.boot</groupId>-->
        <!--            <artifactId>mybatis-spring-boot-starter</artifactId>-->
        <!--            <version>2.1.3</version>-->
        <!--        </dependency>-->

        <!--mybatisPlus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>

        <!-- MybatisPlus分页插件注解-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
            <version>3.5.3.1</version>
            <scope>compile</scope>
        </dependency>

2:配置文件

#mybatisPlus配置 config-location配置mybatis文件地址  mapper-locations mapper地址
#mybatis-plus.config-location=classpath:mybatis-config.xml
mybatis-plus.mapper-locations=classpath*:mapper/*.xml
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

3:添加分页拦截器

@Configuration
public class MybatisPlusConfig {

    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setOverflow(true);//最后一页的下一页调回首页
        paginationInnerInterceptor.setMaxLimit(500L);//-1不受限制 这里限制500条
        interceptor.addInnerInterceptor(paginationInnerInterceptor);//如果配置多个插件,切记分页最后添加

        //interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); 如果有多数据源可以不配具体类型 否则都建议配上具体的DbType
        return interceptor;
    }

4:代码测试

//mapper代码
@Mapper
public interface TestMapper extends BaseMapper<Test> {
    //自定义分页查询
    Page<Test> selectOrderByAgePage(@Param(value = "page") Page<Test> page);

}


//接口和实现类代码
public interface TestService extends IService<Test> {
     Page<Test> selectOrderByAgePage(Page<Test> page);
}

@Service
public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService{

    @Autowired
    TestMapper testMapper;

    /**
     * 查询数据 分页显示
     * @return
     */
    public Page<Test> selectOrderByAgePage(Page<Test> page){
       return testMapper.selectOrderByAgePage(page);
    }
}


//controller 代码
 @GetMapping(value = "/dynamic_table")
    public String dynamic_table(@RequestParam(name = "pageIndex",defaultValue = "1",required = false)Integer pageIndex,
                                            Model model){

        System.out.println("执行dynamic_table方法:默认值是第一页");

        //开始页和条数
        Page<Test> page=new Page<>(pageIndex,3);
        Page<Test> pages = testService.selectOrderByAgePage(page);
        System.out.println("当前页:"+pages.getCurrent());
        System.out.println("总页数:"+pages.getPages());
        System.out.println("总行数:"+pages.getTotal());
        System.out.println("当前页数据:"+pages.getRecords());

        model.addAttribute("pages",pages);
        return "/table/dynamic_table";
    }

7:整合redis集群

集群搭建过程见其他文章

1:导入依赖

  <!--    =======================   -->
        <!--    这里是Redis的集群测试案例    -->
        <!--    =======================   -->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

2:配置集群信息

#配置redis 集群
#集群密码
spring.redis.password=123456
#集群节点81 - 86
spring.redis.cluster.nodes=127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384,127.0.0.1:6385,127.0.0.1:6386
#最大重定向次数
spring.redis.cluster.max-redirects=5
#连接池最大连接量
spring.redis.lettuce.pool.max-active=8
#连接最大阻塞时间 毫秒
spring.redis.lettuce.pool.max-wait=1s
#空闲的最大数量
spring.redis.lettuce.pool.max-idle=8
#空闲的最小数量
spring.redis.lettuce.pool.min-idle=0

3:测试代码


//redistemplate配置
@Configuration
public class RedisConfig集群 {

    @Bean("redisTemplate")
    public RedisTemplate<Object, Object> redisTemplateJQ(
            @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
                    RedisConnectionFactory factory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        serializer.setObjectMapper(mapper);

        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);

        // Hash的key也采用StringRedisSerializer的序列化方式
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;

    }

}


//测试代码
 @Autowired
   RedisTemplate redisTemplate;
    //StringRedisTemplate redisTemplate;

    @Test
    void t1() {
        redisTemplate.opsForValue().set("代", "测试", 10, TimeUnit.MINUTES);
        Set<String> keys = redisTemplate.keys("*");
        for (String key : keys) {
            System.out.println("key:"+key);
        }
        System.out.println(keys);
        System.out.println("返回值a:" + redisTemplate.opsForValue().get("代"));
    }

8:错误处理

8.1:请求不存在的controller

1:浏览器请求没有服务的controller,返回html

2:postMan请求没有服务的controller,返回json

源码分析:

当请求不存在的时候,找不到处理方法报错

服务器转发了一个http://localhost:8080/error 请求,该请求会被自动装配的basicErrorController拦截

1:在ErrorMvcAutoConfiguration声明了一个bean是basicErrorController这个controller会拦截/error请求的错误。

2:这个controller拦截/error请求,在源码中可以看到这连个拦截错误请求

​ 

 3:根据不同的请求方式浏览器和postMan程序来决定返回html和json

8.2:请求存在但是代码错误的controller

controller代码

 @GetMapping(value = "/basic_table")
    public String basic_table(){
        //自定义错误 抛出 java.lang.ArithmeticException: / by zero
        int a=10/0;
        return "/table/basic_table";
    }

源码分析:

1:执行controller代码报错,DispatcherServlet拦截到异常。

2:异常处理

3:系统默认的异常解析器处理异常,结果都处理不了,回到上边用baseErrorController来处理

8.3:前后端未分离

当我们配置了4XX和5XX错误的html页面的时候

我们配置在项目中配置错误页,baseErrorController就会在浏览器请求错误的情况下,跳转到这些错误页面。我们在错误页面中取出异常信息

html页面

    <h3 th:text="${path}">请求路径</h3>
            <h3 th:text="${status}">状态</h3>
            <h3 th:text="${message}">错误消息</h3>
            <h3 th:text="${timestamp}">时间</h3>

 浏览器页面显示

8.4: 前后端分析,全局异常

首先我们定义两个Controller

@Controller
public class 异常Controller {


    /**
     * 前后端分离Controller 直接返回json
     */
    @GetMapping(value = "/basic_table1")
    @ResponseBody
    public CommonReturnType basic_table1(@RequestParam(value = "a",required = false) int b ){

        //1:重点:没有自定义全局异常,默认的异常解析器解析
        //这里出现异常没有返回值 会被DispatcherServlet拦截,捕获异常 发送/error
        // 会进入baseErrorController 返回html

        //2:重点:自定义全局异常,拦截指定异常
        // 会根据自定异常返回值 是走ModelAndView 还是直接返回json
        // 会进入baseErrorController 返回html

        int a=10/0; //报错 后边执行
        List<User> users = Arrays.asList(new User("张三1","000"),
                new User("张三1","111"),
                new User("张三2","222"),
                new User("张三3","333"));
        return CommonReturnType.crateCommonReturnType(users);
    }

    /**
     * 前后端不分离Controller 返回视图
     */
    @GetMapping(value = "/basic_table")
    public String basic_table(@RequestParam(value = "a") int b ){
        //1:重点:没有自定义全局异常,默认的异常解析器解析
        //这里出现异常没有返回值 会被DispatcherServlet拦截,捕获异常 发送/error
        // 会进入baseErrorController 返回html

        //2:重点:自定义全局异常,拦截指定异常
        // 会根据自定异常返回值 是走ModelAndView 还是直接返回json
        // 会进入baseErrorController 返回html
        
        //自定义错误 抛出 java.lang.ArithmeticException: / by zero
        int a=10/0; //报错 后边不执行
        // 这个异常ExceptionHandler 直接返回视图  return "login";//返回视图
        return "/table/basic_table";
    }
}

自定义全局异常

@Slf4j
@ControllerAdvice //底层Component
public class GlobalExceptionHandler {

    //自定义异常CommonReturnType {
    //    "status": "fail",
    //    "data": {
    //        "errCode": "300",
    //        "errMsg": "参数绑定错误"
    //    }
    //}

    //第一个自定义异常
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public CommonReturnType GlobalControllerExceptions1(Exception exception){
        log.info("异常是{}:",exception);
        Map<String,Object> map=new HashMap();
        if (exception instanceof ServletRequestBindingException) {
            map.put("errCode", "300");
            map.put("errMsg", "参数绑定错误");
        } else if (exception instanceof NoHandlerFoundException) {
            map.put("errCode", "404");
            map.put("errMsg", "404错误");
        } else {
            map.put("errCode", "8888");
            map.put("errMsg",exception.getMessage());
        }
        return CommonReturnType.crateCommonReturnType("fail", map);//返回指定异常
    }


    //前提:没有配置全局异常解析器 出现异常会被抛出,没有异常解析器处理
    //然后发送/error请求 被baseErrorController拦截 返回标准页面

    //拦截指定异常,会返回ModelAndView 不加@ResponseBody java.lang.ArithmeticException: / by zero
    @ExceptionHandler(value ={NullPointerException.class,ArithmeticException.class})
    //@ResponseBody 异常直接返回页面
    public String GlobalControllerExceptions(Exception exception) {
        log.info("异常是{}:",exception);
        return "login";//返回视图
    }


}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

部署Redis集群

文章目录 部署Redis集群1. 准备集群主机2. 启用集群功能3. 配置管理主机并创建集群3.1 配置管理主机 192.168.88.573.2 创建集群创建集群命令创建集群失败解决办法 3.3 查看集群信息查看集群统计信息查看集群详细信息 4. **测试集群及集群工作原理**4.1. 访问集群存取数据4.2 *…

Jmeter进阶使用指南-使用参数化

Apache JMeter是一个广泛使用的开源负载和性能测试工具。在进行性能测试时&#xff0c;我们经常需要模拟不同的用户行为和数据&#xff0c;这时候&#xff0c;参数化就显得尤为重要。此文主要介绍如何在JMeter中使用参数化。 什么是参数化&#xff1f; 参数化是一种将静态值替…

OpenCV之ellipse函数

ellipse函数用来在图片中绘制椭圆、扇形&#xff0c;有两个重载函数。 函数原型1&#xff1a; void cv::ellipse( InputOutputArray img,Point center,Size axes,double angle,double startAngle,double …

ORB-SLAM2算法14之局部建图线程Local Mapping

文章目录 0 引言1 概述2 处理队列中的关键帧3 剔除坏的地图点4 创建新地图点5 融合当前关键帧和其共视帧的地图点6 局部BA优化7 剔除冗余关键帧 0 引言 ORB-SLAM2算法7详细了解了System主类和多线程、ORB-SLAM2学习笔记8详细了解了图像特征点提取和描述子的生成、ORB-SLAM2算法…

如何使用SpringCloud Eureka 创建单机Eureka Server-注册中心

&#x1f600;前言 本篇博文是关于使用SpringCloud Eureka 创建单机Eureka Server-注册中心&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&…

Jenkins实现基础CD操作

操作截图 在Jenkins里面设置通过标签进行构建 在Jenkins中进入项目&#xff0c;配置以下 将execute shell换到invoke top-level maven targets之前 在gitlab中配置标签 代码迭代新的版本 项目代码迭代 修改docker-compose.yml 提交新版本的代码 在Jenkins中追加新…

Java调用Web Service接口

方法1. 用IDEA生成相关代码调用方法。 在IDEA插件商店下载插件 然后新建一个Java项目 创建一个包来存放生成的代码&#xff0c;(点击一下)选中这个包&#xff0c;点击Tools 填入接口url&#xff0c;记住后面拼接“?wsdl”&#xff0c;选择生成方法&#xff0c;然后OK即可生…

如何重构大数据时代中小企业的信用评价指标体系?

在大数据时代&#xff0c;中小企业信用评价具有重要的意义。中小企业是经济社会发展的重要力量&#xff0c;他们对就业、经济增长和创新发挥着重要作用。然而&#xff0c;中小企业信用评价面临各种挑战&#xff0c;比如&#xff0c;中小企业融资难的原因就在于信用评价难&#…

nginx-QPS限制

漏桶算法&#xff1a; 通过nginx配置实现QPS限速。 #设置请求并发量 qps1&#xff0c;不设置burst&#xff0c;会同时处理并发的请求&#xff0c;但是由于我们只设置了1个qps&#xff0c;所以同一时间内的请求&#xff0c;只有一个是正常的&#xff0c;其他都是失败的。 http配…

andriod studio 手机模拟器中的文件导出方法

阅读前请看一下&#xff1a;我是一个热衷于记录的人&#xff0c;每次写博客会反复研读&#xff0c;尽量不断提升博客质量。文章设置为仅粉丝可见&#xff0c;是因为写博客确实花了不少精力。希望互相进步谢谢&#xff01;&#xff01; 文章目录 阅读前请看一下&#xff1a;我是…

让你的编程之路更加顺畅——推荐一款前端编程神器

引子&#xff1a;在当今的数字化时代&#xff0c;编程已经成为一种不可或缺的技能。而前端开发&#xff0c;作为整个应用程序的“门面”&#xff0c;更是需要开发人员具备优秀的网页设计和编程能力。今天&#xff0c;我要向大家推荐一款专门为前端开发者打造的APP&#xff0c;它…

leetcode LCR 007 mid. 三数之和。对撞指针解法

题目 算法 对撞指针。双指针的一种&#xff0c;特点是一前一后&#xff0c;相向而行&#xff0c;两个指针相遇时为终点 code var threeSum function(nums) {let len nums.lengthnums.sort((a,b) > a-b)// 元素不足3个, 或 最小值>0 或 最大值<0&#xff0c;不会出…

插件_创蓝图文滑动验证码

目录 [1] 准备工作[2]使用1(1) 引入验证码js(2) 定义button引入js(3)在恰当的时机调起验证图(4) 校验之后的回调 [3] 使用2(1) 引入验证码js(2) 定义Captcha构造函数引入js(3)在恰当的时机调起验证图(4) 校验之后的回调 在进行低价秒杀时需要做一个人机校验防止机器抢购&#x…

切分支解决切不走因为未合并的路径如何解决

改代码的时候改做分支了&#xff0c;本来是在另一个分支上面改代码&#xff0c;结果改到另一个放置上面&#xff0c;然后想着使用git stash进行保存&#xff0c;然后切到另外一个分支再pop&#xff0c;结果不行。 报这个错误&#xff0c;导致切不过去&#xff0c;因为我这边pop…

SpringMVC常用注解、参数传递、返回值

目录 前言 一、常用注解 二、参数传递 ​编辑 1. 基础类型String类型 2. 复杂类型 3. RequestParam 4. PathVariable 5.RequestBody 6. RequestHeader 三、方法返回值 一&#xff1a;void 二&#xff1a;String 三&#xff1a;Stringmodel 四&#xff1a;ModelAndVi…

【HCIE】01.IGP高级特性

高级特性&#xff1a;一条命令解决一个问题 OSPF快速收敛机制 发生故障重新计算拓扑的过程叫做收敛&#xff0c;设备现在本身就是PRC算法和I-SPF算法 PRC&#xff08;针对叶子节点&#xff0c;叶子代表路由&#xff09; 不需要命令配置&#xff0c;就是ospf的特性&#xff…

我国智慧燃气建设应用过程中,有哪些关键问题?

关键词&#xff1a;智慧燃气、智慧燃气系统、智能燃气、燃气智能管控、数字孪生、智慧燃气平台 国内智慧燃气建设应用过程中需要解决以下4个关键问题&#xff1a; 01 广泛生产单元的感知能力建设方面的问题 智慧燃气的核心特征是“智慧”&#xff0c;具备“三个实现”即实现…

【AI Agent】Agent的原理介绍与应用发展思考

文章目录 Agent是什么&#xff1f;最直观的公式Agent决策流程 Agent 大爆发人是如何做事的&#xff1f;如何让LLM替代人去做事?来自斯坦福的虚拟小镇架构记忆&#xff08;Memory&#xff09;反思&#xff08;Reflection&#xff09;计划&#xff08;Plan&#xff09; 类 LangC…

pycharm创建py文件时自动添加基础信息--模板

在图片中加入下面基本信息&#xff0c;这些基本信息可以自己定义&#xff1a; #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : ${DATE} ${TIME} # Author : supermps # File : ${NAME}.py # Software : ${PRODUCT_NAME} import logging import math import w…

【群智能算法改进】一种改进的鹈鹕优化算法 IPOA算法[1]【Matlab代码#57】

文章目录 【获取资源请见文章第5节&#xff1a;资源获取】1. 原始POA算法2. 改进后的IPOA算法2.1 Sine映射种群初始化2.2 融合改进的正余弦策略2.3 Levy飞行策略 3. 部分代码展示4. 仿真结果展示5. 资源获取 【获取资源请见文章第5节&#xff1a;资源获取】 1. 原始POA算法 此…