Spring Boot 2.0 教程

  • Spring Boot 入门教程 一、Spring Boot 是什么 以下截图自 Spring Boot 官方文档: 翻译整理一下,内容如下: Spring Boot 是基于 Spring 框架基础上推出的一个全新的框架, 旨在让开发者可以轻松...
    • 1年前
  • Spring Boot Starter Parent 什么是 Spring Boot Starter Parent ? 通过 Spring Boot Starter Parent, 我们可以进行简单便捷地包依赖管理。在 Spring Boot 每...
    • 1年前
  • Spring Boot 热部署 相信小伙伴们在日常的开发中,调试代码时,免不了经常修改代码,这个时候,为了验证效果,必须要重启 Spring Boot 应用。 频繁地重启应用,导致开发效率降低,加班随之而来。有没有什么办法,能让 Spring B...
    • 1年前
  • 一、工程目录 二、Mybatisplus多数据源配置 1、pom.xml <dependency> <groupId>com.baomidou</groupId> <artifactId>myba...
    • 1月前
  • 欢迎关注博主公众号「java大师」, 回复【dsblog】获取源码 一、效果图展示 一、网站前台 1、首页 2、内容页 3、最新文章页面 二、网站后台 1、登录页 2、首页 3、栏目管理 4、文章管理 三、后端(swa...
    • 3月前
  • springboot上传头像 @Controller @RequestMapping("/upload") public class UploadController { private Logger logger = LoggerFactory...
    • 3月前
  • springboot处理blog字段 欢迎关注博主公众号「Java大师」, 专注于分享Java领域干货文章https://www.javaman.cn/ 1、数据库表结构 其中content为longblob字段,代表存入的内容 CREA...
    • 4月前
  • 手撸一个springsecurity,了解一下security原理 今天手撸一个简易版本的springsecurity,带大家理解下springsecurity的原理: 安全框架的两个特点就是认证和授权,让我们来通过代码了解下认证和授权的处理方式...
    • 7月前
  • SpringBoot2.0之@Configuration注解 前面我们介绍了Spring boot2.0的启动和第一个helloworld实例,今天我们来讲解一下springboot2.0比较关键的注解@Configuration 在讲解@C...
    • 1年前
  • Spring Boot 配置 log4j2 欢迎关注博主公众号「java大师」, 专注于分享Java领域干货文章, 关注回复「资源」, 免费领取全网最热的Java架构师学习PDF, 转载请注明出处 https://www.exception.si...
    • 1年前
springboot+springsecurity+elementui博客系统-dsblog - idea激活- IntelliJ IDEA 2021.1激活码破解教程(亲测激活至 2099 年,长期更新)- 爪哇男教程  

欢迎关注博主公众号「java大师」, 回复【dsblog】获取源码

一、效果图展示

一、网站前台

1、首页

在这里插入图片描述

在这里插入图片描述

2、内容页

在这里插入图片描述

在这里插入图片描述

3、最新文章页面

在这里插入图片描述

二、网站后台

1、登录页

在这里插入图片描述

2、首页

在这里插入图片描述

3、栏目管理

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4、文章管理

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

三、后端(swagger-ui)

在这里插入图片描述

二、 确定需求方案

后台进行栏目和文章的编辑,编辑完后前台展示。

三、整体架构设计

  1. 前端基于Vue+ElementUi,使用WebStorm编辑器;
  2. 后端基于Springboot+SpringSecurity+MyBatisPlus+JWT+Redis实现,使用 IDEA 编辑器;
  3. 数据传输格式:JSON;
  4. 数据库:mysql

三、编码实现 (关键代码)

1、前端Vue代码 - main.js

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import router from './router'
import store from './store'
import {initMenu} from  '/src/utils/menus'
import {getUserInfo} from  '/src/utils/http'
import 'font-awesome/css/font-awesome.css'
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css';

Vue.config.productionTip = false

Vue.use(ElementUI);
Vue.use(mavonEditor)

router.beforeEach((to,from,next)=>{
	if(window.sessionStorage.getItem("token")){
		initMenu(router,store);
		console.log(router);
		if(!window.sessionStorage.getItem('user')){
			return getUserInfo().then(res=>{
				window.sessionStorage.setItem('user',JSON.stringify(res));
				next();
			})
		}
		next();
	}else{
		if(to.path=='/'){
			next();
		}else{
			next('/?redirect='+to.path);
		}
	}
})

new Vue({
	el: '#app',
	router,
	store,
	render: h => h(App),
}).$mount('#app')

2、前端JS代码 - 动态路由

import {
	getNav
} from './http.js'

export const initMenu = (router, store) => {
	if (store.state.routes.length > 0) {
		return;
	}

	getNav().then(data => {
		if (data) {
			let fmtRoutes = formatRoutes(data);
			//动态路由
			router.addRoutes(fmtRoutes);
			router.options.routes = fmtRoutes;
			//数据存入vuex
			store.commit('initRoutes',fmtRoutes);
		}
	})

}

export const dealPath=(path=>{
	return ((path.split('/')).length-1)>1?path.substring(path.indexOf("/"),path.lastIndexOf("/")):path.substring(path.indexOf("/"),path.length)
})


export const formatRoutes = (routes) => {
	let fmtRoutes = [];
	routes.forEach(router=>{
		let{
			path,
			component,
			name,
			iconCls,
			children
		} = router;
		if(children&&children instanceof Array){
			children = formatRoutes(children);
		}
		let fmtRouter = {
			path:path,
			name:name,
			iconCls:iconCls,
			children:children,
			component:()=>import(`../views${dealPath(path)}/${component}.vue`),
			// component:component
		}
		fmtRoutes.push(fmtRouter);
	})
	return fmtRoutes;
}

3、后端Java代码 SecurityConfig

package com.dsblog.server.config.security;

import com.dsblog.server.filter.CustomFilter;
import com.dsblog.server.filter.CustomUrlDecisionManager;
import com.dsblog.server.model.User;
import com.dsblog.server.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private IUserService userService;
    @Autowired
    private RestAuthorizationEntryPoint restAuthorizationEntryPoint;
    @Autowired
    private RestAccessDeniedHandler restAccessDeniedHandler;
    @Autowired
    private CustomFilter customFilter;
    @Autowired
    private CustomUrlDecisionManager customUrlDecisionManager;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
                "/login",
                "/logout",
                "/css/**",
                "/js/**",
                "/index.html",
                "favicon.ico",
                "/doc.html",
                "/webjars/**",
                "/swagger-resources/**",
                "/v2/api-docs/**",
                "/captcha",
                "/ws/**",
                "/static/**",
                "/api/**"
        );
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .anyRequest().authenticated()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setAccessDecisionManager(customUrlDecisionManager);
                        o.setSecurityMetadataSource(customFilter);
                        return o;
                    }
                })
                .and()
                .headers()
                .cacheControl();
        //添加Jwt登录授权拦截器
        http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        //添加未登录和未授权结果返回
        http.exceptionHandling()
                .accessDeniedHandler(restAccessDeniedHandler)
                .authenticationEntryPoint(restAuthorizationEntryPoint);

    }

    @Override
    @Bean
    public UserDetailsService userDetailsService(){
        return username -> {
            User user = userService.getUserByUsername(username);
            if(null!=user){
                user.setRoles(userService.getRoles(user.getId()));
                return user;
            }
            throw new UsernameNotFoundException("用户名或密码不正确");
        };
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public  JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){
        return new JwtAuthenticationTokenFilter();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource(){
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:8080"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",configuration);
        return source;
    }
}

