SpringBoot中启动自带首页(配置类的深入讨论)--【CommandLineRunner】

SpringBoot系列文章目录

SpringBoot知识范围-学习步骤–【思维导图知识范围】

本系列校训

用免费公开视频,卷飞培训班哈人!打死不报班,赚钱靠狠干!
只要自己有电脑,前后项目都能搞!N年苦学无人问,一朝成名天下知!

SpringBoot技术很多很多

本文专门讨论 CommandLineRunner的使用,必须要依赖于org.springframework.boot,所以项目必须要是springBoot 的项目
在这里插入图片描述

韩顺平说:学习JAVA的人有两大难
第一困惑,JAVA能百度到的知识太多太多,完全不知道学啥
第二困惑,就是不知道以什么样的顺序去学,有的时候乱看一堆视频有遗漏,有的时候,两边的视频还有重复。
建议,学习完右侧的技术之后,就应该投入到项目的学习当中,在项目里去学习左侧的技术会好很多。
Spring的外围技术就更多了。本例也是springBoot的外围技术,不过并不在下面的图表之中。
在这里插入图片描述
所以,学习东西要系统一些,如果基本功不够,那后面的技术就会学的很浮。

环境及工具:

本系列环境

环境win11
工具idea 2018
jdk1.8
数据库本例不需要
maven3.2.1
项目导入方式maven 导入
数据库前端工具本例不需要

数据库前端工具:mysql-front (navicat 也可以)
主要是这些跟PHPStudy 2018 整合了,所以有的时候懒的打开navicat
关于环境的重要性,直接看上面的《SpringBoot 的项目编译即报错处理–JSB系列之001

必要的知识

配置类
这里深入的讨论一下配置类。

项目启动时需要加载多个配置类,且需要控制某些配置类的加载顺序。使用@Configuration标注配置类,使用@AutoConfigureAfter、@AutoConfigureBefore设置配置类加载顺序。
结果:能够正常加载配置类,但无法控制配置类的加载顺序。

几个注解 @ComponentScan:自动扫描组件。value
指定扫描的包路径,将包路径下标识了需要装配的类(@Controller,@Service,@Repository,@Configuration等)自动装配到Spring的bean容器中。
启动SpringBoot时,如果配置了@ComponentScan,则扫描包路径为配置的包路径;如果没配置@ComponentScan,扫描包路径默认为SpringBootApplication启动类所在的包路径。

@Configuration:修饰类,表明当前类是一个配置类,如果该类在@ComponentScan指定的包路径下,那么在启动SpringBoot时,就会自动将该类装配到Spring的Bean容器中。
@AutoConfigurationAfter:表明当前配置类在某一个配置类加载后加载。
@AutoConfigurationBefore:表明当前配置类在某一个配置类加载前加载。

常见的配置类

1: 跨域请求后端解决方案

package com.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

//解决跨域问题
@Configuration
public class CrosConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET","POST","HEAD","PUT","DELETE")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }

	// 如果同时配置了拦截器,上面的方法就会失效,可以使用下面的方式解决跨域问题
	    /**
     * 问题:配置 JWT ,使用拦截器出现跨域问题
     * 跨越配置
     * 改用过滤器CorsFilter 来配置跨域,由于Filter的位置是在Interceptor之前的,问题得到解决:
     */

    @Autowired
    JWTInterceptor jwtInterceptor;

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        // 设置允许跨域请求的域名
        config.addAllowedOrigin("*");
        // 是否允许证书 不再默认开启
         config.setAllowCredentials(true);
        // 设置允许的方法
        config.addAllowedMethod("*");
        // 允许任何头
        config.addAllowedHeader("*");
        config.addExposedHeader("token");
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        return new CorsFilter(configSource);
    }
}

2: 编码解决静态文件不加载

package com.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import com.interceptor.AuthorizationInterceptor;

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport{
	
	/**
	 * springboot 2.0配置WebMvcConfigurationSupport之后,会导致默认配置被覆盖,要访问静态资源需要重写addResourceHandlers方法
	 */
	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/**")
        .addResourceLocations("classpath:/resources/")
        .addResourceLocations("classpath:/static/")
        .addResourceLocations("classpath:/admin/")
        .addResourceLocations("classpath:/front/")
        .addResourceLocations("classpath:/public/");
		super.addResourceHandlers(registry);
    }
}

3:MVC 拦截器配置

主要是防用户不登陆 穿透后面的URL(就是直接输入URL访问后面权限控制的页面)

package com.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import com.interceptor.AuthorizationInterceptor;

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport{
	
	@Bean
    public AuthorizationInterceptor getAuthorizationInterceptor() {
        return new AuthorizationInterceptor();
    }
	
	@Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getAuthorizationInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**");
        super.addInterceptors(registry);
	}
	
	/**
	 * springboot 2.0配置WebMvcConfigurationSupport之后,会导致默认配置被覆盖,要访问静态资源需要重写addResourceHandlers方法
	 */
	@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/**")
        .addResourceLocations("classpath:/resources/")
        .addResourceLocations("classpath:/static/")
        .addResourceLocations("classpath:/admin/")
        .addResourceLocations("classpath:/front/")
        .addResourceLocations("classpath:/public/");
		super.addResourceHandlers(registry);
    }
}

4:上传路径存储位置

package com.spring.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfigure implements WebMvcConfigurer {

    /**
     * 设置上传路径存储位置,默认放在运行目录下的 upload
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 设置方位地址
        System.out.println(Configure.UPLOAD_DIR);
        registry
            .addResourceHandler("/upload/**")
            .addResourceLocations("file:" + Configure.UPLOAD_DIR)
            .addResourceLocations("file:" + System.getProperty("user.dir") + "/src/webapp/upload/");
    }
}

5:防SQL注入

package com.spring.config;

import com.jntoo.db.Configuration;
import com.jntoo.db.QueryConfig;
import javax.annotation.Resource;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * 配置数据库访问源
 */
@Component
public class QueryConfigRuntime implements ApplicationRunner {

    @Resource
    private QueryConfigConnect config;

    /**
     * Callback used to run the bean.
     *
     * @param args incoming application arguments
     * @throws Exception on error
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        QueryConfig queryConfig = new QueryConfig();
        queryConfig.setPrefix("");
        queryConfig.setConnectionConfig(config);
        queryConfig.setDebug(true);
        Configuration.setQueryConfig(queryConfig);
    }
}

6: 数据库的里自动日期(创建日期,修改日期等)

在后台这里生成,比前台的准,比数据库里的移植性强。
不过,要求这些字段取一致的字段名

package com.config;

import java.util.Date;

import org.apache.ibatis.reflection.MetaObject;

import com.baomidou.mybatisplus.mapper.MetaObjectHandler;

/**
 * 自定义填充处理器
 */
public class MyMetaObjectHandler extends MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("ctime", new Date(), metaObject);
    }

    @Override
    public boolean openUpdateFill() {
        return false;
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        // 关闭更新填充、这里不执行
    }
}

