SpringBoot课程笔记

1. Web端

1.1 关于页面的一些布局
  • vue页面一般格式
<template>
  <NavBar /> //导航栏
  <router-view/> //路由根据网址显示出不同的页面
</template>

<script>
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap';
import NavBar from './components/NavBar';
export default {
  name: "App",
  components: {
    NavBar,
  },
}
  
</script>

<style scope>
body {
  background-image: url("https://s2.loli.net/2022/10/21/B5trdcDzO42JVKM.jpg");
  background-size: cover;
}
</style>
  • 引入bootstrap的头文件,在vue的app主页面引入即可
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/js/bootstrap';
  • 修改背景图片
background-image: url("背景图片地址");
background-size: cover;
1.2 关于Router的使用
  • /:catchAll(.*)表示所有链接
  • path为通过什么链接来访问该页面
  • name为该页面的别名
  • redirect为重定向到那个链接
  • component 和 import导入名字对应
  • meta是自定义的一个功能用于页面的授权访问
  • /:id/ -->表示id是参数
import { createRouter, createWebHistory } from 'vue-router'

// 用到什么页面就引入什么页面 
import PKIndexView from '../views/pk/PKIndexView'
import NotFound from '../views/error/NotFound'

const routes = [
 {
   path: "/",
   name: "home",
   redirect: "/pk/",
   meta: {
     requestAuth: true,
   },
 },
{
   path: "/pk/:id/",
   name: "pk_index",
   component: PKIndexView,
   meta: {
     requestAuth: true,
   },
 },
 {
   path: "/404/",
   name: "404",
   component: NotFound,
   meta: {
     requestAuth: false,
   },
 },
 {
   path: "/:catchAll(.*)",
   redirect: "/404/",
 },
 
]

const router = createRouter({
 history: createWebHistory(),
 routes
})

router.beforeEach((to, from, next) => {
 if (to.meta.requestAuth && !store.state.user.is_login) {
   next({name: 'user_account_login'});
 } else {
   next();
 }
})

export default router
  • 该函数为访问所有页面前执行的函数
  • router.push({name: ‘路由的别名’,params: {参数x:实参x}}); --> 在任意页面这么写都可实现页面跳转(头文件需引入该页面)
router.beforeEach((to, from, next) => {
  if (to.meta.requestAuth && !store.state.user.is_login) {
    next({name: 'user_account_login'});
  } else {
    next();
  }
1.3 一些细节
1.3.1 active
  • 那个标签class含有active那个标签被选中在bootstrap中
1.3.2 v-model
  • 在标签中使用这可让标签里面的内容与某个属性绑定在一起
1.3.3 localStorage的使用
localStorage.setItem("jwt_token", resp.token);
localStorage.removeItem("jwt_token");
localStorage.getItem("jwt_token");
1.3.4 store的使用
  • commit用于修改全局变量访问mutations中的方法,同步
  • dispatch用于访问actions中的方法,异步
 store.commit('updateToken', jwt_token);
 store.dispatch("getinfo", {
     success() {
         router.push({name: 'home'});
         store.commit("updatePullingInfo", false);
     },
     error() {
         store.commit("updatePullingInfo", false);
     }
 });
1.3.5 JSON的使用
  • stringify用于将json转为字符串(用于数据传输)
JSON.stringify({
    event: "move",
    direction: d,
})
  • parse用于将json的字符串转换为json
JSON.parse(msg.data)
1.3.6 v-for的使用
  • v-for要绑定id
v-for="user in users" :key="user.user.id"
1.3.7 代码编辑框和模态框
  • Modal模态框通过id隐藏
import { Modal } from 'bootstrap/dist/js/bootstrap';
Modal.getInstance("#add-bot-btn").hide();
  • 代码编辑框安装依赖:vue3-ace-editor
import { VAceEditor } from 'vue3-ace-editor';
import ace from 'ace-builds';
ace.config.set(
    "basePath", 
    "https://cdn.jsdelivr.net/npm/ace-builds@" + require('ace-builds').version + "/src-noconflict/")
<VAceEditor
    v-model:value="botadd.content"
    @init="editorInit"
    lang="c_cpp"
    theme="textmate"
    style="height: 300px" />
1.3.8 页面加载和卸载
  • onMounted 页面加载(进入页面), onUnmounted页面卸载(离开页面)
import { onMounted, onUnmounted } from 'vue';
onMounted(页面加载时执行的函数);
onUnmounted(页面卸载时执行函数);
1.3.9 WebSocket协议(双端通信)
  • 定义: let socket = new WebSocket(socketUrl);
  • 主要接口:分别对应连接前,断开后,和接收消息(msg: json的string形式)
socket.onopen = () => {
     console.log("connection");
     store.commit("updateSocket", socket);
 };
 socket.onclose = () => {
     console.log("distconnection");
 };
 socket.onmessage = msg => {
 }
  • 发送消息: socket.send(JSON.stringify({json}));
1.3.10 导航栏
  • 链接页面展示: <router-view/>
  • 链接引用:<router-link :to="{name: 'router里页面定义的名字'}" />
1.3.11 Route(获取链接)
  • myRouter.name:可用于获取当前链接的别名
  • myRouter.query.x:可用于获取当前链接的参数x
import { useRoute } from 'vue-router';
const myRouter = useRoute();
1.3.12 computed (动态计算)
import { computed } from '@vue/reactivity';
let route_name = computed(() => route.name);
1.3.13 ajax访问jwt授权url时需加上以下内容
headers: {
  Authorization: "Bearer " + token,
},

2. 后端

2.1 pom.xml中一些常用的依赖
2.1.1 mysql连接的驱动
  • MySQL Connector/J
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.29</version>
</dependency>
2.1.2 JDBC的实现
  • Spring Boot Starter JDBC
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version>2.7.1</version>
</dependency>
  • application.properties配置jdbc的连接。
spring.datasource.username=root
spring.datasource.password=***
spring.datasource.url=jdbc:mysql://localhost:3306/kob?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver //mysql-8版本
spring.datasource.driver-class-name=com.mysql.jdbc.Driver //mysql-5版本
2.1.3 一个类的基本方法的实现(get,set …)
  • Project Lombok
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
    <scope>provided</scope>
</dependency>
2.1.4 数据库基本操作curd的实现
  • mybatis-plus-boot-starter
  • mybatis-plus-generator
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-generator -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.3</version>
</dependency>
2.1.5 安全机制的实现
  • spring-boot-starter-security
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.7.1</version>
</dependency>
  • 默认情况会封锁所有的url,登录账号为user、密码为项目启动是随机生成的字符串,若要更改登录为查询数据库账号密码需实现以下两个类:
  • UserDetailsServiceImpl、②UserDetailsImpl
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) {
            throw new RuntimeException("无该用户");
        }
        return new UserDetailsImpl(user);
    }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDetailsImpl implements UserDetails {

    private User user;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {//账户是否没有过期
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {//账户是否没有被锁定
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {//授权是否没有过期
        return true;
    }

    @Override
    public boolean isEnabled() {//是否被启用
        return true;
    }
}
  • 注: 在查询数据库密码时,会涉及到密码的存储方式问题{noop}***表示该密码***是明文密码,不加默认认为是密文。
  • 加密算法需自己在配置类中实现
@Configuration
@EnableWebSecurity
public class SecurityConfig {

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

补充:PasswordEncoder 的方法
encode("xxx")为加密字符串xxx
matches("aaa", "bbb")为判断bbb是否是aaa的加密字符串。

2.1.6 jwt验证
  • jjwt-api
  • jjwt-impl
  • jjwt-jackson
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
  • 登录时用于通过账号密码获取认证和jwt
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
         = new UsernamePasswordAuthenticationToken(username, password);
 //登录失败自动处理
 Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
 UserDetailsImpl loginUser = (UserDetailsImpl)authenticate.getPrincipal();
 User user = loginUser.getUser();
 String jwt = JwtUtil.createJWT(user.getId().toString());
  • 在授权成功后通过上下文获取user
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
        (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
UserDetailsImpl loginUser = (UserDetailsImpl) usernamePasswordAuthenticationToken.getPrincipal();
User user = loginUser.getUser();
2.1.7 websocket
  • spring-boot-starter-websocket
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
    <version>2.7.2</version>
</dependency>
2.1.8 json
  • fastjson
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.11</version>
</dependency>
2.1.9 joor(动态编译、执行Java代码)
  • joor-java-8
<dependency>
	<groupId>org.jooq</groupId>
	<artifactId>joor-java-8</artifactId>
	<version>0.9.14</version>
</dependency>
2.1.10 httpclient
  • httpclient
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>
2.1.11 redis
  • spring-boot-starter-data-redis
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.7.5</version>
</dependency>
2.2 在SpringBoot中的一些配置
2.2.1 解决跨域的配置
  • 添加配置类:CorsConfig
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
public class CorsConfig implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        String origin = request.getHeader("Origin");
        if(origin!=null) {
            response.setHeader("Access-Control-Allow-Origin", origin);
        }

        String headers = request.getHeader("Access-Control-Request-Headers");
        if(headers!=null) {
            response.setHeader("Access-Control-Allow-Headers", headers);
            response.setHeader("Access-Control-Expose-Headers", headers);
        }

        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");

        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) {

    }

    @Override
    public void destroy() {
    }
}
2.2.2 jwt认证的配置
  • 实现utils.JwtUtil类,为jwt工具类,用来创建、解析jwt token,其中有两个常用方法createJWT(id)通过id获取jwtparseJWT(jwt)通过jwt获取id
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

@Component
public class JwtUtil {
    public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14;  // 有效期14天
    public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232131afasdfac"; //密钥用的时候改一下不能太短,不能给别人看

    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static String createJWT(String subject) {
        JwtBuilder builder = getJwtBuilder(subject, null, getUUID());
        return builder.compact();
    }

    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        SecretKey secretKey = generalKey();
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        if (ttlMillis == null) {
            ttlMillis = JwtUtil.JWT_TTL;
        }

        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        return Jwts.builder()
                .setId(uuid)
                .setSubject(subject)
                .setIssuer("sg")
                .setIssuedAt(now)
                .signWith(signatureAlgorithm, secretKey)
                .setExpiration(expDate);
    }

    public static SecretKey generalKey() {
        byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256");
    }

    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(jwt)
                .getBody();
    }
}
  • 实现config.filter.JwtAuthenticationTokenFilter类,用来验证jwt token,如果验证成功,则将User信息注入上下文中。
