手机手机删除tencent文件夹 是什么文件夹可以删除

刚刚参加完一个项目,背景:后端是用java,后端服务已经开发的差不多了,现在要通过web的方式对外提供服务,也就是B/S架构。后端专注做业务逻辑,不想在后端做页面渲染的事情,只向前端提供数据接口。于是协商后打算将前后端完全分离,页面上的所有数据都通过ajax向后端取,页面渲染的事情完全由前端来做。另外还有一个紧急的情况,项目要紧急上线,整个web站点的开发时间只有两周,两周啊!于是在这样的背景下,决定开始一次前后端完全分离的尝试。
之前开发都是同步渲染和异步渲染混搭的,有些东西可以有后端PHP帮你编译好,如通用的页面模板,后端传回的页面参数等。提前预感到这次完全分离可能会遇到一些困难,但是项目上线要紧,也不能深入搞架构,于是打算就用jQuery+handlebars,jQuery来完成页面逻辑和DOM操作,用handlebars来完成页面渲染,这个方案是如此的简单粗暴,但好处能最稳妥的保证项目按期完成。其实前后端分离并不是一件容易的工作,这么做会有诸多不完善之处,后面再谈。
浅谈前后端分离
所谓的前后端分离,到底是分离什么呢?其实就是页面的渲染工作,之前是后端渲染好页面,交给前端来显示,分离后前端需要自己拼装html代码,然后再显示。前端来管理页面的渲染有很多好处,比如减少网络请求量,制作单页面应用等。事情听起来简单,但这么一分离又会牵扯到很多问题,比如:
&资源的按需加载。尤其是在单页应用中。
页面展现逻辑。分离让前端的逻辑陡增,需要有一个良好的前端架构,如mvc模式。
数据校验。因为页面数据都是从后端请求来的,必须校验要展示的数据是否合法,避免xss或其他安全问题。
短暂白屏。因为页面不是同步渲染的,在请求数据完毕之前,页面是白屏的,体验很不好。
代码的复用。众多的模板、逻辑模块需要良好组织实现可复用。
路由控制。无刷新的前端体验同时毁掉了浏览器的后退按钮,前端视图需要有一套路由机制。
SEO。服务端不再返回页面,前端根据不同的逻辑呈现不同的视图(并非页面),要对搜索引擎友好需要做很多额外的工作。
以上每一个问题都够棘手,要处理好需要有设计精良又符合实际项目的方案。现在已经有很多框架可以帮我们做这些事情,Backbone, EmberJS, KnockoutJS, AngularJS, React, avalon等等,利用它们可以架构起一个富前端。但框架毕竟是框架,要利用到实际项目中,还是需要有自己的设计,框架并不能解决所有的问题。
之前也有看过淘宝团队的实践,利用nodejs做一个中间层,处理页面渲染、路由控制、SEO等事情,将前后端的分界线进行了重新定义。个人感觉这应该是一个正确的方向,有点颠覆的感觉,前端走向工程化,将变成真正的全栈式大前端。不知现在这种架构是否在淘宝全面铺开,真有点期待看看效果。
以上的框架,还有淘宝的实践,毕竟都是大牛之作,我这个小辈也只是参考学习过,未能在实际项目中使用。低头看看自己现在手头的项目,1个前端,2周时间,要完成一个完整的web项目,还是用最稳妥最低级的方式来搞吧~
项目整体并不是一个单页应用,但有些模块需要做成局部的单页操作,像这种需要分步完成的操作,只需局部加载子页面即可。
因此,一个模块有一个主html页面,初始只有一些基本的骨架,有一个名字相同的js文件,该模块逻辑都在此js文件中,有一个名字相同的css文件,该模块的所有样式都定义在此css文件中。
需要异步加载的子页面,像上图中每个步骤的页面,我都使用jQuery的$.load()方法来加载,此方法能在页面某个容器中加载内容,并可指定回调函数,使用起来很方便。被异步加载的子页面我都用_开头,如_step1.html,用于做区分。
为了确保浏览器的前进后退按钮可用,我使用了hash来做路由标记,页面地址如:publish.html#step2。有个缺陷是hash并不会发送给服务器,所以SEO就废了。事实上使用history API也可以更优雅的解决问题,但需要考虑兼容性,还有额外工作要做,考虑时间因素,退而求其次,况且本项目也无需做SEO。或者像淘宝的方案那样,nodejs层与浏览器层统一路由,SEO问题可以迎刃而解。但又明显不在本人的实力范围之内,汗&!
除了用$.load异步加载的子页面,剩余的局部页面就是用handlebars提供的模板渲染了,我使用了handlebars的预编译功能,不得不说很强大,一来节约了页面加载阶段所需的编译时间(编译handlebars模板),二来编译后的模板(js文件)方便复用。
接下来就是前端逻辑如何组织,因为没有用mv*框架,所以只能靠自己来写一个便于开发的结构。如上面所述,每个模块有一个主js文件,文件内容结构如下:
var publish = {
&&&&&init : function(){
&&&&&&&&&&this.renderData(param);
&&&&&&&&&&this.initListeners();
&&&&&renderData : function(param){
&&&&&&&&&&
&&&&&initListeners : function(){
&&&&&&&&&&$(document.body).delegates({
&&&&&&&&&&&&&&&'.btn' : function(){
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&},
&&&&&&&&&&&&&&&'.btn2' : function(){
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&},
&&&&&&&&&&&&&&&'.checkbox' : {
&&&&&&&&&&&&&&&&&&&&'change' : function(){
&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&}
&&&&&&&&&&});
每个模块给一个命名空间,所有的方法都挂在上面,js文件中只做函数的定义,不立即执行任何东西,然后在html文件中调用入口方法:publish.init()。业务逻辑都封装到函数中,如上面的renderData,然后供其他地方调用。页面的事件监听器统一都注册在body元素上,用事件代理来完成,为了避免写太多的on、click之类代码,为jQuery扩展了一个delegates方法,用来以配置的方式统一绑定监听器,用法如上所示。把delegates定义的代码也放出来吧:
$.fn.delegates = function(configs) {
&&&&&el = $(this[0]);
&&&&&for (var name in configs) {
&&&&&&&&&&var value = configs[name];
&&&&&&&&&&if (typeof value == 'function') {
&&&&&&&&&&&&&&&var obj = {};
&&&&&&&&&&&&&&&obj.click =
&&&&&&&&&&&&&&&value =
&&&&&&&&&&};
&&&&&&&&&&for (var type in value) {
&&&&&&&&&&&&&&&el.delegate(name, type, value[type]);
&&&&&&&&&&}
&&&&&return this;
基本的结构就是这样,没有什么新技术,只是把现有的东西做了一下组合。但工作到此还远远没有结束,在实际应用中还会有一些东西需要处理,下面来详细说说:
公共头部底部的引用
这是一个比较棘手的问题,一般通用的头部和底部会放一些公共的代码,如页面外层结构html代码,站点使用的库如jQuery、handlebars,站点通用js和css文件。在传统的开发中,通常是写一个单独的文件如head.html,在其他页面中用后端代码如include语句引入,由此来进行复用。
现在前后端分离后,无法依靠后端来给你渲染,所以得在前端做了。既然用了handlebars,很容易想到把公用部分写成一个模板,然后预编译出来,生成一个header.js文件,然后在其他页面引用。然而在实际操作中发现了一个问题,handlebars是静态模板,编译后生成的字符串通过innerHTML的方式插入到页面,在一般的模板中这样是没问题的。现在有个问题是header中有一些&script&标签,外链着要使用的库,通过innerHTML插入&scirpt&标签,浏览器并不会发送请求加载对应的js文件,所以就出问题了。
搜索、尝试了多种方法后,最终的方案定为:用document.write()将编译结果写到页面,这样&script&标签能够正常加载。所以每个页面使用头部的代码就变成这样:
&script src="static/js/tpl/head.js"&&/script&
&&&&&&div id="header"&
&&&&&&&&&&&script src="static/js/includeHead.js"&&/script&
&&&&&&/div&
includeHead.js中的代码如下:
function includeHead(){
&&&&&var header = document.getElementById('header');
&&&&&var compileHead = Handlebars.templates['head'];
&&&&&var head = compileHead({});
&&&&&document.write(head);
includeHead();
看着是有点别扭,不过为了实现功能,目前也就只能这样了。
如上面所述,jQuery的$.load()方法可以满足加载子页面的需求,现在需要解决的问题是,不管用户刷新页面还是前进后退,我们都得根据hash值来渲染对应的视图,其实就是路由控制。这个时候就需要监听hashchange事件了,我定义了一个loadPage方法用来加载子页面,然后绑定监听器如下:
window.onhashchange = this.loadP
在loadPage方法中,根据hash的值来调用$.load()方法,子页面的初始化工作,在$.load()的回调函数中指定。
这样做还有一个便捷之处,我们切换视图不必手动调loadPage方法,只需要修改页面的hash就可以了,hash发生变化被监听到,自动加载对应的子页面。例如,点击下一步进入步骤二:
'.next' : function(){
&&&&&&&&location.href = '#step2';
如此便实现了一个简单的路由控制,由于不是整站单页面,也没有多级路由,这样完全可以满足需求。至于SEO,就只能呵呵了,正好项目也不需要做SEO,否则此方法得作罢。
另外想说的一点就是页面的缓存,异步加载来的内容可以存在localStorage中,也可以放在页面上进行显隐控制,这样用户在频繁切换视图的时候无需再次请求,回到上一步的时候之前填好的表单数据也不会消失,体验会非常好。
页面间参数传递
有时候我们需要给访问的页面传参数,比如访问一个设备的详细信息页,要把设备id给传过去,detail.html?id=1,这样detail页面可以根据id去请求对应的数据。传统由后端渲染的页面,url中的参数会发送到服务端,服务端接收后可以再渲染到页面上供js使用。我们现在不行了,请求页面压根不跟后端打交道,但这个参数是必不可少的,所以需要前端有一套传递参数的机制。
其实非常简单,通过location.href可以拿到当前的url地址,然后进行字符串匹配,把参数提取出来就可以了。看上去挺土鳖的,但工作起来良好,另外也有考虑过用cookie来传递,感觉有点麻烦。
由于这些参数通常是写在&a&标签上的,而&a&标签又是根据动态数据渲染出来的(因为是动态参数),我们不可能在页面渲染完后,用js修改所有&a&标签的href值,给它追加一个参数。怎么办呢?这时候handlebars就派上用场了,我们可以使用handlebars万能的helper,在渲染页面的时候直接查询url中的参数,然后输出在编译好的代码中。我在handlebars中注册了一个helper,如下:
Handlebars.registerHelper('param', function(key, options){
&&&&var url = location.href.replace(/^[^?=]*\?/ig, '').split('#')[0];
&&&&var json = {};
&&&&url.replace(/(^|&)([^&=]+)=([^&]*)/g, function (a, b, key , value){
&&&&&&&&try {
&&&&&&&&&&&&key = decodeURIComponent(key);
&&&&&&&&} catch(e) {}
&&&&&&&&try {
&&&&&&&&&&&&value = decodeURIComponent(value);
&&&&&&&&} catch(e) {}
&&&&&&&&if (!(key in json)) {
&&&&&&&&&&&&json[key] = /\[\]$/.test(key) ? [value] :
&&&&&&&&else if (json[key] instanceof Array) {
&&&&&&&&&&&&json[key].push(value);
&&&&&&&&else {
&&&&&&&&&&&&json[key] = [json[key], value];
&&&&return key ? json[key] :
这个名为param的helper可以输出你所要查询的参数值,然后可以直接写在模板中,如:
&a href="detail.html?id={{param id}}"&设备详细信息&/a&
这样就方便多了!但是这么做有没有问题呢?其实是有些不完美的,如果你考虑&性能&二字的话。一个url中参数的值是固定的,而你每次使用这个helper都会计算一遍,白白做了多余的事情。如果handlebars可以在模板中定义常量就好了,可惜我找遍文档没发现有这个功能。只能为了方便牺牲性能了,也正印证了我标题中所说的&简单粗暴&,呵呵。
数据的校验和处理
由于数据是由后端传来的,有很多不确定性,数据可能不合法,或者结构有错,或者直接是空的。因此前端有必要对数据做一个合法性的校验。借助handlebars,可以很方便的进行数据校验。没错,就是利用helper。handlebars内置的helper如if、each都支持else语句,出错信息可以在else中输出。如果需要个性化的校验,我们可以自己定义helper来完成,关于如何自定义helper,我之前研究了下,写过一篇文章:。总之自定义helper很强大,可以完成你所需的任何逻辑。
数据的格式化,如日期、数字等,也可以通过helper来完成。
另外一方面,前端还应对数据进行html转义,避免xss,由于handlebars已经给做了html转义,所以我们可以直接忽略此项了。
本文是我刚刚参加完一个项目后所写,记录一下整个过程遇到的问题及处理方式,其他的一些细碎点如表单异步提交什么的,不是本文重点,不写了。这是我第一次实践前后端完全分离的项目,整个前端全由我来设计、开发。2周时间,凭着这套方案,项目按期开发完成,而且还提前完成了,预留出一天多的时间测试了一遍。
虽然开发任务是完成了,但是回头看一下整个方案,并不是很优雅也没有什么技术含量,文章开头提到的几个问题都没有解决。所以命题为简单粗暴的方案,都是为了赶工期啊。
最后,如果给我再来一次的机会,并且时间充足,我一定要尝试用mv*方案来搞一下,或angular,或avalon。
阅读(...) 评论()前后端分离的一点实践_Java_ThinkSAAS
前后端分离的一点实践
前后端分离的一点实践
内容来源: 网络
什么是前后端分离
对于这个问题,其实可以看看我的学习历程,我觉得很好的体现了Web开发模式的演化。
石器时代:那正是本人刚学JSP的时候,写了一个简单的商城DEMO,所有的业务逻辑,数据库的交互以及Javascript代码等都杂糅在.jsp文件中,好处就是简单,几个JSP页面就能解决问题,但也正是由于内嵌了大量的Java代码,前后端的代码挤在一个文件中,后期可维护性很差,代码完全没有可读性,而且更改一个CSS样式都必须要重启服务器才行
文明兴起:那之后学习了Servlet,开始重构商城Demo,将数据库的交互,业务逻辑,抽象到Servlet类中,JSP中的Java代码慢慢消失,但还是造成了Controller类过于肥胖的问题
近现代: 这个时候已经学习了SSH、Spring Family,搞过PlayFramework,JFinal等各种小玩意,对于MVC模式以及架构慢慢有了自己的理解,代码的可维护性,可读性各方面有了明显的提升,项目各个层次的职责比较清晰:Model层采用SpringDATA,Entity只需少量注解,DAO层只需实现相应的接口,实现交给Spring去注入,Controller层则采用SpringMVC,View采用Freemarker,Velocity等模板,功能很强大,最重要的是断了你在前端页面中写Java代码的念头。但是这个阶段依然存在相关的问题:
View层仍然职责不清晰,究竟是该让前端学习点后台技术去直接套JSP模板,还是应该先在自己的机器上写好页面,然后交给后台开发人员去改造成JSP/FTL等
开发效率底下,不利于前后台的开发测试,后端不仅需要写逻辑代码,还需要去关注视图层
可以看出,前后端分离其实是职责的分离,将不同逻辑抽象出来,让前后端开发人员能够更好的合作,对于我个人说,能够更专一,开发后端的时候,只需要专心解决后端的问题,前端同理
怎么做前后端的分离
我目前的做法是:将Java作为一种服务存在,仅需要提供RESTFul接口即可,前端目前采用AngularJS,调用后端API,解析JSON数据,静态HTML页面
交给Nginx代理,下面是具体配置:
Java Layer
Java采用SpringMVC,方法返回JSON数据,然后运行带后台中,监听8080端口,处理来自前台的请求
@RestController
@RequestMapping("api")
public class APIController {
@Autowired
private NewsItemService itemS
@Autowired
private NewsDetailService detailS
* API:获取单页新闻
* @param pageable
@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);
* 获取指定ID新闻
* @param id
@RequestMapping(value ="/news/{id}")
public NewsItem showNewsItem(@PathVariable("id") Long id){
NewsItem item = itemService.get(id);
采用AngularJS,充当Controller层,前后端实现了真正的分离,但还是有点问题的。
index.html
&!doctype html&
&html lang="zh-CN"ng-app="dznews"&
&title&DzNews&/title&
&div ng-view&&/div&
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 =
newsControllers.controller("newsDetailCtrl",['$scope', '$routeParams','$http','$sce',
function($scope, $routeParams,$http,$sce) {
$http.get("/api/news/detail/"+$routeParams.id).success(function (data) {
$scope.detail =
$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/
#index index.html index.
try_files $uri $uri/ /index.html =404;
location /api/ {
proxy_pass http://localhost:8080;
proxy_set_header Host $
proxy_set_header X-Real-IP $remote_
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_
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只作为无状态的服务存在,可以部署多个实例。
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信前后端分离时代,java后端用什么技术_java吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:565,716贴子:
前后端分离时代,java后端用什么技术收藏
前端用不上java,后端肯定是restful api了,如果用java开发,一般用什么高开发效率的轻量级技术?
java培训---美国上市公司出品,入学签订就业协议,名企疯抢达内学员.java,O基础小班授课,java专家领衔授课,免费试听,满意后付款!
restful和java又不是对立的
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或

我要回帖

更多关于 手机删除tencent文件夹 的文章

 

随机推荐