修改了用户信息, 但是postman获取的仍然是旧的,问题出在repository里面的方法前面加了

@Cacheable(cacheNames = USERS_BY_LOGIN_CACHE)

这个不太好使, 去掉就行了。

最新后台编译命令: ./mvnw package -DskipTests -Pprod verify jib:dockerBuild

Windows下安装首先要下载Yarn,安装之前,还需要安装node.js, 安装完后yarn --version验证成功。接着yarn global add yo 安装Yeoman,这是是产生代码的。

接着yarn global add generator-jhipster安装angular 2版本的jhipster。

此处开始创建应用了:

创建一个目录jhipapp,打开命令行工具,cd jhipapp, 输入jhipster,出现一个界面:

选择应用类型,我选简单的Monolithic,应用的基本名称jhipapp,默认的java包名称com.james.myapp,选择验证类型,我选JWT authentication,数据库选MySql,使用Hibernate 2级缓存,用maven,选Search engine using Elasticsearch和API first development using swagger-codegen,选angular 4,语言选Chinese (Simplified),附加语言是English

最后在powershell中输入./mvnw开始下载,遇到node的错误,以及其他下载错误,估计和没有设置代理有关系

添加阿里云maven仓库镜像到C:\Users\James\.m2\settings.xml如下:

 

<mirror>
    <id>nexus-aliyun</id>
    <mirrorOf>*</mirrorOf>
    <name>Nexus aliyun</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror> 

下载依赖包成功。

 

但是连接数据库有抛了异常如下:

开头是java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: NO), 我之前电脑上装了mysql 5.7,好久没有用了

进入C:\Program Files\MySQL\MySQL Server 5.7\bin, 命令行执行mysqld, 出现

 


MySQL Server 5.7\data\'     (Errcode: 2 - No such file or directory)

错误,上网查,用了一个命令mysql --initialize生成data目录,然后再用mysqld顺利启动。

 

mysql启动之后,再用powershell调用./mvnw,结果还是mysql访问拒绝,查看了一下应用根目录下的pom.xml,有个设置mysql目录的地方,

在org.liquibase这一节下,设置了目录,但是还是报同样的错误,然后用intellij导入现有工程,选择自动导入maven项目(打钩),选择dev profile,按两次shift键查找password,

发现src/main/resources/config/application-dev.yml文件中可以设置密码,果断设上

重新./mvnw,新的错误发现不了数据库,用phpmyadmin创建一个空的数据库,设置排序规则utf8-general-cli,再次./mvnw,还有错误说8080端口已被占用。

Windows下普通命令行输入一下命令:

netstat -aon | find "8080"

再用taskmgr杀掉改pid,再次./mvnw成功!

 

如果需要前后端分离,分两步创建工程:

服务器端:

cd jhipback_end

jhipster --skip-client

cd jhipfront_end

jhipster --skip-server --db mysql --auth jwt

项目分离之后,运行时需要两个web server,前端调用api会映射到另外一套url,这个url前缀需要在

webpack.common.js文件里面修改SERVER_API_URL,比如:

 

SERVER_API_URL: `"http://localhost:8080/"`

 

后端也要设置CORS

前端调试:

如果单独用vscode调试angular4应用,需要安装Debugger for Chrome,安装完成后,如果想调试,先yarn start吧web启动起来,然后把端口改成9000,然后按F5调试,即可。

如果前后端没有分离,想在Intellij上同时调试前后端,请安装下面步骤:

1. 配置前端debug

第一步:在chrome上安装JetBrains IDE Support扩展

第二步:在Intellij里面建立一个新的Javascript Debug configuration

第三步:在第二步的基础上配置Javascript Debug 配置:主要是这是URL,如:http://localhost:9000/,然后再配置一下远程URL(可选步骤,主要找出index.html)

第四步:开始调试(可以同时在Intellij调试前后端)

2. 配置后端debug

就是一般的spring boot的debug,需要配置,网上一搜就是。

添加Entity:

打开https://start.jhipster.tech/jdl-studio

图形化方式,建好entity以及它们之间的关系(支持一对多,多对一,多对多,以及分页)

下载jdl文件到本地,然后输入下列命令:

jhipster import-jdl your-jdl-file.jh

就会在工程里面生成前后端以及entity代码。

如果只生成后端的entity代码:

jhipster import-jdl your-jdl-file.jh --skip-client

只生成前端的entity代码:

jhipster import-jdl your-jdl-file.jh --skip-server

 

默认情况下import-jdl会重新生成那些有改变的entities,如果想要所有的entities都重新生成一下,用到--force选项,要注意的是,这会覆盖所有本地的改动。

下面就一个ManyToOne的关系解释一下jdl语言的含义:
github上blog的例子:https://github.com/mraible/jhipster4-demo#generate-entities

relationship ManyToOne {

  Entry{blog(name)} to Blog

}

花括号里面小写的blog是关系名称,就是生成的@Entity Entry代码里面private Blog blog;是成员变量名,
同时也是前端typescript代码class Entry里面的public成员变量名称。就是说jh文件里面的内容影响前后端

的代码。

圆括号()里面的内容(此处是name)只会影响前端,比如创建一个Entry,代表创建的form里面会让你选择

此Entry属于哪个blog,如果省略圆括号,默认显示blog的id;此处写name,name显示的是blog的名称。

上面是多对一,就是一个blog包含多个entry;如果采用一对多,采用如下方式:

relationship OneToMany {

  Blog to Entry{blog(name) required}

}

或者

relationship OneToMany {

  Blog{entry} to Entry{blog(name) required}

}

上面两种形式生成的代码一样,相对于多对一,Blog类里面多了一个Entry的集合类:

 

@OneToMany(mappedBy = "blog")
@JsonIgnore
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Entry> entries = new HashSet<>();

当添加一个entity是,在server端主要有下面这些更改:

1. 数据库schema的变动,两个xml,一个是create,另一个是加外键

2. Entity类

3. Jpa的repository接口

4. 控制器controller

5. elasticSearch的变化

6. 添加到cache

在前端主要是添加了一个module,i18n的翻译

在修改某个entity的过程中碰到一个错误,原因是我之前曾经直接改过mysql的表,错误如下:

Liquibase Validation Failed:

config/liquibase/changelog/20180124122638_added_entity_Examine.xml::20180124122638-1::jhipster was:xxxxxx

解决方案:到mysql里面执行:

UPDATE DATABASECHANGELOG SET MD5SUM=null WHERE ID='20180124122638-1';

 

更新generate-jhipster:

yarn global upgrade generator-jhipster

从jhipster 5.3.0开始npm为默认的包管理器了,而不是yarn

安装用:

npm install -g generator-hipter

更新应用目录下的angular/cli:

npm install --save-dev @angular/cli@latest

更新应用程序:

jhipster upgrade

据stackoverflow上最新的更新指南:

先更新generator-jhipster:

npm update -g generator-jhipster

然后到项目根目录下运行:

yo jhipster

如果想更新所有的entities:

 


yo jhipster --with-entities

 

我从4.13.1升级到4.14.3应用程序改变不大。

 

生成一个单独的前端应用之后,使用yarn start,运行前端程序,此时会在build/www/目录下生成一堆可运行的文件,把

nginx的root指定到这里,就可以运行了。

如果只想build, 而不想用yarn来启动,输入命令:

yarn run webpack:build

webpack:build是定义在package.json文件中scripts里面的任务,在该文件中还有其他的任务。其中start如下定义:

"start": "yarn run webpack:dev"

其中webpack:dev定义如下:

 

yarn run webpack-dev-server -- --config webpack/webpack.dev.js --progress --inline --hot --profile --port=9060 --watch-content-base

 

 

 

 

在Windows下,进入nginx安装目录,运行

start nginx就可以启动nginx

在powershell下运行./nginx -s quit关闭nginx

==================================================================================================================================

看来google的Angular系列走不长了,Vue是主流了现在,用yo命令更新generator-vuejs,

然后创建一个目录,用jhipster --blueprint vuejs来产生vue前端。

==========================================================================

既然jhipster面向angular2和spring boot, 理解他们的概念是必要的,下面是一些angular 2的一些基础知识:

angular cli是一个命令行工具,用它创建,测试,部署项目,cli由npm安装:

npm install -g @angular/cli 全局安装

装完之后就可以用各种cli的命令了,命令一般以ng开头,比如:

ng new my-app

到这一步,有可能会出现"Installing packages for tooling via npm", 然后一直停在那里似乎没有反应了,解决:

1.首先安装国内taobao的npm镜像:

npm config set registry https://registry.npm.taobao.org

配置后可以通过下面方式来验证是否成功:

npm config get registry

或npm info express

如果还有问题:

可以分两步走:

1. ng new my-app --skip-install

2. npm install

就可以了

cd my-app

ng serve --open // 启动server,监视文件修改,打开浏览器http://localhost:4200/

应用主要放在src目录下,其中两个文件tsconfig.app.json和tsconfig.spec.json使用配置typescript编译器的,用来编译app和单元测试。

src目录之外的文件都是辅助性的,用来支持构建项目的,需要熟悉的有:

node_modules/    由node.js下载的第三方模块放在该目录下,这些第三方模块列举在

package.json文件中。

tsconfig.json  IDE的TypeScript编译器配置, 我们知道TypeScript需要编译成javascript才能使用,TypeScript是面向对象的。

网上有很多吐槽angular2的(主要和react比较),比如需要需额外的语法,额外的语言(TypeScript),不过对于我这样的c++/C#背景的程序员来说,

TypeScript的面向对象特点以及对于Google的信任,其他都不重要了,不需要学习Javacript这个变态的语言了(想象一下this在闭包里面的使用)。

熟悉Angular2几个重要而且容易混淆的感念很重要:

1. imports

在Module的ts文件,你会两次看到imports,一个在文件顶部,一个在@NgModule()的括号内,

顶部的imports是TypeScript的语法,凡是出现在文件下方的标识符都需要imports进来。

@NgModule内的imports是把本Module要用到的其他Modules的输出声明引入进来。

2. service 服务

service一般用来和远程的service打交道,比如和后台web api, 不需要和html关联,但是service一般需要依赖别的库来共同作用,所以metadata的修饰符是

@Injectable。

service不用new创建,而是在私有构造函数里注入,通过provider创建。

服务一般从远程取数据,多用异步操作,一般返回Promise或者Observable, HttpClient的get方法就返回Observable,这个是在rxjs库中定义的

用ng cli生成app范围内的服务:

ng generate service message --module=app

 

3. routing 前端路由

routing的输入就是URL,经过routing之后,能够调出相应的view进行展示。

就是说routing一边解释URL,一边取出相应的component(和某个view关联)进行展示。

比如点击了一个a元素,会导致URL改变,这时routing截取改变之后的URL,进行分析,然后找出相关联的view展示。

routing是一个单例的服务。由forRoot函数配置。forRoot的名字也意味着路由是在应用程序的root级别进行配置的。

配置时,url前面不需要加/,但是在使用routerLink时需要加/.

在配置routing之前,必须把<base href="/">加为index.html <head>的第一个子节点。

在需要routing的地方使用routerLink指令。

routerLink的值可以为单个字符串,也可以是数组(带参数的):

<a routerLink="/hero">AAA</a>

<a [routerLink]=["/hero", hero.id]>BBB</a>

4. 不直观的概念

4.1 OnInit,你以为是函数,却是一个interface。

大坑:用angular-cli打包,之前有个程序用的较老的nodejs生成的angular4工程,package.json里面好多angular组件是4.3.4版本,用

ng build 命令打包失败,失败信息如下:

 

添加bootstrap4到ng cli项目中:

首先用npm下载bootstrap:

npm install jquery --save

npm install popper.js --save

npm insall bootstrap@next --save

然后把必须的脚本文件加到apps[0].scripts中(.angular-cli.json文件中)

 

"scripts": [
  "../node_modules/jquery/dist/jquery.slim.js",
  "../node_modules/popper.js/dist/umd/popper.js",
  "../node_modules/bootstrap/dist/js/bootstrap.js"
],

最后把bootstrap CSS加到apps[0].styles中(.angular-cli.json文件中)

 

 

"styles": [
  "../node_modules/bootstrap/dist/css/bootstrap.css",
  "styles.css"
],

 

Angular4的日期等等默认语言都是美国英语,如果想要支持中文,请用下列命令起server:

 

ng serve --aot --locale zh --open     // 主要是--locale zh

如果不想用aot二用JIT,请在app.module.ts里面import {LOCALE_ID} from '@angular/core';

然后再@NgModule里面的providers数组里面添加:

providers: [{provide: LOCALE_ID, useValue: 'zh'}],

用ng cli直接生成component:

ng generate component hero-detail

 

==========================================================================================================