import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import com.kob.backend.service.impl.utils.UserDetailsImpl;
import com.kob.backend.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    private UserMapper userMapper;

    @Override
    protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");

        if (!StringUtils.hasText(token) || !token.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);
            return;
        }

        token = token.substring(7);

        String userid;
        try {
            Claims claims = JwtUtil.parseJWT(token);
            userid = claims.getSubject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        User user = userMapper.selectById(Integer.parseInt(userid));

        if (user == null) {
            throw new RuntimeException("用户名未登录");
        }

        UserDetailsImpl loginUser = new UserDetailsImpl(user);
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser, null, null);

        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        filterChain.doFilter(request, response);
    }
}
  • 配置config.SecurityConfig类,放行登录、注册等接口。
import com.kob.backend.config.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

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

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/user/account/token/", "/user/account/register/").permitAll()
                .antMatchers(HttpMethod.OPTIONS).permitAll()
                .anyRequest().authenticated();

        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
2.2.3 分页的配置
@Configuration
public class MybatisConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
  • 用法
IPage<User> iPage = new Page<>(page, 8);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("rating");
List<User> users = userMapper.selectPage(iPage, queryWrapper).getRecords();
2.2.4 HttpClient的配置
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;

public class HttpClientUtil {
    public static String get(String url, List<NameValuePair> params) {
        URIBuilder uriBuilder = null;
        try {
            uriBuilder = new URIBuilder(url);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            return null;
        }
        uriBuilder.setParameters(params);

        try (CloseableHttpClient client = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            CloseableHttpResponse response = client.execute(httpGet);
            HttpEntity entity = response.getEntity();
            return EntityUtils.toString(entity);
        } catch (IOException | URISyntaxException e) {
            e.printStackTrace();
            return null;
        }
    }
}

用法:

List<NameValuePair> list = new ArrayList<>();
list.add(new BasicNameValuePair("appid", appId));
list.add(new BasicNameValuePair("secret", appSecret));
list.add(new BasicNameValuePair("code", code));
String data = HttpClientUtil.get(applyAccessTokenUrl, list);
2.3 各种注意事项
  • 在数据库中名称为user_id是在实体类需写成userId
  • 在自增的属性上加注解@TableId(type = IdType.AUTO)
  • 在时间的属性java.util.Date上加注解@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone="Asia/Shanghai")
  • 当静态属性需要注入时,需使用set注入,并且所有注入(包括非静态注入)都需要在该类上面加注解一般为@Component特殊情况使用别的。
  • 在动态执行Java代码时需单开一个线程执行避免死循环
