前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >快速搭建Spring Boot项目及常用技术整合

快速搭建Spring Boot项目及常用技术整合

作者头像
一觉睡到小时候
发布2019-12-13 14:07:23
8870
发布2019-12-13 14:07:23
举报

Spring Boot简介

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。

Spring Boot特点

  • 创建独立的Spring应用程序
  • 嵌入的Tomcat,无需部署WAR文件
  • 简化Maven配置
  • 自动配置Spring
  • 提供生产就绪型功能,如指标,健康检查和外部配置
  • 绝对没有代码生成并且对XML也没有配置要求

快速入门

1、访问http://start.spring.io/构建项目,也可在idea创建如下图:
step1.png
step1.png

step2.png
step2.png

step3.png
step3.png
step4.png
step4.png
2、 springboot默认生成三个文件
2.1 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 http://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.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

重点就一个gav:spring-boot-starter-web,其他可以删除。

2.2 application.properties

该文件默认为空,springboot的默认启动端口号:8080,可以在改文件修改。建议用yml的格式

server:
  port: 8080
2.3 启动类文件
public class JxcApplication {

    public static void main(String[] args) {
        SpringApplication.run(JxcApplication.class, args);
    }

}
2.4 验证springboot

在项目包路径下创建一个Controller,写一个HelloController

@Controller
public class HelloController {

    @RequestMapping("/")
    @ResponseBody
    public String getHello() {
        return "hello";
    }
}

浏览器查看效果

HelloController.png
HelloController.png

完成项目

完整项目目录
project.png
project.png
1、项目依赖
  • web
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

      <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectjweaver.version}</version>
        </dependency>
  • mysql
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
  • lombok(可选)
       <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
  • pagehelper(可选)
       <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pagehelper.version}</version>
        </dependency>
  • JWT(可选)
       <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jwt.version}</version>
        </dependency>
  • mybatis
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.2</version>
        </dependency>
  • shiro
       <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
  • hutool(可选)
<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.0.7</version>
        </dependency>
  • druid
       <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
  • jdbc
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
  • fastjson
      <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
  • tomcat
       <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
        </dependency>

附上properties

<properties>
        <project.version>1.0</project.version>
        <java.version>1.8</java.version>
        <mysql.version>5.1.25</mysql.version>
        <pagehelper.version>1.2.12</pagehelper.version>
        <jwt.version>0.9.1</jwt.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <commons.lang.version>3.9</commons.lang.version>
        <aspectjweaver.version>1.9.4</aspectjweaver.version>
        <fastjson.version>1.2.62</fastjson.version>
    </properties>
2、配置文件
2.1修改`application.properties`为`application.yml`

配置端口,项目根路径,spring配置,mybatis配置,分页插件配置

server:
  port: 8100
  servlet:
    context-path: /api


spring:
  profiles:
    active: dev
  http:
    encoding:
      charset: UTF-8
      force: true
      enabled: true

mybatis:
  mapper-locations: classpath:/mapper/*.xml
  type-aliases-package: com.example.jxc.domain.entity.*
  configuration:
    cache-enabled: true
    lazy-loading-enabled: true
    multiple-result-sets-enabled: true
    use-column-label: true
    call-setters-on-nulls: true
    local-cache-scope: session
    map-underscore-to-camel-case: true
    default-executor-type: BATCH
    auto-mapping-behavior: PARTIAL

pagehelper:
  helperDialect: mysql
  reasonable: true
  supportMethodsArguments: true
  params: count=countSql
2.2 新建`application-dev.yml`

配置数据库信息,通过application.yml中的active来启用dev配置文件

spring:
  profiles:
    active: dev

application-dev.yml完整配置

spring:
  datasource:
    #   数据源基本配置
    username: root
    password:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/fhshgl
    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
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
3、数据库连接池
@Configuration
public class DruidConfig {

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druid(){
        return  new DruidDataSource();
    }

    /**
     * 配置Druid的监控
     * @return
     */
    @Bean
    public ServletRegistrationBean statViewServlet(){
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        Map<String,String> initParams = new HashMap<>();

        initParams.put("loginUsername","admin");
        initParams.put("loginPassword","123456");
        //默认就是允许所有访问
        initParams.put("allow","");
        initParams.put("deny","192.168.15.21");

        bean.setInitParameters(initParams);
        return bean;
    }


    /**
     * 配置一个web监控的filter
     * @return
     */
    @Bean
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        Map<String,String> initParams = new HashMap<>();
        initParams.put("exclusions","*.js,*.css,/druid/*");

        bean.setInitParameters(initParams);

        bean.setUrlPatterns(Arrays.asList("/*"));

        return  bean;
    }
}
4、shiro
4.1自定义realm
realm.png
realm.png
public class MyRealm extends AuthorizingRealm{

    @Autowired
    private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //拿到封装好账户密码的token
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String userName = token.getUsername();
        //用户校验
        User user = this.userService.getUser(userName);
        if (user == null) {
            throw new AuthenticationException("用户名或密码错误!");
        }
        //加盐 计算盐值 保证每个加密后的 MD5 不一样
        ByteSource credentialsSalt = ByteSource.Util.bytes(user.getUsername());
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), credentialsSalt,
                this.getName());
        return info;
    }
}
4.2shiro配置
@Configuration
public class ShiroConfig {

    /**
     * 主要配置一些相应的URL的规则和访问权限
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        //拦截器.
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/system/logout", "anon");
        //过滤链定义,从上向下顺序执行,一般将/**放在最为下边
        //authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
//        filterChainDefinitionMap.put("/static/**", "anon");
        shiroFilterFactoryBean.setLoginUrl("/system/login");
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }


    /**
     * 注入 securityManager
     */
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(customRealm());
        return securityManager;
    }

    /**
     * 自定义身份认证 realm;
     * <p>
     * 必须写这个类,并加上 @Bean 注解,目的是注入 MyRealm,
     * 否则会影响 MyRealm 中其他类的依赖注入
     */
    @Bean
    public MyRealm customRealm() {
        return new MyRealm();
    }


    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
     *
     * @return
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * Shiro生命周期处理器 ---可以自定的来调用配置在 Spring IOC 容器中 shiro bean 的生命周期方法.
     *
     * @return
     */
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
}
5、过滤器-跨域过滤
5.1跨域过滤
public class CostFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        String origin = req.getHeader("Origin");
        if (origin == null) {
            origin = req.getHeader("Referer");
        }
        // 允许指定域访问跨域资源
        resp.setHeader("Access-Control-Allow-Origin", origin);
        // 允许客户端携带跨域cookie,此时origin值不能为“*”,只能为指定单一域名
        resp.setHeader("Access-Control-Allow-Credentials", "true");

        if ("OPTIONS".equals(req.getMethod())) {
            String allowMethod = req.getHeader("Access-Control-Request-Method");
            String allowHeaders = req.getHeader("Access-Control-Request-Headers");
            // 浏览器缓存预检请求结果时间,单位:秒
            resp.setHeader("Access-Control-Max-Age", "86400");
            // 允许浏览器在预检请求成功之后发送的实际请求方法名
            resp.setHeader("Access-Control-Allow-Methods", allowMethod);
            // 允许浏览器发送的请求消息头
            resp.setHeader("Access-Control-Allow-Headers", allowHeaders);
            resp.setHeader("Content-Type", "application/json;charset=utf-8");
            return;
        }
        chain.doFilter(request, response);
    }
}
5.2 过滤器配置
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean configureFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean<>();
        bean.setName("costFilter");
        CostFilter costFilter = new CostFilter();
        bean.setFilter(costFilter);
        bean.setOrder(1);
        List<String> urlList = new ArrayList<String>();
        urlList.add("/*");
        bean.setUrlPatterns(urlList);
        return bean;
    }
}
6、token拦截
6.1JWT

jwt工具类

public class JwtUtils {

    public static SecretKey getBase64Key() {
        String stringKey = "MyJwtSecret";
        byte[] encodeKey = Base64.getDecoder().decode(stringKey);
        SecretKey key = new SecretKeySpec(encodeKey, 0, encodeKey.length, "AES");
        return key;
    }

    /**
     * 签发token
     *
     * @param userName 用户名
     * @return token
     */
    public static String create(String userName) {
        Date now = new Date(System.currentTimeMillis());
        String token = Jwts.builder()
                .setIssuedAt(now)
                .setSubject(userName)
                .setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 1000))
                .signWith(SignatureAlgorithm.HS256, getBase64Key())
                .compact();

        return token;
    }

    /**
     * 解析token
     *
     * @param token token
     * @return 用户名
     */
    public static String parse(String token) {
        String username = null;
        try {
            username = Jwts.parser()
                    .setSigningKey(getBase64Key())
                    .parseClaimsJws(token.replace("Bearer ", ""))
                    .getBody()
                    .getSubject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return username;
    }

    /**
     * 检验token是否过期
     *
     * @param token
     * @return
     */
    public static boolean verify(String token) {
        Date expiraDate = null;
        Date currentDate = new Date();
        try {
            expiraDate = Jwts.parser()
                    .setSigningKey(getBase64Key())
                    .parseClaimsJws(token.replace("Bearer ", ""))
                    .getBody()
                    .getExpiration();
            if (currentDate.before(expiraDate)) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }
}
6.2token拦截器
@Component
public class TokenInterceptor implements HandlerInterceptor {

    public Log log = LogFactory.getLog(TokenInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        if (request.getMethod().equals("OPTIONS")) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        response.setCharacterEncoding("utf-8");
        String token = request.getHeader("Authorization");
        if (token != null) {
            boolean result = JwtUtils.verify(token);
            if (result) {
                return true;
            }
        }
        log.error("认证失败");
        response.setStatus(HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION);
        return false;
    }
}
6.3配置拦截器
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {

    @Autowired
    private TokenInterceptor tokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/**/login")
                .excludePathPatterns("/**/logOut");
    }
}
7、完成一个登录接口`LoginController`
@RestController
@RequestMapping("/system")
public class LoginController extends BaseController {

    @Autowired
    private UserService userService;

    /**
     * 浏览器点击登录
     *
     * @param user
     * @return
     */
    @PostMapping("/login")
    public R login(@RequestBody User user) {
        log.debug("------浏览器点击登录------");
        String userName = user.getUsername();
        String passWord = user.getPassword();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, MD5.md5Salt(passWord, userName));
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(usernamePasswordToken);
            String token = JwtUtils.create(userName);
            return R.ok(R.SUCCESS, R.MSG_SUCCESS, token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
            return R.error(R.MSG_LOGIN_ERROR);
        }
    }
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 国产程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring Boot简介
  • Spring Boot特点
  • 快速入门
    • 1、访问http://start.spring.io/构建项目,也可在idea创建如下图:
      • 2、 springboot默认生成三个文件
        • 2.1 pom.xml
        • 2.2 application.properties
        • 2.3 启动类文件
        • 2.4 验证springboot
    • 完成项目
      • 完整项目目录
        • 1、项目依赖
          • 2、配置文件
            • 2.1修改`application.properties`为`application.yml`
            • 2.2 新建`application-dev.yml`
          • 3、数据库连接池
            • 4、shiro
              • 4.1自定义realm
              • 4.2shiro配置
            • 5、过滤器-跨域过滤
              • 5.1跨域过滤
              • 5.2 过滤器配置
            • 6、token拦截
              • 6.1JWT
              • 6.2token拦截器
              • 6.3配置拦截器
            • 7、完成一个登录接口`LoginController`
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档