4、后端Java代码 swagger配置

package com.dsblog.server.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableSwagger2
public class Swagger2Config {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .pathMapping("/")
                .apiInfo(apiInfo())
                .select()
                //swagger要扫描的包路径
                .apis(RequestHandlerSelectors.basePackage("com.dsblog.server.controller"))
                .paths(PathSelectors.any())
                .build()
                .securityContexts(securityContexts())
                .securitySchemes(securitySchemes());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder().title("dsblog接口文档")
                .contact(new Contact("java大师","http://localhost:8081/doc.html","fry000@qq.com"))
                .version("1.0").description("dsblog接口文档").build();
    }

    private List<SecurityContext> securityContexts() {
        //设置需要登录认证的路径
        List<SecurityContext> result = new ArrayList<>();
        result.add(getContextByPath("/.*"));
        return result;
    }

    private SecurityContext getContextByPath(String pathRegex) {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex(pathRegex))
                .build();
    }

    private List<SecurityReference> defaultAuth() {
        List<SecurityReference> result = new ArrayList<>();
        AuthorizationScope authorizationScope = new AuthorizationScope("global",
                "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        result.add(new SecurityReference("Authorization", authorizationScopes));
        return result;
    }

    private List<ApiKey> securitySchemes() {
        //设置请求头信息
        List<ApiKey> result = new ArrayList<>();
        ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");
        result.add(apiKey);
        return result;
    }

}

# 四、开发配置&代码结构说明

## 1、Java开发环境配置

![图片](https://img-blog.csdnimg.cn/img_convert/facc4116644c055e4996689af09d3eea.png)

 ![图片](https://img-blog.csdnimg.cn/img_convert/c186f6ad7dd5b837a632f609dd51efc7.png)



![图片](https://img-blog.csdnimg.cn/img_convert/6964f07d402e8f04edf634108b4474b4.png)

 然后GENERATE,下载包即可。

## 2、代码结构说明 

### a、项目路径

![在这里插入图片描述](https://img-blog.csdnimg.cn/442de78b283745568d81714f1b6b563d.png#pic_center)




### **b、application.yml配置**

![在这里插入图片描述](https://img-blog.csdnimg.cn/c0beb7d293bc4b0e94f41d7dd93cd277.png#pic_center)



全部评论: 0

    我有话说: