Nginx反向代理与Tomcat实现ssm项目前后端分离部署

Nginx

nginxLOGO

nginx是一款http和支持反向代理web服务器,以其优越的性能被广泛使用。以下是百度百科的介绍。

Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。

其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

Nginx配置文件

下载解压之后大概的文件结构大概是这样的,image-20211014222606281

打开conf文件夹并找到名为nginx.conf的文件并打开它。

image-20211014222812590

nginx.conf就是Nginx一个很重要的配置文件。所以了解以下它的结构相关的基本配置是很重要的。

配置文件详解:

######Nginx配置文件nginx.conf中文详解#####

#定义Nginx运行的用户和用户组
user www www;

#nginx进程数,建议设置为等于CPU总核心数。
worker_processes 8;
 
#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
error_log /usr/local/nginx/logs/error.log info;

#进程pid文件
pid /usr/local/nginx/logs/nginx.pid;

#指定进程可以打开的最大描述符:数目
#工作模式与连接数上限
#这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。
#现在在linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。
#这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。
worker_rlimit_nofile 65535;


events
{
    #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型
    #是Linux 2.6以上版本内核中的高性能网络I/O模型,linux建议epoll,如果跑在FreeBSD上面,就用kqueue模型。
    #补充说明:
    #与apache相类,nginx针对不同的操作系统,有不同的事件模型
    #A)标准事件模型
    #Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择select或poll
    #B)高效事件模型
    #Kqueue:使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。
    #Epoll:使用于Linux内核2.6版本及以后的系统。
    #/dev/poll:使用于Solaris 7 11/99+,HP/UX 11.22+ (eventport),IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
    #Eventport:使用于Solaris 10。 为了防止出现内核崩溃的问题, 有必要安装安全补丁。
    use epoll;

    #单个进程最大连接数(最大连接数=连接数*进程数)
    #根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。每个进程允许的最多连接数,理论上每台nginx服务器的最大连接数为。
    worker_connections 65535;

    #keepalive超时时间。
    keepalive_timeout 60;

    #客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
    #分页大小可以用命令getconf PAGESIZE 取得。
    #[root@web001 ~]# getconf PAGESIZE
    #4096
    #但也有client_header_buffer_size超过4k的情况,但是client_header_buffer_size该值必须设置为“系统分页大小”的整倍数。
    client_header_buffer_size 4k;

    #这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
    open_file_cache max=65535 inactive=60s;

    #这个是指多长时间检查一次缓存的有效信息。
    #语法:open_file_cache_valid time 默认值:open_file_cache_valid 60 使用字段:http, server, location 这个指令指定了何时需要检查open_file_cache中缓存项目的有效信息.
    open_file_cache_valid 80s;

    #open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive时间内一次没被使用,它将被移除。
    #语法:open_file_cache_min_uses number 默认值:open_file_cache_min_uses 1 使用字段:http, server, location  这个指令指定了在open_file_cache指令无效的参数中一定的时间范围内可以使用的最小文件数,如果使用更大的值,文件描述符在cache中总是打开状态.
    open_file_cache_min_uses 1;
    
    #语法:open_file_cache_errors on | off 默认值:open_file_cache_errors off 使用字段:http, server, location 这个指令指定是否在搜索一个文件是记录cache错误.
    open_file_cache_errors on;
}
 
 
 
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http
{
    #文件扩展名与文件类型映射表
    include mime.types;

    #默认文件类型
    default_type application/octet-stream;

    #默认编码
    #charset utf-8;

    #服务器名字的hash表大小
    #保存服务器名字的hash表是由指令server_names_hash_max_size 和server_names_hash_bucket_size所控制的。参数hash bucket size总是等于hash表的大小,并且是一路处理器缓存大小的倍数。在减少了在内存中的存取次数后,使在处理器中加速查找hash表键值成为可能。如果hash bucket size等于一路处理器缓存的大小,那么在查找键的时候,最坏的情况下在内存中查找的次数为2。第一次是确定存储单元的地址,第二次是在存储单元中查找键 值。因此,如果Nginx给出需要增大hash max size 或 hash bucket size的提示,那么首要的是增大前一个参数的大小.
    server_names_hash_bucket_size 128;

    #客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
    client_header_buffer_size 32k;

    #客户请求头缓冲大小。nginx默认会用client_header_buffer_size这个buffer来读取header值,如果header过大,它会使用large_client_header_buffers来读取。
    large_client_header_buffers 4 64k;

    #设定通过nginx上传文件的大小
    client_max_body_size 8m;

    #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
    #sendfile指令指定 nginx 是否调用sendfile 函数(zero copy 方式)来输出文件,对于普通应用,必须设为on。如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络IO处理速度,降低系统uptime。
    sendfile on;

    #开启目录列表访问,合适下载服务器,默认关闭。
    autoindex on;

    #此选项允许或禁止使用socke的TCP_CORK的选项,此选项仅在使用sendfile的时候使用
    tcp_nopush on;
     
    tcp_nodelay on;

    #长连接超时时间,单位是秒
    keepalive_timeout 120;

    #FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 128k;

    #gzip模块设置
    gzip on; #开启gzip压缩输出
    gzip_min_length 1k;    #最小压缩文件大小
    gzip_buffers 4 16k;    #压缩缓冲区
    gzip_http_version 1.0;    #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
    gzip_comp_level 2;    #压缩等级
    gzip_types text/plain application/x-javascript text/css application/xml;    #压缩类型,默认就已经包含textml,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
    gzip_vary on;

    #开启限制IP连接数的时候需要使用
    #limit_zone crawler $binary_remote_addr 10m;



    #负载均衡配置
    upstream piao.jd.com {
     
        #upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
        server 192.168.80.121:80 weight=3;
        server 192.168.80.122:80 weight=2;
        server 192.168.80.123:80 weight=3;

        #nginx的upstream目前支持4种方式的分配
        #1、轮询(默认)
        #每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
        #2、weight
        #指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
        #例如:
        #upstream bakend {
        #    server 192.168.0.14 weight=10;
        #    server 192.168.0.15 weight=10;
        #}
        #2、ip_hash
        #每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
        #例如:
        #upstream bakend {
        #    ip_hash;
        #    server 192.168.0.14:88;
        #    server 192.168.0.15:80;
        #}
        #3、fair(第三方)
        #按后端服务器的响应时间来分配请求,响应时间短的优先分配。
        #upstream backend {
        #    server server1;
        #    server server2;
        #    fair;
        #}
        #4、url_hash(第三方)
        #按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
        #例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
        #upstream backend {
        #    server squid1:3128;
        #    server squid2:3128;
        #    hash $request_uri;
        #    hash_method crc32;
        #}

        #tips:
        #upstream bakend{#定义负载均衡设备的Ip及设备状态}{
        #    ip_hash;
        #    server 127.0.0.1:9090 down;
        #    server 127.0.0.1:8080 weight=2;
        #    server 127.0.0.1:6060;
        #    server 127.0.0.1:7070 backup;
        #}
        #在需要使用负载均衡的server中增加 proxy_pass http://bakend/;

        #每个设备的状态设置为:
        #1.down表示单前的server暂时不参与负载
        #2.weight为weight越大,负载的权重就越大。
        #3.max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误
        #4.fail_timeout:max_fails次失败后,暂停的时间。
        #5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

        #nginx支持同时设置多组的负载均衡,用来给不用的server来使用。
        #client_body_in_file_only设置为On 可以讲client post过来的数据记录到文件中用来做debug
        #client_body_temp_path设置记录文件的目录 可以设置最多3层目录
        #location对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡
    }
     
     
     
    #虚拟主机的配置
    server
    {
        #监听端口
        listen 80;

        #域名可以有多个,用空格隔开
        server_name www.jd.com jd.com;
        index index.html index.htm index.php;
        root /data/www/jd;

        #对******进行负载均衡
        location ~ .*.(php|php5)?$
        {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi.conf;
        }
         
        #图片缓存时间设置
        location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires 10d;
        }
         
        #JS和CSS缓存时间设置
        location ~ .*.(js|css)?$
        {
            expires 1h;
        }
         
        #日志格式设定
        #$remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
        #$remote_user:用来记录客户端用户名称;
        #$time_local: 用来记录访问时间与时区;
        #$request: 用来记录请求的url与http协议;
        #$status: 用来记录请求状态;成功是200,
        #$body_bytes_sent :记录发送给客户端文件主体内容大小;
        #$http_referer:用来记录从那个页面链接访问过来的;
        #$http_user_agent:记录客户浏览器的相关信息;
        #通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。
        log_format access '$remote_addr - $remote_user [$time_local] "$request" '
        '$status $body_bytes_sent "$http_referer" '
        '"$http_user_agent" $http_x_forwarded_for';
         
        #定义本虚拟主机的访问日志
        access_log  /usr/local/nginx/logs/host.access.log  main;
        access_log  /usr/local/nginx/logs/host.access.404.log  log404;
         
        #对 "/" 启用反向代理
        location / {
            proxy_pass http://127.0.0.1:88;
            proxy_redirect off;
            proxy_set_header X-Real-IP $remote_addr;
             
            #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             
            #以下是一些反向代理的配置,可选。
            proxy_set_header Host $host;

            #允许客户端请求的最大单文件字节数
            client_max_body_size 10m;

            #缓冲区代理缓冲用户端请求的最大字节数,
            #如果把它设置为比较大的数值,例如256k,那么,无论使用firefox还是IE浏览器,来提交任意小于256k的图片,都很正常。如果注释该指令,使用默认的client_body_buffer_size设置,也就是操作系统页面大小的两倍,8k或者16k,问题就出现了。
            #无论使用firefox4.0还是IE8.0,提交一个比较大,200k左右的图片,都返回500 Internal Server Error错误
            client_body_buffer_size 128k;

            #表示使nginx阻止HTTP应答代码为400或者更高的应答。
            proxy_intercept_errors on;

            #后端服务器连接的超时时间_发起握手等候响应超时时间
            #nginx跟后端服务器连接超时时间(代理连接超时)
            proxy_connect_timeout 90;

            #后端服务器数据回传时间(代理发送超时)
            #后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据
            proxy_send_timeout 90;

            #连接成功后,后端服务器响应时间(代理接收超时)
            #连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)
            proxy_read_timeout 90;

            #设置代理服务器(nginx)保存用户头信息的缓冲区大小
            #设置从被代理服务器读取的第一部分应答的缓冲区大小,通常情况下这部分应答中包含一个小的应答头,默认情况下这个值的大小为指令proxy_buffers中指定的一个缓冲区的大小,不过可以将其设置为更小
            proxy_buffer_size 4k;

            #proxy_buffers缓冲区,网页平均在32k以下的设置
            #设置用于读取应答(来自被代理服务器)的缓冲区数目和大小,默认情况也为分页大小,根据操作系统的不同可能是4k或者8k
            proxy_buffers 4 32k;

            #高负荷下缓冲大小(proxy_buffers*2)
            proxy_busy_buffers_size 64k;

            #设置在写入proxy_temp_path时数据的大小,预防一个工作进程在传递文件时阻塞太长
            #设定缓存文件夹大小,大于这个值,将从upstream服务器传
            proxy_temp_file_write_size 64k;
        }
         
         
        #设定查看Nginx状态的地址
        location /NginxStatus {
            stub_status on;
            access_log on;
            auth_basic "NginxStatus";
            auth_basic_user_file confpasswd;
            #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
        }
         
        #本地动静分离反向代理配置
        #所有jsp的页面均交由tomcat或resin处理
        location ~ .(jsp|jspx|do)?$ {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:8080;
        }
         
        #所有静态文件由nginx直接读取不经过tomcat或resin
        location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|
        pdf|xls|mp3|wma)$
        {
            expires 15d; 
        }
         
        location ~ .*.(js|css)?$
        {
            expires 1h;
        }
    }
}
######Nginx配置文件nginx.conf中文详解#####

nginx的常用功能有很多,比如

  • HTTP代理(正向代理/反向代理)
  • 负载均衡
  • IP哈希算法
  • web缓存
  • 等等

本文中ssm项目部署就用到了它的的反向代理功能。

代理与反向代理

注意:千万不要盯着这个一直看哈,不然你可能会不认识这个字,直接影响了后面的阅读(手动狗头.jpg)

代理(正向代理)

一个位于客户端原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。

在正向代理过程中,代理服务器相当于一个中间人的角色,它代理客户端向目标服务器发起访问,携带结果缓存到代理服务器中,再将缓存的页面数据返回给客户端。

既是代理服务器代理客户端访问目标服务器进行交互

所以,目标服务器是可能不知道真正的客户端是谁的,甚至可能不知道访问自己的原来是个中间商代理服务器。因此客户端或代理服务器对目标服务器来所是隐藏的。

反向代理

是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器

既是代理服务器代理了目标服务器和客户端进行交互

代理服务器来接受客户端的网络访问连接请求,然后服务器将请求有策略的转发给网络中实际工作的业务服务器,并将从业务服务器处理的结果,返回给网络上发起连接请求的客户端。

即当一个代理服务器能够代理外部网络上的主机,访问内部网络时,这种代理服务的方式称为反向代理服务。此时代理服务器对外就表现为一个Web服务器,

项目结构介绍

本次的部署项目是基于ssm框架实现的校园即时通系统。

前端页面展示使用bootstrap搭建的JSP页面,后端使用了Spring+SpringMVC+Mybatis+JWT,通过Ajax进行数据之间的请求与交互。

所谓前后端分离部署,即将所有静态页面(包括涉及到的静态文件)和后端业务代码(包括和数据库的交互)分离开来

那么问题来了,这样做会引起跨域问题

何为跨域?

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域

  • 域名跨域

    • 主域名不同
    • 子域名不同
    • 域名和IP冲突
  • 端口跨域

    这个比较好理解,比如访问8080端口和访问8081端口就已经跨域了

  • 协议跨域

    • http协议
    • https协议

注意:localhost和127.0.1虽然都是指向的本机,但也属于跨域范畴。

跨域问题带来的限制
  1. 非同源网页的Cookie,LocalStorage,IndexDB读取受限
  2. 非同源DOM受限制
  3. AJAX请求处理受限制(可以发送但浏览器会拒绝处理响应)
跨域问题的解决方案

关于跨域问题的解决,行业前辈们已经总结并搞出了一些列切实可用的方案,我们只需要理解并学会运用就好。向前辈致敬!!!

  • JSONP

    • 只支持 GET 请求
    • 只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题
    • 调用失败的时候不会返回各种 HTTP 状态码。
    • 安全性,万一假如提供 JSONP 的服务存在页面注入漏洞,即它返回的 javascript 的内容被人控制的。