this.start();
try{
    this.join(timeout);
} catch (InterruptedException e) {
    e.printStackTrace();
} finally {
    this.interrupt();
}
2.4 写项目时用的的一些类
2.4.1 WebSocket
  1. 添加配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
  1. 添加WebSocketServer
    • 一个类在添加@ServerEndpoint注解后该类为websocket类。
    • 每建立一个websocket连接相当于创建一个该类的对象。
    • @ServerEndpoint("/websocket/{token}"):为第一步配置类所配置的websocket注解,里面的内容为访问该websocket的url。
    • 后端向前端发送消息要使用一开始建立连接时的session注意这里的session是websocket包下的
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@Component
@ServerEndpoint("/websocket/{token}")  // 注意不要以'/'结尾
public class WebSocketServer {
	private Session session = null;
	
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        // 建立连接
        this.session= session;
    }

    @OnClose
    public void onClose() {
        // 关闭链接
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        // 从Client接收消息
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }
    
    public void sendMessage(String message) {
    	// 发送消息给远程连接
        synchronized (this.session) {
            try {
                this.session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  1. security中放行websocket的所有链接
    • 配置config.SecurityConfig
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/websocket/**");
}
2.4.2 RestTemplate(服务器之间通信、访问HTTP协议)
  1. 配置RestTemplateConfig类,使其可以被注入
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}
  1. RestTemplate中一些方法的详解: https://zhuanlan.zhihu.com/p/31681913
  2. 本项目用到的方法:postForObject(url, data, class)
    • url:请求地址。
    • data:请求参数。(这儿如果使用map需使用MultiValueMap
    • class:返回值的类型对应的class。
2.4.3 ReentrantLock
  1. 用途:处理多线程读写冲突
  2. 定义:ReentrantLock lock = new ReentrantLock()
  3. 使用
lock.lock();
try {
    // 执行的语句
} finally {
    lock.unlock();
}
2.4.4 JSONObject
  1. 定义:JSONObject resp = new JSONObject();
  2. string->json:resp = JSONObject.parseObject(message);
  3. json->string:String message = resp.toJSONString();
2.4.5 Reflect
  • 导包:import org.joor.Reflect;
  • 使用:
Reflect.compile(
        name, // 编译的类名
        content // 编译的类的内容
 ).create(
 	// 构造方法的参数
 ).get(); //获得该类的对象
2.4.6 UUID(用于获取一个随机字符串)
  • 配合Reflect来使用Reflect动态编译一个类每次类名不能重复因此需要在类名后加一个随机值。
  • 导包:import java.util.UUID;
UUID uuid = UUID.randomUUID();
String id = uuid.toString();
2.6.7 Condition
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
condition.await(); // 释放锁并且该线程阻塞
condition.signalAll(); // 唤醒所有阻塞(await)的线程
2.6.8 Redis
  • Linux服务器中启动redissudo redis-server /etc/redis/redis.conf
  • 在application.properties文件中的配置
spring.redis.host=localhost
spring.redis.port=6379
  • 用法:
@Autowired
private RedisTemplate<String, String> redisTemplate;

redisTemplate.opsForValue().set(state.toString(), "true");
redisTemplate.expire(state.toString(), Duration.ofMinutes(10)); //过期时间为10分钟

Boolean.FALSE.equals(redisTemplate.hasKey(state) //判断state是否存在/过期
2.5 Ubuntu下安装软件
2.5.1 mysql
  • 安装:sudo apt-get install mysql-server
  • 启动:sudo service mysql start
  • 设置root用户的密码:ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'yourpasswd';
  • 执行sql脚本:source xxx.sql;
2.5.2 jdk
  • 安装java8:ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'yourpasswd';
2.6 项目上线
  • 将后端代码打包成jar文件
<packaging>jar</packaging>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <!--这里写上main方法所在类的路径-->
            <configuration>
                <mainClass>com.kob.backend.BackendApplication</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
  • idea打包后端项目示例:先点击clean再点击package
  • 打包之后会在对应项目文件下的target目录下生成xxx.jar文件
  • 在linux服务器上输入java -jar xxx.jar运行该项目

三、AcApp端

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值