jhipster
修改了用户信息, 但是postman获取的仍然是旧的,问题出在repository里面的方法前面加了@Cacheable(cacheNames = USERS_BY_LOGIN_CACHE)这个不太好使, 去掉就行了。最新后台编译命令:./mvnw package -DskipTests -Pprod verify jib:dockerBuildWindows下安装首先要下载Y...
修改了用户信息, 但是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支持接口规范方法名查询,即,如果
在接口中定义的方法名称符合命名规范,就可以不写实现,下面列举两个例子:
Keyword | Sample | JPQL snippet |
IsNotNull | findByAgeNotNull | ... where x.age not null |
Like | findByNameLike | ... 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只在开发工具打开的时候
更多推荐
所有评论(0)