先后端分离的一点实践

什么是先后端分离

对于这个问题,其实能够看看个人学习历程,我以为很好的体现了Web开发模式的演化。javascript

石器时代:那正是本人刚学JSP的时候,写了一个简单的商城DEMO,全部的业务逻辑,数据库的交互以及Javascript代码等都杂糅在.jsp文件中,好处就是简单,几个JSP页面就能解决问题,但也正是因为内嵌了大量的Java代码,先后端的代码挤在一个文件中,后期可维护性不好,代码彻底没有可读性,并且更改一个CSS样式都必需要重启服务器才行html

文明兴起:那以后学习了Servlet,开始重构商城Demo,将数据库的交互,业务逻辑,抽象到Servlet类中,JSP中的Java代码慢慢消失,但仍是形成了Controller类过于肥胖的问题前端

近现代:这个时候已经学习了SSH、Spring Family,搞过PlayFramework,JFinal等各类小玩意,对于MVC模式以及架构慢慢有了本身的理解,代码的可维护性,可读性各方面有了明显的提高,项目各个层次的职责比较清晰:Model层采用SpringDATA,Entity只需少许注解,DAO层只需实现相应的接口,实现交给Spring去注入,Controller层则采用SpringMVC,View采用Freemarker,Velocity等模板,功能很强大,最重要的是断了你在前端页面中写Java代码的念头。可是这个阶段依然存在相关的问题:html5

  1. View层仍然职责不清晰,到底是该让前端学习点后台技术去直接套JSP模板,仍是应该先在本身的机器上写好页面,而后交给后台开发人员去改形成JSP/FTL等java

  2. 开发效率底下,不利于先后台的开发测试,后端不只须要写逻辑代码,还须要去关注视图层数据库

能够看出,先后端分离实际上是职责的分离,将不一样逻辑抽象出来,让先后端开发人员可以更好的合做,对于我我的说,可以更专注,开发后端的时候,只须要专心解决后端的问题,前端同理。后端

怎么作先后端的分离

我目前的作法是:将Java做为一种服务存在,仅须要提供RESTFul接口便可,前端目前采用AngularJS,调用后端API,解析JSON数据,静态HTML页面。api

交给Nginx代理,下面是具体配置:安全

Java Layer

Java采用SpringMVC,方法返回JSON数据,而后运行带后台中,监听8080端口,处理来自前台的请求服务器

@RestController
    @RequestMapping("api")
    public class APIController {

        @Autowired
        private NewsItemService itemService;

        @Autowired
        private NewsDetailService detailService;
        /**
         * API:获取单页新闻
         * @param pageable
         * @return
         */
        @RequestMapping(value = "/news")
        public List<NewsItem> showNewsPage(Pageable pageable){
            return itemService.findAll(pageable);
        }
        /**
         * API:根据指定NewsItem ID
         *      获取新闻详情
         */
        @RequestMapping(value = "/news/detail/{id}")
        public NewsDetail showNewsDetail(@PathVariable("id")Long id){
            NewsDetail detail = detailService.findByNewsItemId(id);
            return detail;
        }
        /**
         * 获取指定ID新闻
         * @param id
         * @return
         */
        @RequestMapping(value = "/news/{id}")
        public NewsItem showNewsItem(@PathVariable("id") Long id){
            NewsItem item  = itemService.get(id);
            return item;
        }
        。。。
    }

FrontEnd

采用AngularJS,充当Controller层,先后端实现了真正的分离,但仍是有点问题的。

index.html
<!doctype html>
<html lang="zh-CN" ng-app="dznews">
<head>
    <title>DzNews</title>
</head>
<body >
<div ng-view></div>
</body>
</html>
app.js:
var dznews = angular.module('dznews', [
  'ngRoute',
  'newsControllers',
]);
dznews.config(['$routeProvider','$locationProvider',
  function($routeProvider,$locationProvider) {
      $routeProvider.
          when('/',{
            templateUrl: 'part/news_list.html',
            controller: 'listController'
          }).
          when('/news', {
              templateUrl: 'part/news_list.html',
              controller: 'listController'
          }).
          when('/news/:id', {
              templateUrl: 'part/news_detail.html',
              controller: 'newsDetailCtrl'
          }).
          otherwise({
              redirectTo: '/news'
          });

          // use the HTML5 History API
          $locationProvider.html5Mode(true);
  }]);


var newsControllers = angular.module('newsControllers', []);

newsControllers.controller('listController', function ($scope,$http) {
  $scope.page = 0;
  <!--/api/news交给Nginx转发给8080端口的Java后端服务-->
  $http.get('/api/news').success(function(data) {
      $scope.newses = data;
  });
});

newsControllers.controller("newsDetailCtrl",['$scope', '$routeParams','$http','$sce',
  function($scope, $routeParams,$http,$sce) {
        $http.get("/api/news/detail/"+$routeParams.id).success(function (data) {
          $scope.detail = data ;
          $scope.detail.content = $sce.trustAsHtml($scope.detail.content);
      });
}]);

Nginx Layer

Nginx监听80端口,静态请求交由Nginx处理,动态请求转发给8080端口的Java后端服务,配置以下供参考:

try_files:因为AngularJS是单页应用,一个ng-app对应一个页面,并且实现了本身的前端路由机制,这样就能够由一个ng-app管理多个页面,只需替换局部的ng-view,可是这样就会有一个问题,当咱们直接访问首页,跳转到/news/:id的时候是没问题的,
可是当直接访问/news/:id这个网址的时候,就会出现404的错误,就其缘由,是由于WebServer找不到对应的页面,因此须要将全部的由AngularJS路由管理的URL都转发到ng-app便可,

location /  {
    root   DzNewsBackEnd/app;
    #index  index.html index.htm;
    try_files $uri $uri/ /index.html =404;
}



location /api/ {
    proxy_pass http://localhost:8080;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size 10m;
    client_body_buffer_size 128k;
    proxy_connect_timeout 90;
    proxy_send_timeout 90;
    proxy_read_timeout 90;
    proxy_buffer_size 4k;
    proxy_buffers 4 32k;
    proxy_busy_buffers_size 64k;
    proxy_temp_file_write_size 64k;
}

总结

在用这种方式进行开发的时候,当我完成后端API的开发,就能够专一去写前端的页面和JS逻辑,遇到BUG的时候,也至关容易调试,由于很容易发现是哪一层的问题,但仍是存在一些短板,将全部的逻辑交由前端JS去执行,安全及性能方面存在不少短板,当进去首页的时候,会发现有一个明显的白屏,并且会暴露后端的API,所以须要在后端进行一些验证,例如OAUTH等方案,我我的倾向于中间加一层NodeJS,将全部的逻辑,session管理等都交由这层处理,也能够部署多个Node实例,再加上Nginx进行负载均衡处理,与Java部署在不一样的服务器上,这样Java只做为无状态的服务存在,能够部署多个实例。

相关文章
相关标签/搜索