将ajax请求中的json替换为jsonp的一种方式

  $.ajax({
            url: "/cims/user/login",
            data: $("form").serialize(),
            type: "post",
      		//使用jsonp代替json
      		dataType:"jsonp"
         success:function:{},
		 error:function:{}
  • CORS(跨域资源共享)

跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源。

浏览器将 CORS 请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request。

因为本项目用到的是非简单请求(包含DELETE,PUT,GET,POST),所以重点记录非简单请求的使用。

非简单请求(复杂请求)

进行真正的请求之前,浏览器会先使用 OPTIONS 方法发送一个预检请求 (preflight request),OPTIONS 是 HTTP/1.1 协议中定义的方法,用以从服务器获取更多信息。

在预检请求中会携带以下字段:

  • Access-Control-Request-Method: 这个字段表明了请求的方法;
  • Access-Control-Request-Headers: 这个字段表明了这个请求的 Headers;
  • Origin: 这个字段表明了请求发出的域。

服务端收到请求后,会以 Access-Control-* response headers 的形式对客户端进行回复:

  • Access-Control-Allow-Origin: 能够被允许发出这个请求的域名,也可以使用*来表明允许所有域名;
  • Access-Control-Allow-Methods: 用逗号分隔的被允许的请求方法的列表;
  • Access-Control-Allow-Headers: 用逗号分隔的被允许的请求头部字段的列表;
  • Access-Control-Max-Age: 这个预检请求能被缓存的最长时间,在缓存时间内,同一个请求不会再次发出预检请求。

特别的Access-Control-Allow-Credentials这个字段是一个布尔值,表示是否允许发送 Cookie,对于跨域请求,浏览器对这个字段默认值设为 false,而如果需要拿到浏览器的 Cookie,需要添加这个响应头并设为 true, 并且在前端也需要设置withCredentials属性.

具体的,在请求体中添加如下字段:

xhrFields:{
          withCredentials:true
          },
部署流程大致步骤
  • 改造前端页面以及Ajax请求体。
  • 后端controller修改
  • 前端文件移到Nginx服务器的html文件夹下
  • 后端项目打war包并放到Tomcatwebapps文件夹下
  • 配置nginx.conf文件
  • 启动Tomcat,启动Nginx
  • 输入项目地址并运行测试,完成前后端分离部署

其中,在前端改造阶段,自己遇到了不少的坑,要特别注意一下

第一步改造前端页面以及Ajax请求

在正式进入部署流程之前,大致了解一下整个项目目录结构。

分离前:项目目录结构中存在JSP以及相关的静态文件

image-20211016183758279

分离后:不存在相关JSP以及静态文件,注意WEB-INF文件夹需要保留。

image-20211016183953278

了解完基本机构之后就可以开始改造了。

  1. webapp中所有.jsp页面中的JSP标识代码去掉,方法方式很多,我是先在idea中利用全局替换功能一键去除的。【具体方法细节备注在文末,需要自取】

  2. 把所有静态文件包括前面去掉标识的.jsp页面剪切到其他编译工具中,我用的是webStorm,用什么工具无所谓,个人习惯!

  3. 将所有.jsp文件后缀改为.html,完成后是这样的。

    image-20211016185201566

4.修改所有涉及到的跳转路径连接(a标签),改为xxxx.html即可。

image-20211016185400556

修改之前可能是这样的:

image-20211016185612287

关于html中涉及到的其他CSS或者JS文件链接路径,保持之前在JSP页面阶段的相对路径即可,但不能出现${App_path}这玩意儿。

image-20211016185914354

image-20211016185918828

  1. 修改Ajax请求,具体如下
  • 在请求体中新增

    xhrFields:{
        withCredentials:true
    },
    
  • 修改所有方法请求的路径:基于/cims/根目录

比如login方法中

image-20211016190329806

修改之前可能是这样的:

image-20211016190415696

比如userManger中请求units方法

image-20211016190803497

修改之前可能是这样的:

image-20211016190617907

如果説,注銷功能是通過a标签链接的话,也要改为/cims/xxx/xxx

image-20211016191213999

到这里,前端改造步骤差不多就结束了。

第二步:后端Controller修改

将所有Controller中的方法加上@CrossOrigin注解

image-20211016191504865

第三步:前端文件移到Nginx服务器的html文件夹下

结构如下

image-20211016191657080

第四步:后端项目打war包并放到Tomcatwebapps文件夹下

结构如下

image-20211016191836616

注意:图中蓝色区域的cims_war文件夹是运行后自动编译生成的,无需自己创建。只需要关注这个war文件.

第五步:配置nginx.conf文件

打开nginx.conf配置文件,关注以下配置

   location / {
            root   html;
            index  login.html;
        }

        location /cims/ {
            add_header 'Access-Control-Allow-Origin' $http_origin;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' '*';
            add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
            add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain; charset=utf-8';
                add_header 'Content-Length' 0;
                return 204;
            }
            proxy_pass http://localhost:8080/cims_war/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Cookie $http_cookie;
        }

image-20211016192407185

现在知道为什么上面的请求路径需要修改为/cims/xxx形式了吧!

图中蓝色椭圆中的地址就是我们的项目访问地址。

第六步:启动Tomcat,启动Nginx

Tomcat启动

image-20211016192935421

启动完成大概是这样的

image-20211016193607828

启动Nginx服务

image-20211016193030522

为了操作直接,nginx服务的启动这里使用的是直接点击它的可执行文件即可,其他的命令行启动方式可以了解一下。需要注意的是,nginx启动之后,如果过程中修改了html内容,需要停止服务(可以通过任务管理器结束该任务)再次启动才可以生效哈。

最后一步:访问项目

在浏览器地址栏输入localhost回车就可以进入项目了。

image-20211016193827397

以上就是所有通过Nginx前后端分离部署SSM项目的全部内容了。

附录:相关的一些操作技巧
  • idea中全局替换的快捷键方式

    Ctrl+Shift+R

  • idea中页面内容关键词搜索

  • Ctrl+F

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/530341.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

解析大语言模型训练三阶段

大语言模型的训练过程一般包括3个阶段:预训练(Pre-training)、SFT(有监督的微调,Supervised-Finetuning)以及RLHF(基于人类反馈的强化学习,Reinforcement Learning from Human Feedb…

maxpool long数据类型报错

报错: RuntimeError: “max_pool2d” not implemented for ‘Long’ 源码: import torch from torch import nn from torch.nn import MaxPool2dinput torch.tensor([[1, 2, 0, 3, 1],[0, 1, 2, 3, 1],[1, 2, 1, 0, 0],[5, 2, 3, 1, 1],[2, 1, 0, 1, 1…

【uniapp】多端打包(h5...)

1. h5 HBuilder X -> 项目目录中manifest.json 发行 查看打包文件(用浏览器打开就行了)或者直接运行在浏览器中

android支付宝接入流程

接入前准备 接入APP支付能力前,开发者需要完成以下前置步骤。 本文档展示了如何从零开始,使用支付宝开放平台服务端 SDK 快速接入App支付产品,完成与支付宝对接的部分。 第一步:创建应用并获取APPID 要在您的应用中接入支付宝…

idea中jdk版本的配置

配置JDK版本的步骤如下: 下载JDK安装文件:首先,需要从Oracle官方网站(https://www.oracle.com/java/technologies/javase-jdk8-downloads.html)下载适合您操作系统的JDK版本。 安装JDK:双击下载的安装文件…

unity按路径移动

using System; using System.Collections; using System.Collections.Generic; using UnityEngine;public class FollowPathMove : MonoBehaviour {public Transform[] wayPointArray;[SerializeField] private Transform PathA;//路径点的父物体[SerializeField]private Trans…

【学习 在服务器上使用bypy直接下载百度云盘的资源。

参考:bypy 具体步骤 step1: pip install bypystep2: bypy info第一次输入该命令, 点击进入网址,点击登陆后,获取token(10分钟内有效),然后输入到命令行:…

华为海思校园招聘-芯片-数字 IC 方向 题目分享——第二套

华为海思校园招聘-芯片-数字 IC 方向 题目分享(共9套,有答案和解析,答案非官方,未仔细校正,仅供参考)——第二套(共九套,每套四十个选择题) 部分题目分享,完整版获取&am…

真实世界的映照-DDD实体

什么是实体? 实体,官方的解释是:实体(Entity,又称为Reference Object)很多对象不是通过他们的属性定义的,而是通过一连串的连续事件和标识定义的。主要由标识定义的对象被称为ENTITY。 但&…

人工智能——机器学习概述

1. 人工智能 1.1. 概念 人工智能(Artificial Intelligence,AI),是新一轮科技革命和产业变革的重要驱动力量, [26]是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。 人工智能是智能学科重要的组…

ChromeDriver / Selenium-server

一、简介 ChromeDriver 是一个 WebDriver 的实现,专门用于自动化控制 Google Chrome 浏览器。以下是关于 ChromeDriver 的详细说明: 定义与作用: ChromeDriver 是一个独立的服务器程序,作为客户端库与 Google Chrome 浏览…

GFS部署实验---gfs9.6版本---网络源安装

目录 1、部署环境 2、更改节点名称 3、准备环境 4、做主机映射--/etc/hosts/ 5、yum网络源直接安装客户端软件 1.安装公网源 2.安装服务 3.开启服务 6、添加节点到存储信任池中 7、创建卷 1、创建数据目录 2、创建分布式卷 3、创建复制卷 4、创建分布式复制卷 5、…

每天五分钟深度学习:如何理解逻辑回归算法的假设函数?

本文重点 我们在机器学习专栏中已经学习了逻辑回归算法,本次课程我们将重温逻辑回归算法,该算法适用于二分类的问题,本文主要介绍逻辑回归的假设函数。我们在学习线性回归算法的时候,我们已经知道了线性回归算法的假设hθ(x)=θTX(参数θ的转置*X),但是对于逻辑回归而言…

GEE:基于GEDI-4A 级(L4A)数据和机器学习方法预测地上生物量密度(AGBD;单位为 Mg/ha)

作者:CSDN @ _养乐多_ 本文将介绍在 Google Earth Engine (GEE)平台上使用GEDI-4A 级(L4A)数据和机器学习方法预测地上生物量密度(AGBD;单位为 Mg/ha)的方法和代码。 代码包括(1) Landsat 和 GEDI 影像预处理;(2)特征变量(光学/雷达/时序/纹理/物候/地表温度/主…

「44」直播间换脸,揭开神秘的面纱……

「44」换脸神器 让你瞬间秒变「明星脸」带货 DeepFace是Facebook的人脸识别系统之一,旨在在照片和视频中准确识别和标识人脸。它使用深度学习和神经网络技术来进行高度精确的人脸匹配和验证。 DeepFace利用了大量的训练数据和先进的人脸识别算法,能够…

Jmeter02-2:参数化组件其他方式

0、Jmeter组件:参数化概述 0.1 是什么? 参数化是动态的获取并设置数据 0.2 为什么? 比如执行批量操作时,批量插入或批量删除,之前数据都是手写的,每执行完都要修改一次,效率太低 而参数化就是…

监控指标体系:交互延迟上的探索与最佳实践

FID 在互联网高速发展的时代,用户体验已成为企业竞争的关键所在。网页性能作为用户体验的重要组成部分,直接影响着用户的满意度和工作效率。First Input Delay(FID)作为衡量网页性能的重要指标,越来越受到业界关注。今天,让我们一起来深入了解FID,探讨如何优化FID以提升…

Verilog实现手表计时

实现手表的计时功能: 1.具有start启动信号、pause暂停信号,可以自定义其触发机制。 2.具有时间更改接口,可以更改时、分、秒。 3.输出时、分、秒。 Verilog设计 模块端口定义: module watch1(input wire clk …

蓝桥杯加训

1.两只塔姆沃斯牛&#xff08;模拟&#xff09; 思路&#xff1a;人和牛都记录三个数据&#xff0c;当前坐标和走的方向&#xff0c;如果人和牛的坐标和方向走重复了&#xff0c;那就说明一直在绕圈圈&#xff0c;无解 #include<iostream> using namespace std; const i…

软考高级架构师:TCP/IP 协议 和 OSI 七层模型

一、AI 讲解 TCP/IP 协议族是一组计算机网络通信协议的集合&#xff0c;其中TCP和IP是两个核心协议。TCP/IP 协议族通常被用来参照互联网的基础通信架构。与之相对的OSI七层模型&#xff0c;是一个更为理论化的网络通信模型&#xff0c;它将网络通信分为七个层次。 TCP/IP 与…