前后端分离,Centos环境,64位,Centos 7,首先安装wget

yum install wget

安装epel 阿里云源:

将下载的文件存放到指定的文件夹下,同时重命名下载的文件,利用-O:

wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo

更新一下yum缓存

yum clean all

yum makecache

把james用户加到sudoer组里面(wheel组)

root登陆,然后

usermod -aG wheel james

然后安装nginx

sudo yum install nginx 速度飞快啊

systemctl是一个systemd工具,主要负责控制systemd系统和服务管理器

Nginx不会自己启动,用下面命令:

sudo systemctl start nginx

然后查一下centos的ip:

ifconfig -a,提示ifconfig command not found

安装网络工具:

sudo yum install net-tools

再次http://192.168.5.119提示可能防火墙问题,打开防火墙的http:

sudo firewall-cmd --permanent --zone=public --add-service=http

sudo firewall-cmd --reload

再次访问,成功

如果想机器启动时自动启动nginx:

sudo systemctl enable nginx成功创建一个符号链接

Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service

当nginx用sudo启动时,系统起一个master进程,用户是root;一个worker进程,用户是nginx,这个nginx用户在nginx.conf文件里面指定。

nginx需要监听80或者443端口,而只有root进程才能监听小于1024的端口,所以master作为root启动。

为了以后干活容易,(考虑以后部署apache,nginx),需要创建一个group,名字就叫www-data:

sudo groupadd www-data

把nginx用户加到www-data组里面,并设为primary group

usermod -g www-data nginx

删除组:

groupdel www-data

列举所有的组:

cat /etc/group

查看用户组的情况:

groups nginx

循环改变目录的owner和group:

chown -R nginx:www-data /var/www

查看某个路径的权限:

namei -om /var/www

如果取消自动启动nginx:

sodu systemctl disable nginx

查看哪些服务开机自启动:

 

systemctl list-unit-files --type=service

 

停止nginx服务:

sodu systemctl nginx stop

查看nginx安装在哪里了:

find / -name nginx

软件安装在/usr/sbin/nginx

web应用应该放在

/usr/share/nginx下面

日志文件在/var/log/nginx目录下

pid文件在/var/run目录下:nginx.pid

nginx安装程序会创建一个nginx用户,列举系统所有用户指令查看:

cat /etc/passwd

查看运行的服务是哪个用户启动的指令:

ps aux | grep nginx

返回所有运行的进程名字中包含nginx。并搜索nginx进程,第一列就是运行那个进程的用户名。

复制目录内所有文件到另外一个目录下:

