一个项目的记录:多人博客

笔记

Maven项目

  1. 从官网复制一份pom.xml
  2. 更改 maven mirror :
  • ~/.m2.setting.xml 影响全局
  • pom.xml 仅影响当前项目
  1. 按着官方文档创建一个Controller,一个Application
  2. 运行,成功。

依赖注入

Springboot推荐注解:官方文档

Spring Boot favors Java-based configuration. Although it is possible to use SpringApplication with XML sources, we generally recommend that your primary source be a single @Configuration class. Usually the class that defines the main method is a good candidate as the primary @Configuration.

1. 从XML配置加载Bean

创建 src/main/resources/applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- <context:component-scan base-package="com.in28minutes.spring.basics"/> -->
    <bean id="" class=""></bean>
</beans>

创建 configuration/XmlConfiguration.java

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource({"classpath*:applicationContext.xml"})
public class XmlConfiguration {
}

这样就大功告成了。但是xml方式是个古老的方式。。

2. 从Java配置加载Bean

创建 configuration/JavaConfiguration.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JavaConfiguration {
	@Bean
	public String someDummyBean1() {
		return "someDummyBean1";
	}
}

3. 自动装配

@Inject注解,需要引入javax.inject

一个小知识,记下来。转载于: @Autowired,@Inject,@Resource的区别:
1、@Autowired是spring自带的,@Inject是JSR330规范实现的
2、@Autowired、@Inject用法基本一样,不同的是@Autowired有一个request属性

连接数据库

Docker:-> MySQL
ORM:Object Relationship Mapping 对象关系映射 -> MyBatis

JPA:一个不需要写SQL的ORM框架?打个笔记,有时间专门看看。。。

参考的官方文档:mybatis-spring-boot-autoconfigure

创建 mapper/CityMapper.java

@Mapper
public interface CityMapper {
  @Select("SELECT * FROM CITY WHERE state = #{state}")
  City findByState(@Param("state") String state);
}

然后通过构造器注入mapper,但是发现还需要一个DataSource。
所以: 参考官方文档:Working with SQL Databases

MVC

Model View Controller

開始根據前端接口写模块

吭哧吭哧。。。。

security -> Springboot:Securing a Web Application

官方文档:保护Web应用程序

本指南将引导您完成使用受Spring Security保护的资源创建简单的Web应用程序的过程。

引入 pom.xml:

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

在configuration包里创建一个类:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}

现在所有请求都被拦截了。

@Override
protected void configure(HttpSecurity http) throws Exception {
	http
		.authorizeRequests()
			.antMatchers("/", "/home").permitAll()
			.anyRequest().authenticated()
}

这样又能访问了,但是有些还是不能。。。

Request URL: http://...
Request Method: POST
Status Code: 403 

查了一些资料。然后发现了一个叫csrf的东西。

http.csrf().disable();

这时候就可以访问了。

Springboot antMatchers:
匹配url遵循如下规则:
? matches one character(匹配一个字符)
* matches zero or more characters(匹配0个或多个字符)
** matches zero or more directories in a path(匹配0个或多个目录)
{spring:[a-z]+}} matches the regexp [a-z]+ as a path variable named "spring",意思是将使用[a-z]+ 正则去匹配spring的变量值

继续加入:

@Bean
@Override
public UserDetailsService userDetailsService() {
	UserDetails user =
		 User.withDefaultPasswordEncoder()
			.username("user")
			.password("password")
			.roles("USER")
			.build();
	return new InMemoryUserDetailsManager(user);
}

这里发现withDefaultPasswordEncoder() 方法被废弃掉了。看了源代码的注释看到它是不安全的。

Using this method is not considered safe for production, but is acceptable for demos and getting started.

Auth:

  1. Authentication:鉴权。-> 是不是?
  2. Authorization:验权。-> 有没有权限?

登陆状态维持

Cookie:
Cookie 是一些数据, 存储于你电脑上的文本文件中。
当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息。
Cookie 的作用就是用于解决 "如何记录客户端的用户信息"

参考文档:JavaScript Cookie | 菜鸟教程

记录一个权威的文档:rfc cookie

SecurityContextHolder.getContext() 
// 把用户信息(Cookie)保存在一个地方

登陆 / 注册

pass

查看约束信息:show create table #{表名};

登出(logout)

参考1: spring-security-logout
参考2: docs.spring.io/spring-security

