美文网首页前端全栈解决方案Java
基于前后端分离的Nginx+Tomcat动静分离

基于前后端分离的Nginx+Tomcat动静分离

作者: 最后的轻语_dd43 | 来源:发表于2019-04-27 13:15 被阅读50次

    1.什么是动静分离

    “动”与“静”

    在弄清动静分离之前,我们要先明白什么是动,什么是静。

    在Web开发中,通常来说,动态资源其实就是指那些后台资源,而静态资源就是指Html、img、js、css等文件。

    动静分离就是将动态资源和静态资源分开,将静态资源部署在Nginx上,当一个请求来的时候,如果是静态资源的请求,就直接到nginx配置的静态资源目录下面获取资源,如果是动态资源的请求,nginx利用反向代理的原理,把请求转发给后台应用去处理,从而实现动静分离。

    好处

    tomcat的优势在于少量的接收并处理复杂的http请求(将用户请求读写数据库等),nginx的优势在于能够大量的接收并处理简单的http请求(将http请求转发或者加个header、body等)。

    将Html、img、js、css等这种静态资源交给nginx,将用户需要读写数据库等请求交给tomcat是对各自优势的最大利用。

    详解

    Nginx与tomcat各自的优势与区别详解参考:tomcat 与 nginx,apache的区别是什么?.

    2.环境准备

    需要nginx、tomcat、SpringBoot

    2.1 linux

    linux环境下的nginx下载、安装、使用

    linux环境下的jdk8下载、安装、使用

    linux环境下的tomcat下载、安装、使用

    2.2 windows

    windows环境下nginx下载解压后,即可使用。
    Windows下Nginx的启动、停止等命令

    由于使用SpringBoot,所以使用内嵌的tomcat。

    3.正式部署

    3.1 前台

    前台使用一个ajax请求后端,新建一个index.html

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>前后端分离</title>
            <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.2/jquery.js"></script>
            <script type="text/javascript">
                $(function(){
                    $("#loginBtn").click(function(){
                        $.post(
                        "http://localhost:8080/username",
                        function(rtn){                  
                            $("#name").text(rtn.username)
                        });
                    });
                });
            </script>
        </head>
        <body>
            <form>
                <input type="button" value="查看当前用户" id="loginBtn">
                <div id="name" style="color:#00FF00">
                  
                </div>
            </form>
        </body>
    </html>
    

    将index.html放到nginx的html目录下(将nginx/html目录下的文件都删了)。

    正式部署时,只需要将静态资源扔到html目录下即可

    3.2 后台

    后台使用SpringBoot,只需一个接收请求的controller即可,这里为了省事,直接在Application里面写controller了。

    package com.example.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    @RestController
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
        @RequestMapping(value = "/username", method = {RequestMethod.GET, RequestMethod.POST})
        public User username() {
            // 假装请求了数据库
            User user = new User("tom");
            return user;
        }
    
        class User {
            private String username;
    
            public User(String username) {
                this.username = username;
            }
    
            public String getUsername() {
                return username;
            }
    
            public void setUsername(String username) {
                this.username = username;
            }
        }
    }
    
    

    启动SpringBoot项目可以访问到

    SpringBoot

    正式部署时,只需要将SpringBoot打的jar包扔到服务器上启动即可

    //打jar
    mvn clean package -Dmaven.test.skip=true
    //启动jar
    nohup java -jar ROOT.jar &
    

    3.3 nginx.conf

    worker_processes  1;
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
        server {
            #监听8080端口,代理前端请求
            listen       80;
            server_name  localhost;
            location / {
                # 默认访问html下的index.html
                index  index.html;
            }  
        }
        server {
            #监听8080端口,代理后端请求
            listen       8080;
            server_name  localhost; 
            location / {
            proxy_pass http://localhost:8080;
            proxy_set_header X-Real-IP $remote_addr;
          }
            
        }
    }
    
    

    启动nginx

    start nginx
    

    nginx.conf的更多配置

    Nginx反向代理、负载均衡、动静分离、缓存、压缩、防盗链、跨域访问

    nginx.conf详细配置

    3.4前后端分离导致动静分离的跨域问题

    访问http://localhost/

    跨域
    Access to XMLHttpRequest at 'http://localhost:8080/username' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    

    由于前后端分离了,所以前端http://localhost/使用ajax请求http://localhost:8080/发生了跨域问题。

    详解:

    CORS解决跨域问题

    Jsonp解决跨域问题

    这里直接给出解决方案,使用CORS解决跨域问题

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
    import org.springframework.web.filter.CorsFilter;
    
    @Configuration
    public class GlobalCorsConfig {
        @Bean
        public CorsFilter corsFilter() {
            //1.添加CORS配置信息
            CorsConfiguration config = new CorsConfiguration();
            //1) 允许的域,不要写*,否则cookie就无法使用了
            config.addAllowedOrigin("http://localhost");
            //2) 是否发送Cookie信息
            config.setAllowCredentials(true);
            //3) 允许的请求方式
            config.addAllowedMethod("GET");
            config.addAllowedMethod("POST");
            config.addAllowedMethod("OPTIONS");
            config.addAllowedMethod("HEAD");
            config.addAllowedMethod("PUT");
            config.addAllowedMethod("DELETE");
            config.addAllowedMethod("PATCH");
            // 4)允许的头信息
            config.addAllowedHeader("*");
    
            //2.添加映射路径,我们拦截一切请求
            UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
            configSource.registerCorsConfiguration("/**", config);
    
            //3.返回新的CorsFilter.
            return new CorsFilter(configSource);
        }
    }
    

    放到Application.java同目录及以下即可

    结构:

    GlobalCorsConfig位置

    重启项目,再次访问http://localhost/,访问成功。

    访问成功

    4.总结

    总的来说就是将静态资源html、js、css等放入nginx中,将动态请求交给tomcat。

    如果发生跨域,需要在解决跨域问题。

    5.答疑

    Q:该例子就一个html静态资源为什么不放到项目的static下?放到static下不就不会跨域了吗?
    A:因为这只是一个例子,模拟动静分离。一个真实的项目,可能将html等静态资源放到不同于后台的服务、或者CDN上,那时候就一定会发生跨域问题。

    相关文章

      网友评论

        本文标题:基于前后端分离的Nginx+Tomcat动静分离

        本文链接:https://www.haomeiwen.com/subject/fqxknqtx.html