cp /home/james/dist/* /var/www/nginx/

目录改名:

mv /var/www/nginx /var/www/nginx_

强制删除目录以及目录里面的文件:

rm -rf /var/www/nginx

Centos默认情况下Selinux是Enforcing的,nginx默认的网站目录是/usr/share/nginx/html, 如果改为其他目录,

除了设定owner和group的权限之外,还要设定该目录的selinux安全性文本(或者改为宽容模式 setenforce Permissive):

chcon -R -u system_u -t httpd_sys_content_t /var/www/nginx

查看selinux的模式:

getenforce

观察nginx的安全性文本数据(主要是 -Z):

ps aux -Z | grep nginx

安装nodejs和npm:

sudo yum install nodejs  

sudo yum remove nodejs  // 卸载

sudo yum update // 更新所有系统中已经安装的包

sudo yum list nodejs  // 列举可用的nodejs

centos设置npm淘宝镜像:

npm configset registry https://registry.npm.taobao.org

=========================================================

安装jre 8u152,先从oracle网站上下载rpm 64位包,通过WinSCP上传到james目录,

sudo chmod u+x jre-8u152-linux-x64.rpm

sudo yum install jre-8u152-linux-x64.rpm

sudo find / -name java

如果查找同时列出文件属性:

find / -name java | xargs ls -l

java -version 查看版本

如果系统中有多个java版本,用

alternatives --config java 来选择一个默认的java

此命令中的+号表示手动选择的,*号表示自动默认的

如果添加一个OpenJDK,用下面命令:

sudo alternatives --install /usr/bin/java java /usr/lib/jvm/jre-1.6.0-openjdk/bin/java 2000

最后面是优先级,数字越大,优先级越高

还有一个有用的选项是--display,显示可用的alternatives

sudo alternatives --display java

设置JAVA_HOME

先用update-alternatives --config java列举一下java都安装在哪里

然后打开

sudo vim /etc/profile在最后一行添加:

export JAVA_HOME="/usr/java/jre1.8.0_152"

保存退出, 注意JAVA_HOME的路径是不带bin的

用下面命令重新加载/etc/profile文件,修改立即生效。

source /etc/profile

用echo $JAVA_HOME查看一下有没有设置成功。

=========================================================

安装mysql community server版本

本来想从mysql网站上直接下载一个64位rpm包到Windows上,然后再上传到CentOs上,但是安装过程中报错,说有什么client的依赖。

所以不能这么安装,可以用yum repository的方法安装:

首先添加MySQL yum repositories:

wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm

文件名mysql57-community-release-el7-11.noarch.rpm可以在https://dev.mysql.com/downloads/repo/yum/网页上看到

下载完成后用md5校验一下,保证下载的包是好的

md5sum mysql57-community-release-el7-11.noarch.rpm

然后比较生成的md5字符串是否和网页上面的一样

运行:

sudo rpm -ivh mysql57-community-release-el7-11.noarch.rpm

添加yum仓库

这时,可以正式安装mysql了:

sudo yum install mysql-server

出现提示直接按y确认

mysql -V

启动msyqld守护进程:

sudo systemctl start mysqld

查看mysqld状态:

sudo systemctl status mysqld

在安装过程中,root用户会有一个临时密码再/var/log/mysqld.log里面,这个密码需要记住:

sudo grep 'temporary password' /var/log/mysqld.log

下面为初次使用mysql前的配置,包括修改密码,删除临时数据库,禁止远程root登录等

执行安全脚本:

sudo mysql_secure_installation

输入新的密码,输入之后,立即有个反馈信息,然后立即又会让你再次修改,这次选No

然后一直按Y就可以结束整个安装。

安装完成后,测试一下

mysqladmin -u root -p version

列举已经安装的数据库:

show databases;

列举表:

use first_spring;

show tables;

删除数据库,需要在bash提示符下:

mysqladmin -u root -p drop first_spring;

或者mysql -u root -p登录后

drop database first_spring;

列举所有mysql用户:

select user, host from mysql.user;

创建用户,不限localhost

create user james identified by 'xxx';

在spring boot项目中添加mysql支持:

如果是用gradle,添加

 

compile 'mysql:mysql-connector-java'

如果是maven,添加

 

 

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

然后在application.properties文件中添加下面几行:

 

 

spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://localhost:3306/db_example
spring.datasource.username=james
spring.datasource.password=password

ddl-auto有好几个选项:none,update,create,create-drop,对于mysql来说默认是none,在产品环境下也请选择none

 

选择create就是由Entity来创建数据库schema。

=========================================================

安装mongodb,数据分析时候用,

mongodb的包mongodb-org包含4个包:

mongodb-org-server

mongodb-org-mongos 包含mongos deamon

mongodb-org-shell 包含mongo shell

mongodb-org-tools 包含一些工具:mongoimport, bsondump, mongodump, mongoexport, mongofiles, mongoperf, mongorestore, mongostat, mongotop

安装之前,先建立一个文件/etc/yum.repos.d/mongodb-org-3.6.repo, 输入以下内容:

 

[mongodb-org-3.6]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.6/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc


保存退出,输入

 

sudo yum install -y mongodb-org

安装完成之后,如果在Centos系统上,需要处理Selinux,开放tcp端口27017,这个端口是mongodb用的:

sudo semanage port -a -t mongod_port_t -p tcp 27017

如果找不到semanage命令,按以下步骤安装:

1. yum provides /usr/sbin/semanage  看看那个包提供了文件/usr/sbin/semanage

2. yum -y install policycoreutils-python

安装完mongodb后,启动mongodb:

sudo service mongod start

设置开机启动:

sudo chkconfig mongod on

停止mongodb:

sudo service mongod stop

 

Windows 10下输入一下命令:

mongod.exe --dbpath d:\mongodb\data

创建来用户名和密码的数据库:

1. 不带访问控制启动mongodb

mongod --port 27017 --dbpath /data/db

2. 连接到实例

mongo --port 27017

3. 创建用户管理员(在admin数据库中)

use admin

db.createUser(
  {
    user: "myUserAdmin",
    pwd: "abc123",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
)

4. 带访问控制重启mongodb

mongod --auth --port 27017 --dbpath /data/db

5. 作为用户管理员连接到admin

mongo --port 27017 -u "myUserAdmin" -p "abc123" --authenticationDatabase "admin"

6. 为产品创建用户(在test数据库中)

use test

db.createUser(
  {
    user: "myTester",
    pwd: "xyz123",
    roles: [ { role: "readWrite", db: "test" },
             { role: "read", db: "reporting" } ]
  }
)

7. 用myTester连接到test数据库

mongo --port 27017 -u "myTester" -p "xyz123" --authenticationDatabase "test"

=========================================================

再来看看spring boot, 用Idea创建一个spring boot程序,maven构建,在application.properties文件中,更改端口

server.port = 8080

 

然后在包含main函数的那个文件右键选择run。。。

spring security的验证功能:

用户登录时发个post请求上来,在请求的body里面带上来用户名和密码,服务器端用jackson的ObjectMapper类的

readValue(stream, User.class)由json对象创建一个User对象,然后把这个User对象传给

AuthenticationManager的authenticate函数进行验证,该函数返回一个Authentication对象

这个对象是一个经过完全验证的对象,该对象包含凭据(credentials)

以上过程主要是在

UsernamePasswordAuthenticationFilter的attemptAuthentication函数中进行的

验证成功之后,下一步服务器就要生成一个jwt给浏览器了,过程如下
上一步验证成功之后,调用successfulAuthentication函数产生jwt,具体使用Jwts类设置Subject,
设置过期时间(比如10天),在用签名算法(比如HS12,HMAC using SHA-512)进行签名得到一个JWS,
最后调用一个compact函数实际构建JWT字符串,这个字符串是URL安全的,就是能作为URL的一部分传来传去的。
注意HMAC和电脑的MAC地址没有关系,全称是HASH-based Message Authentication Code
然后把产生的jwt加上前缀Bearer 作为头Authorization的值传给浏览器。

以上过程是在

UsernamePasswordAuthenticationFilter的successfulAuthentication函数中进行的

经过上面二个过程,客户通过验证了,服务器也下发了jwt了。后续的来自浏览器的请求需要带上这个jwt到服务器,

 

服务器需要验证这个jwt是不是有效的token,这个过程叫做授权Authorization:

通过派生一个BasicAuthenticationFilter类实现我们的授权过程,为什么要派生自BasicAuthenticationFilter呢?

因为派生的话,Spring就会知道这个授权过程在filter链条中处于什么位置,并把我们的派生filter替换掉原来的filter。

授权过程先要解析jwt,主要由helper类Jwts来完成,解析完成后得到一个用户名称(username),然后由这个username

构造一个Authentication的实例,这个实例的类型是UsernamePasswordAuthenticationToken类,这个过程叫做对jwt进行有效性验证:

validation,如果所有的东西都各就各位了,我们就把jwt抽取出来的用户置于spring的安全上下文中,意味着

用户的请求可以向前移动了,那就是真正的业务处理了,包括增删改查等等。

 

上面重载的两个类还不够,spring不会自动加载我们重载的类,需要我们告诉spring加载并替换原来的filter,

这个需要我们从WebSecurityConfigurerAdapter类派生一个类:例如叫WebSecurity,并且需要加上@EnableWebSecurity,

这样就能利用spring security提供的web安全配置相关的功能了。

在这个类中主要重载了两个函数:

configure(HttpSecurity http)

configure(AuthenticationManagerBuilder auth)

在第一个函数中配置哪些资源是公开的,哪些是需要保护的(就是确保是授权用户,输入了正确的用户名和密码)。添加上面重载的两个

Filter;

是否需要支持跨域资源共享(CORS, Cross-Origin Resource Sharing),这是通过HttpSecurity.cors()函数来得到:

cors函数用于添加CorsFilter,如果提供了一个名称为corsFilters的Bean,则使用这个Bean;如果没有,再看看

有没有定义corsConfigurationSource的Bean,如果有则使用。否则如果使用了Spring MVC,使用HandlerMappingIntrospector类实例来获取

请求中的CORS 配置。

第二个函数中。基于我们定义的一个UserDetailsService添加Authentication。这个UserDetailsService是用spring安全框架使用来加载

和用户相关的数据,一般是从数据库中获取。比如,数据库中保存的经过加密的密码(这个需要一个加密方法以便对上传的密码加密之后

再和数据库中保存的密码进行比对),所以我们

还需要提供一个加密的Bean,这个一般是BCryptPasswordEncoder.

在WebSecurity类中还需要定义一个corsConfigurationSource的Bean,如前所述,用来配置cors的,可以配置成允许任何来源的请求

(/**)

接着来看下UserDetailsService接口的实现:

该类主要有个重载函数:

loadUserByUsername,该函数返回一个UserDetails类,该类是spring security框架中的User类的接口

该接口定义了一些方法:

1. 获取授权列表

2. 获取密码

3. 获取用户名

4. 账号是否过期

5. 账号是否锁定

6. 凭据是否过期

7. 用户是否enable

这个函数调用一个比较有趣的函数,这个函数没有写代码(是一个接口函数),叫做findByUsername,为什么这个接口函数没有实现

还能调用呢,这就涉及到JpaRepository的细节了,因为接口是从JpaRepository派生的,JpaRepository支持接口规范方法名查询,即,如果

在接口中定义的方法名称符合命名规范,就可以不写实现,下面列举两个例子:

 

KeywordSampleJPQL snippet
IsNotNullfindByAgeNotNull...  where x.age not null
LikefindByNameLike...  where x.name like ?1

 

findByUsername会先去掉前缀findBy,剩下Username,如果Username是Entity的一个属性,就按照Username进行查询。

 

感觉Spring有些过了,规则太多,不太直观,造成学习困难,因为要记的东西太多。

=========================================================

有时候碰到什么概念不理解,需要建一个简单的web应用实践一下,但是以前如果想建一个这样的工程是相当麻烦的,这一点

要给Visual Studio一万个赞。一个web应用需要具备一下几个功能:

1. 浏览器有页面显示

2. 有restful

3. 支持一种模板语言(freemarker)

4. 后端java,要有mvc,

5. 能响应rest以及正常的request请求

6. 支持javascript和jquery

7. 需要servlet container,比如apache tomcat

下面介绍一个最简单快捷的方法:

用Intellij创建一个spring boot initializer应用,选择Web和Freemarker, maven

在生成的框架代码里面,template下面添加一个hello.html, 在static目录下添加一个hello.js

打开pom.xml文件添加webjars依赖,这样不需要下载jquery放进代码目录里面

把jquery和hello.js的引用添加到html的body下部:

 

<script type="text/javascript" src="webjars/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="js/hello.js"></script>

 

注意script这个tag千万不要写成<script xxxx/>, 而要写成<script xxxx></script>

血的教训,浪费好几个小时

body里面添加一个button和一个div, id为response-panel

然后在hello.js里面发起一个ajax的get请求:

$.ajax({type: 'GET', url: 'list', async: 'true', data: dataSet, processData: 'true', contentType: 'application/json', 

success: function(data, status, xhr) {

var auth = xhr.getRespnoseHeader('Authorization');

document.cookie = "name-" + auth + ";expires=30";

_response.html(JSON.stringify(data, true, 2));

}

然后在后端HelloCotroller.java里面定义controller

两个函数:一个hello,一个list, hello返回主页面,list是restful请求

 

    @RequestMapping("/hello")
    public String hello(HttpServletResponse servletResponse, Model model, @RequestParam(name="name", value = "", defaultValue = "Welcome") String name) {

        model.addAttribute("name", name);
        servletResponse.addCookie((new Cookie("foo", "bar")));
        return "hello";
    }

    @ResponseBody
    @RequestMapping(value="/list", method= RequestMethod.GET, consumes = MediaType.APPLICATION_JSON_VALUE)
    public List<String> list(HttpServletResponse servletResponse, @ModelAttribute("username") String username, @RequestParam("password") String password) {
        servletResponse.addHeader("Authorization", "jamessecurity");
        java.util.List<String> response = new ArrayList<String>();
        response.add(username);
        response.add(password);
        return response;
    }


然后再把hello.html改名为hello.ftl文件,编译,运行。

 

对于maven项目,如果要部署,先打包成jar文件:

 

mvn package

然后运行:
java -jar target/xxx.jar

如果用gradle,先打包:

./gradlew build

然后运行:

java -jar build/libs/xxx.jar

 

在Centos 7运行spring boot的web应用程序:

现在Windows上用Maven打好包,然后通过WinSCP上传到james用户的家目录,然后

chmod 755 xxx.jar

java -jar xxx.jar

看到程序运行,然后在Windows上打开浏览器,输入192.168.1.87:8086没反应,提示可能是防火墙问题

用putty, root用户登录,发出下面指令打开端口8086:

firewall-cmd --permanent --add-port=8086/tcp

firewall-cmd --reload

打开端口成功,然后在浏览器输入:

http://192.168.1.87:8086/greeting看到restfull响应,成功。

作为服务来运行spring boot 完全自执行包(所有依赖都在包内部):

首先在pom.xml的spring-boot-maven-plugin下面加上:

 

<configuration>
   <executable>true</executable>
</configuration>

修改项目的<version>为1.0.0,然后mvn package打包到target子目录中

 

WinSCP上传到james家目录下面james-web-1.0.0.jar并且chmod 755 james-web-1.0.0.jar

假定这个jar包放到/var/jamesweb目录下(安装), 在/etc/systemd/system目录下创建一个文件jamesweb.service(用vim编辑):

 

[Unit]
Description=james-web-1.0.0.jar
After=syslog.target

[Service]
User=myapp
ExecStart=/var/jamesweb/james-web-1.0.0.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

然后sudo cp james-web-1.0.0.jar /var/jamesweb/james-web-1.0.0.jar把jar文件复制到/var/jamesweb目录下

 

启动服务

sudo systemctl start jamesweb.service

设定开机自启动

sudo systemctl enable jamesweb.service

超级简单

 

=========================================================

vim常用指令:

显示行号: :set nu

删除光标处一行 dd

撤销 u

重做 Ctrl + r

移动到文件第一行 gg

移动到最后一行 G

移动到第几行 nG, n是数字

将第3行至第4行的数据,复制到第8行后面 :3,4 co 8

将第3行至第4行的数据,移动到第8行后面 :3,4 m 8

多行删除,在命令模式, 按大写的V进行视觉模式,然后上下移动光标到多行,然后按x或者d删除

移动到下一个单词的结尾 e,下一个单词的开始 w, 前一个单词的开始 b

删除光标开始处的5个单词 5dw

删除光标处到行尾:d$

打开多个文件: 用:tabe <filepath>

切换到下一个tab: :tabp

切换到前一个tab: :tabn

映射F7键到tabp: :nmap <F7> :tabp <CR>

映射F8键到tabn: :nmap <F8> :tabn <CR>

复制3行到另外一个文件:

3yy,切换到另一个文件,p

往下翻页:Ctrl + f

往前翻页:Ctrl + b

复制文件到另一个文件:cp temp.txt foo/temp2.txt

复制文件到另一个目录:cp temp.txt foo

查看一个文件内容:cat more less

 

 

linux开启8080端口:

首先查询哪些程序开启了哪些端口:

netstat -tulnp

t:tcp, u:udp, l:listening port, n:numberic address, p:监听的程序

 

===============================================================

html5相关:

引用块级文本:blockquote

引用行内文本:q

===============================================================

javascript相关:

5种基本类型值:Undefined, null, boolean, number, string

===============================================================

intellij常用命令:

按住Ctrl键再把鼠标放到一个函数或者类名上,会显示简单信息

Ctrl+E 显示近期打开的一些文档

================================================================

前端的各种路径:

html的路径

info/index.html

表示在当前文件所在目录中有个文件夹叫info,里面的index.html文件

如果在网站的根文件夹目录下有个img目录(里面有个文件index.html),但是根文件夹是目前所在目录往上二级父目录../../

../../img/index.html这样不太好,可以在最开始使用一个斜杠表示根目录,这样/img/index.html

当URL以一个目录结尾(可以包含一个结尾的斜杠,也可以不包含),指的是路径中最后一个目录中的默认文件,通常为index.html

锚的路径

如果锚位于另一个文档,就使用<a href ="page.html#anchor-name"> 引用该区域。( 在URL 和# 之间没有空格。) 如
果锚位于另一台服务器上的页面,则需输入<a href="http://www.site.com/directory/page.html#anchor-name">

================================================================

一些开发技巧:

开发过程中disable chrome cache, F12打开开发工具,点击Network,勾选就行,需要注意,禁掉cache只在开发工具打开的时候

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