另外:封装统一返回结果集时,解决返回 null 值显示

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;

/**
 * 使用 SpringBoot 默认的 jackjson 解决 统一结果集为空的情况
 * */


@Configuration
public class NullValueConfiguration {
    
    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();
        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, IOException {
                jsonGenerator.writeString("");
            }
        });
        return objectMapper;
    }
}

本文也是一种配置类。实用性很强。学起来容易。
就是一个项目,经过了一段时间之后,经常是找不到开始的首页了。有一些项目不太方便在index.html里跳转。

那么,本文的这个配置类就可以登场了。

public class AutoStartProjectInDefaultBrowser implements CommandLineRunner

也是取SpringBoot 里的类。
整体代码如下:

package com.config;

import java.lang.reflect.*;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringBootConfiguration;

/**
 * 系统启动后执行这里,运行浏览器
 */
@SpringBootConfiguration
public class AutoStartProjectInDefaultBrowser implements CommandLineRunner {

    @Value("${server.port}")
    private String port;

    @Value("${server.servlet.context-path}")
    private String path;

   String home_path = "/front/pages/login/login.html";

    /**
     * springboot自带的监听任务,启动浏览器
     *
     * @param args
     * @throws Exception
     */
    @Override
    public void run(String... args) throws Exception {
        try {
            String url = "http://localhost:" + port + path + home_path;
            browse(url);
            //Runtime.getRuntime().exec("cmd /c start http://localhost:" + port + ""+path);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static void browse(String url) {
        try {
            String osName = System.getProperty("os.name", "");
            if (osName.startsWith("Mac OS")) {
                Class fileMgr = Class.forName("com.apple.eio.FileManager");
                Method openURL = fileMgr.getDeclaredMethod("openURL", String.class);
                openURL.invoke(null, url);
            } else if (osName.startsWith("Windows")) {
                Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);
            } else {
                // Unix or Linux
                String[] browsers = {"firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape"};
                String browser = null;
                for (int count = 0; count < browsers.length && browser == null; count++) // 执行代码,在brower有值后跳出,
                    // 这里是如果进程创建成功了,==0是表示正常结束。
                    if (Runtime.getRuntime().exec(new String[]{"which", browsers[count]}).waitFor() == 0)
                        browser = browsers[count];
                if (browser == null) throw new Exception("Could not find web browser");
                else // 这个值在上面已经成功的得到了一个进程。
                    Runtime.getRuntime().exec(new String[]{browser, url});
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

就是本文啦。

代码位置。

在这里插入图片描述

Spring Boot启动类

把启动的用户,密码也记在启动类里

package com;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
@MapperScan(basePackages = {"com.dao"})
public class SpringbootSchemaApplication extends SpringBootServletInitializer{

	public static void main(String[] args) {
		SpringApplication.run(SpringbootSchemaApplication.class, args);
		System.out.println("点击后面的链接访问主页:");
		System.out.println("http://localhost:8080/springbootj470j/front/pages/login/login.html");
		System.out.println("前台用户密码:11/11");
		System.out.println("后台用户密码:admin/admin");

	}
	
	@Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
        return applicationBuilder.sources(SpringbootSchemaApplication.class);
        //http://localhost:8080/springbootj470j/front/pages/login/login.html

    }
}

最后的成果。
在这里插入图片描述

另外:
还可以在启动类里记录下项目的其它的配置要求:
数据源里的datasource 的名字。用户名,密码。还有就是mysql 的驱动是com.mysql.jdbc.Driver
总的来说,
com.mysql.jdbc.Driver 是 mysql-connector-java 5.5之前的,
com.mysql.cj.jdbc.Driver 是 mysql-connector-java 6及6之后的的,
初学者容易陷入一个误区,就是什么东西最新版是最好的,事实上很有可能他写的东西,明明JDK6.0就完全足够。一边喊着自己的机器内存不足,一边让内存运行着他自己用不到的东西。就比如说idea应该算是这些开发者工具里最卡的。有人可能明明只是打开几个网页,那为什么不使用webstorm? 甚至不是写很多代码的时候,为什么不选择更轻量级的VSCode?

配套资源

配套资源

作业:

无,看懂即是神
学SpringBoot,里面的东西很多,没有人可以在工作之前都能碰得到,经验的积累才是工作中顺利晋升的关键

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

项目花园范德彪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值