测试

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.6.0</version>
                <executions>
                    <execution>
                        <id>start-test-database</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <configuration>
                            <longModulepath>false</longModulepath>
                            <executable>docker</executable>
                            <arguments>
                                <argument>run</argument>
                                <argument>--name</argument>
                                <argument>test-mysql</argument>
                                <argument>-e</argument>
                                <argument>MYSQL_ROOT_PASSWORD=123456</argument>
                                <argument>-e</argument>
                                <argument>MYSQL_DATABASE=springboot</argument>
                                <argument>-p</argument>
                                <argument>3307:3306</argument>
                                <argument>-d</argument>
                                <argument>mysql</argument>
                            </arguments>
                        </configuration>
                    </execution>
                    <execution>
                        <id>teardown-test-database</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>exec</goal>
                        </goals>
                        <configuration>
                            <longModulepath>false</longModulepath>
                            <executable>docker</executable>
                            <arguments>
                                <argument>rm</argument>
                                <argument>-f</argument>
                                <argument>test-mysql</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

集成测试 和 销毁测试数据库

运行:>mvn pre-integration-test
销毁:>mvn post-integration-test

Jenkins

docker run -p 8080:8080 -v E:\docker:/var/jenkins_home jenkins

补剩下的笔记。。。

  • Controller 参数验证,清洗
  • Service 处理业务需求
  • Dao 访问数据库

MyBatis参考文档
MyBatis Getting Started

记录问题

遇到前端数据传不过来的问题:

正确返回的response:{"status":"ok","msg":"登陆成功","data":{"id":1,"name":"张三","avatar":"","createdAt":"2020-02-19T05:35:34.331Z","updatedAt":"2020-02-19T05:35:34.331Z"},"login":true}

错误返回的response:{"status":"ok","msg":"登陆成功","login":true}

解决方法:data的getter忘了写。

登陆时返回404

返回的response:{"timestamp":"2020-02-19T05:39:22.740+0000","status":404,"error":"Not Found","message":"No message available","path":"/auth/login"}

解决方法:给方法加上@ResponseBody

使用错误的账号登陆时返回403

返回的response:{"timestamp":"2020-02-19T05:41:18.728+0000","status":403,"error":"Forbidden","message":"Access Denied","path":"/auth/login"}

正确返回的response:{"status":"fail","msg":"用户不存在","data":null,"login":false}

解决方法:UserDetailsService接口抛出UsernameNotFoundException。

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

解决方法:使用 org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
绝对不可以使用明文密码。

    1. 必须加密
    1. 加密是不可逆的
    1. 加密必须是一致的

WARNING:不要自己设计加密算法

created_at和updated_at两个字段不断的刷新,并且和数据库对不上

原因:驼峰形式和下划线形式匹配不上
解决方法:application.properties 加上 mybatis.configuration.mapUnderscoreToCamelCase=true

Bean循环依赖问题

Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
|  webSecurityConfig defined in file [.../WebSecurityConfig.class]
↑     ↓
|  userService defined in file [.../UserService.class]
└─────┘

解决方法:我这里把一个Bean变成字段注入。。。了。。。

避免某些字段序列化到前端(例如:密码)

解决方法:Spring默认的序列化工具是jackson。查了资料:jackson not serelize得知@JsonIgnore注解可以解决

maven-surefire-plugin报告 Tests run:0, Failure:0, Error:0, Skipped:0

相关:Gradle 5 JUnit BOM and Spring Boot Incorrect Versions
解决方式:pom.xml添加

<properties>
    <junit-jupiter.version>5.6.0</junit-jupiter.version>
</properties>

集成测试:A type incompatibility occurred while executing org.codehaus.mojo:exec-maven-plugin:1.6.0:exec: java.lang.String cannot be cast to org.codehaus.mojo.exec.Modulepath

解决方法: 中加入:

<longModulepath>false</longModulepath>

重构

DRY原则:Don’t Repeat Yourself

解决:重构了部分重复代码。。。(写了一个静态工厂方法)

自动化测试

测试驱动开发 TDD:Test-Driven Development

为什么?

  1. 自动
  2. 节省时间
  3. 人会犯错
  4. 测试水平

单元测试:unit test

用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作

  • 黑盒测试

集成测试:intergration test

将部分代码集成一块进行测试

冒烟测试:smoke test

测试软件的基本功能

回归测试:regression test

重复以前的全部或部分的相同测试

posted @ 2020-02-18 19:21  带了1个小才艺  阅读(236)  评论(0编辑  收藏  举报