整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

当Java遇见了Html-Jsp……

方微信:动力节点java学院

官方微博:动力节点

一、什么是Jsp

jsp是一种基于文本的程序,全名java server page,其特点是html和java程序共存。执行时jsp会被运行容器编译,编译后的jsp跟servlet一样,因此jsp是另一种形式的servlet。

二、jsp页面组成

jsp 页面包括以下内容:

  • 静态内容

  • 指令

  • 表达式

  • 小脚本

  • 声明

  • 注释

1.指令:

  • page指令: 通常位于jsp页面的顶端,同一个页面可以有多个page指令。

  • include指令:将一个外部文件嵌入到jsp文件中。

  • taglib指令 :使用标签定义新的自定义标签。

1.1其中page指令语法:

<%@ page 属性=“属性值”>

属性默认值
languagejava
import“”

1.2 include 指令

<%@ include file="url" %>

1.3 动作

  • include动作

    <jsp:include page="url" flush="true"/>

    include 动作和include指令区别

    描述 | include指令 | include 动作

    --- | --- | ---

    语法 | < % @ include file=""/> | < jsp:include page="url" flush="true"/>

    发生时间 | 页面转换期间 | 请求期间

    包含内容 | 文件实际内容 | 页面的输出

    转化servlet | 一个servlet | 2个servlet

    编译时间 | 较慢 | 较快

    执行时间 | 稍快 |较慢--每次资源必须被编译

    forward动作

    <jsp:forward page="url"/>

    ==request.getRequestDispatcher("/url").forward(res,resp);

    param动作

    <jsp:param name="参数名" value="参数值"/>常常与<jsp:forward>一起使用

    例子:

    <jsp:forward page="user.jsp">

    <jsp:param name="email" value="1233@154.com"/></jsp:forward>

    2.jsp注释

  • html注释

    <!-- html注释 -->//客户端可见

  • jsp 注释

    <%-- jsp注释 --%>//客户端不可见

  • jsp 脚本注释 //客户端不可见

//单行注射

/** 多行注释*/

3.jsp脚本

在jsp页面中执行的java代码,语法:

<% java 代码 %>

4.jsp声明

在jsp页面定义变量或者方法,语法

<%! java 代码 %>

举例:

<%!

String s="adele"; int add(int x,int y){ return x+y;

}

%>

5.jsp表达式

在jsp页面执行的表达式,语法:

<% =表达式 %>// 表达式不以分号结尾

举例:

<%!

String s="adele";%><h2> hello,<%=s %> </h2>

三、jsp生命周期

CC36B22A-503E-4C29-98BB-3B58038C140E.png

jspService()是用来处理客户端请求的,对于每一个请求,服务器会创建一个新的线程来处理该请求。以多线程方式执行大大降低对系统的资源需求,提高系统的并发量和缩短了响应时间,servlet是常驻在服务器内存中。

它同servlet 一样,jsp 实例初始化和销毁也会调用sevlet的init() 和destroy();

另外jsp还有自己的初始化方法_jspInit();_jspDestroy();

<%@ page language="java" contentType="text/html";charset="utf-8">

<%!

public void _jspInit(){

}public void _jspDestroy(){

}

%>

四、javaben的使用

动作元素:

动作元素为请求处理阶段提供信息。

Paste_Image.png

在jsp页面使用javaben

  • 像普通的java类一样,创建javabean;

  • 在jsp使用动作标签来使用 javaben

相关标签如下:

<jsp:useBwan id="" class="" scope="" />

<jsp:setProperty name="javabean 是例" property="*"/>(跟表单关联)

<jsp:setProperty name="javabean 是例" property="javaben 属性名"/>(跟表单关联)

<jsp:setProperty name="javabean 是例" property="javaben 属性名" value=""/>(手动设置)

<jsp:setProperty name="javabean 是例" property="javaben 属性名" param="request对象参数"/>(跟request参数关联)

<jsp:getProperty name="" property=""/>

举个例子:

首先用户 在login.jsp提交表单,然后用户在dologin.jsp 根据动作标签获取参数。

login.jsp

<form name="loginForm" action="dologin.jsp?mypass=999999" method="post">

<table>

<tr>

<td>用户名:</td>

<td><input type="text" name="username" value=""/></td>

</tr>

<tr>

<td>密码:</td>

<td><input type="password" name="password" value=""/></td>

</tr>

<tr>

<td colspan="2" align="center"><input type="submit" value="登录"/></td>

</tr>

</table>

</form>

dologin.jsp

<body>

<jsp:useBean id="myUsers" class="com.po.Users" scope="page"/>

<h1>setProperty动作元素</h1>

<hr>

<!--根据表单自动匹配所有的属性 -->

<%--

<jsp:setProperty name="myUsers" property="*"/>

--%>

<!--根据表单匹配所有部分的属性 -->

<%--

<jsp:setProperty name="myUsers" property="username"/>

--%>

<!--根表单无关,通过手工赋值给属性 -->

<%--

<jsp:setProperty name="myUsers" property="username" value="lisi"/>

<jsp:setProperty name="myUsers" property="password" value="888888"/>

--%>

<!--通过URL传参数给属性赋值 -->

<jsp:setProperty name="myUsers" property="username"/>

<jsp:setProperty name="myUsers" property="password" param="mypass"/>

<!-- 使用传统的表达式方式来获取用户名和密码 -->

<%--

用户名:<%=myUsers.getUsername() %><br>

密码:<%=myUsers.getPassword() %><br>

--%> <!-- 使用getProperty方式来获取用户名和密码 -->

用户名:<jsp:getProperty name="myUsers" property="username"/> <br>

密码:<jsp:getProperty name="myUsers" property="password"/><br>

<br>

<br>

<a href="testScope.jsp">测试javabean的四个作用域范围</a>

<%

request.getRequestDispatcher("testScope.jsp").forward(request, response); %>

</body>

javaben 四大作用域

  • page ,仅当前页面有效

  • request ,通过httpRequest.getAttribute()获取jvabean对象

  • session ,通过httpSession.getAttribute() 获取javabean对象

  • application,通过application.getAttribute方法获取javabean 对象。

五、cookie

1.概述:

由于http协议的无状态,无法保存用户的状态,所以需要用session和cookie.

cookie 是web服务器保存在客户端的一系列文本信息。它的作用时记录一些用户的行为,简化登陆,但是容易泄露用户信息。

2.jsp创建和使用cookie

  • 创建cookie

Cookie cookie=new Cookie(String ,Object);

  • 写入cookie

response.addCookie(cookie);

  • 读取 cookie

Cookie[] cookies=request.getCookies();

3.cookie的常用方法

  • setMaxAge();

  • setValue();

  • getName();

  • getValue();

  • getMaxAge();

举个列子: 使用cookie记住用户登陆的账号密码;

登陆界面:

<body>

<h1>用户登录</h1>

<hr>

<%

request.setCharacterEncoding("utf-8");

String username="";

String password = "";

Cookie[] cookies = request.getCookies(); if(cookies!=null&&cookies.length>0)

{ for(Cookie c:cookies)

{ if(c.getName().equals("username"))

{

username = URLDecoder.decode(c.getValue(),"utf-8");

} if(c.getName().equals("password"))

{

password = URLDecoder.decode(c.getValue(),"utf-8");

}

}

} %>

<form name="loginForm" action="dologin.jsp" method="post">

<table>

<tr>

<td>用户名:</td>

<td><input type="text" name="username" value="<%=username %>"/></td>

</tr>

<tr>

<td>密码:</td>

<td><input type="password" name="password" value="<%=password %>" /></td>

</tr>

<tr>

<td colspan="2"><input type="checkbox" name="isUseCookie" checked="checked"/>十天内记住我的登录状态</td>

</tr>

<tr>

<td colspan="2" align="center"><input type="submit" value="登录"/><input type="reset" value="取消"/></td>

</tr>

</table>

</form>

</body>

处理登陆逻辑的jsp

<body>

<h1>登录成功</h1>

<hr>

<br>

<br>

<br>

<%

request.setCharacterEncoding("utf-8"); //首先判断用户是否选择了记住登录状态

String[] isUseCookies = request.getParameterValues("isUseCookie"); if(isUseCookies!=null&&isUseCookies.length>0)

{ //把用户名和密码保存在Cookie对象里面

String username = URLEncoder.encode(request.getParameter("username"),"utf-8"); //使用URLEncoder解决无法在Cookie当中保存中文字符串问题

String password = URLEncoder.encode(request.getParameter("password"),"utf-8");

Cookie usernameCookie = new Cookie("username",username);

Cookie passwordCookie = new Cookie("password",password);

usernameCookie.setMaxAge(864000);

passwordCookie.setMaxAge(864000);//设置最大生存期限为10天

response.addCookie(usernameCookie);

response.addCookie(passwordCookie);

} else

{

Cookie[] cookies = request.getCookies(); if(cookies!=null&&cookies.length>0)

{ for(Cookie c:cookies)

{ if(c.getName().equals("username")||c.getName().equals("password"))

{

c.setMaxAge(0); //设置Cookie失效

response.addCookie(c); //重新保存。

}

}

}

} %>

<a href="users.jsp" target="_blank">查看用户信息</a>

</body>

使用cookie获取用户信息:

<body>

<h1>用户信息</h1>

<hr>

<%

request.setCharacterEncoding("utf-8");

String username="";

String password = "";

Cookie[] cookies = request.getCookies(); if(cookies!=null&&cookies.length>0)

{ for(Cookie c:cookies)

{ if(c.getName().equals("username"))

{

username = URLDecoder.decode(c.getValue(),"utf-8");

} if(c.getName().equals("password"))

{

password = URLDecoder.decode(c.getValue(),"utf-8");

}

}

} %>

<BR>

<BR>

<BR>

用户名:<%=username %><br>

密码:<%=password %><br>

</body>

3.cookie和 session的区别

sessioncookie
在服务端保存信息在客户端保存信息
保存的 object类型保存的是 string 类型
随会话结束,销毁数据可以长期保存在客户端中
重要信息不重要信息

如有问题请下方留言
来源:互联网

SP:Java Server Pages。JSP是一种网页的编码格式,不同于HTML的是JSP中是由 HTML中的标签指令 和 Java逻辑代码 拼凑而成, 其中的Java代码类似于JavaScript中的逻辑代码, 但相对比来说JSP中的Java代码更方便阅读和书写.

一:JSP的运行原理

当JSP页面被运行时,WEB容器会把请求交给JSP引擎处理,会将JSP翻译成一个_jspServlet,然后按照Servlet的调用方式来进行调用,

浏览器向服务器发请求,不管访问的是什么资源,其实都是在访问Servlet,所以当访问一个jsp页面时,其实也是在访问一个Servlet,服务器在执行jsp的时候,首先把jsp翻译成一个Servlet,所以我们访问jsp时,其实不是在访问jsp,而是在访问jsp翻译过后的那个Servlet,

二:Tomcat

Tomcat在Web中的作用:

Tomcat是Web中的容器,

当客户在Web服务器中输入请求的时候, 如果请求的动态页面, 那么Web服务器会创建一个Servlet来处理, Servlet就是Java代码, 只是在服务器端的Java代码, Servlet通过配置文件来拦截客户所发出的请求, 并进行相应的处理, 最后反馈到客户端.

在这一系列的请求中,Web服务器是如何创建出Servlet来对请求进行处理? 而Tomcat的作用就是帮助Web服务器来创建Servlet的

Tomcat是应用(java)服务器,它只是一个Servlet容器,是Apache的扩展,处理动态页面的部分

Tomcat各个文件夹的含义

  • bin:二进制执行文件。里面最常用的文件是startup.bat
  • conf:配置目录。里面最核心的文件是server.xml。可以在里面改端口号等。默认端口号是8080,也就是说,此端口号不能被其他应用程序占用。
  • lib:库文件。tomcat运行时需要的jar包所在的目录
  • logs:日志
  • temp:临时产生的文件,即缓存
  • webapps:web的应用程序。web应用放置到此目录下浏览器可以直接访问
  • work:编译以后的class文件。

当我们通过浏览器访问index.jsp时,服务器首先将index.jsp翻译成一个index_jsp.class,在Tomcat服务的work\Catalina\localhost\项目名\org\apache\jsp 目录下可以看到index_jsp.class的源代码文件index_jsp.java

index_jsp这个类是继承 org.apache.jasper.runtime.HttpJspBase这个类的,通过查看Tomcat服务器的源代码,可以知道在apache-tomcat-6.0.20-src\java\org\apache\jasper\runtime目录下存HttpJspBase这个类的源代码文件

HttpJspBase 类是继承 HttpServlet 的,所以 HttpJspBase 类是一个 Servlet ,而 index_jsp 又是继承 HttpJspBase类的,所以index_jsp类也是一个Servlet,所以当浏览器访问服务器上的index.jsp页面时,其实就是在访问index_jsp这个Servlet,index_jsp这个Servlet使用_jspService这个方法处理请求。

三:Jsp中的HTML代码和Java代码如何发送到客户端

1:jsp中的代码是由 Java代码 和 HTML 代码组成的 但是两种不同的代码是如何实现他们的作用的?

在客户端发出请求时(请求的是动态代码) 但是客户端却只能看到HTML代码, Java代码是客户端看不到的

原因是: 请求的JSP页面中,所有的代码是通过了Web服务器(在Tomcat下)编译后的Servlet代码, 在jsp中编写的java代码和html代码都会被翻译到_jspService方法中去,在jsp中编写的java代码会原封不动地翻译成java代码,如<%out.print("HelloJsp");%>直接翻译成out.print("Hello Jsp");,而HTML代码则会翻译成使用out.write("<html标签>\r\n");的形式输出到浏览器。在jsp页面中编写的html排版标签都是以out.write("<html标签>\r\n");的形式输出到浏览器,浏览器拿到html代码后才能够解析执行html代码。

当执行_jspService方法处理请求时,就会执行在jsp编写的java代码了,所以Jsp页面中的java代码服务器是通过调用_jspService方法处理请求时执行的。(_jspService中的Java代码是实现动态页面的逻辑基础)

我们的开发工程中经常会使用到各种图,所谓的图就是由节点和节点之间的连接所形成的系统,数学上专门有一个分支叫图论(Graph Theroy)。利用图我们可以做很多工具,比如思维导图,流程图,状态机,组织架构图,等等。今天我要做的是用开源的HTML5工具来快速构造一个做图的工具。

工具选择

工预善其事,必先利其器。第一件事是选择一件合适的工具,开源时代,程序员还是很幸福的,选择很多。

  • flowchart.js http://adrai.github.io/flowchart.js/ , 基于SVG创建Flow Chart
  • go.js http://www.gojs.net/latest/index.html go.js 提供一整套的JS工具 ,支持各种交互式图表的创建。有免费版和收费版
  • joint.js http://www.jointjs.com/ joint.js 是另一个创建图标库的工具,也提供免费版和商业版
  • jsPlumb http://www.jsplumb.org/ jsPlumb是一套开源的流程图创建工具 ,小巧精悍,使用简单
  • d3 http://d3js.org 在html5领域,d3可谓是最好的可视化基础库,提供方面的DOM操作,非常强大。

最终,我选择了jsPlumb,因为它完全开源,使用很简单,用D3的话可能会多花很多功夫。joint.js也不错。大家可以根据自己的需要选择。

构建静态应用

下面我们一步一步的来使用jsPlumb来创建我们的流程图工具。

第一步是等待DOM和jsPlumb初始化完毕,类似document.ready()和jquery.ready(), 要使用jsPlumb, 需要把代码放在这个函数里:

jsPlumb.ready(function() {
    // ... your code goes here ...
}


创建一个jsPlumb的实例,并初始化jsPlumb的配置参数:

//Initialize JsPlumb
var color = "#E8C870";
var instance = jsPlumb.getInstance({
    // notice the 'curviness' argument to this Bezier curve.  the curves on this page are far smoother
    // than the curves on the first demo, which use the default curviness value.      
    Connector : [ "Bezier", { curviness:50 } ],
    DragOptions : { cursor: "pointer", zIndex:2000 },
    PaintStyle : { strokeStyle:color, lineWidth:2 },
    EndpointStyle : { radius:5, fillStyle:color },
    HoverPaintStyle : {strokeStyle:"#7073EB" },
    EndpointHoverStyle : {fillStyle:"#7073EB" },
    Container:"container-id"
 });


这里给给出了一些配置包括,连接线(这里配置了一个贝塞尔曲线),线的风格,连接点得风格。Container需要配置一个对应的DIV容器的id。(这里也可以使用setContainer的方法)

下面我们要创建一个节点(node),每一个节点可以用一个DIV来实现。我这里提供了一个函数来创建节点。

function addNode(parentId, nodeId, nodeLable, position) {
  var panel = d3.select("#" + parentId);
  panel.append('div').style('width','120px').style('height','50px')
    .style('position','absolute')
    .style('top',position.y).style('left',position.x)
    .style('border','2px #9DFFCA solid').attr('align','center')
    .attr('id',nodeId).classed('node',true)
    .text(nodeLable);

  return jsPlumb.getSelector('#' + nodeId)[0];
}


这里做的事情就是创建了一个DIV元素,并放在对应的容器的制定位置上,注意为了支持拖拽的功能,必须使用position:absolute 。

我使用D3来操作DOM,大家可能会更习惯JQuery,这纯属个人喜好的问题。

最后返回创建节点的实例引用,这是的selector使用了jsPlumb.getSelector()方法,它和JQuery的selector是一样的,这样用的好处是你可以使用不同的DOM操作库,例如Vanilla

下面我使用一个函数来创建端点/锚点(anchor),锚点就是节点上的连接点,用于连接不同的节点。

function addPorts(instance, node, ports, type) {
  //Assume horizental layout
  var number_of_ports = ports.length;
  var i = 0;
  var height = $(node).height();  //Note, jquery does not include border for height
  var y_offset = 1 / ( number_of_ports + 1);
  var y = 0;

  for ( ; i < number_of_ports; i++ ) {
    var anchor = [0,0,0,0];
    var paintStyle = { radius:5, fillStyle:'#FF8891' };
    var isSource = false, isTarget = false;
    if ( type === 'output' ) {
      anchor[0] = 1;
      paintStyle.fillStyle = '#D4FFD6';
      isSource = true;
    } else {
      isTarget =true;
    }

    anchor[1] = y + y_offset;
    y = anchor[1];

    instance.addEndpoint(node, {
      uuid:node.getAttribute("id") + "-" + ports[i],
      paintStyle: paintStyle,
      anchor:anchor,
      maxConnections:-1,
      isSource:isSource,
      isTarget:isTarget
    });
  }
}


instance是jsPlumb的实例

node是我们用addNode方法创建的Node实例

ports,是一个string的数组,指定端点的个数和名字

type,可能是output或者input,指定端点的种类,一个节点的输出端口可以连接另一个节点的输入端口。

这里anchor是一个四维数组,0维和1维分别是锚点在节点x轴和y轴的偏移百分比。我这里希望把端口画在节点的左右两侧,并按照端口的数量均匀分布。

最后使用instance.addEndpoint来创建端点。注意这里只要指定isSource和isTarget就可以用drag&drop的方式来连接端点,非常方便。

下面一步我们提供一个函数来连接端点:

function connectPorts(instance, node1, port1, node2 , port2) {
  // declare some common values:
  var color = "gray";
  var arrowCommon = { foldback:0.8, fillStyle:color, width:5 },
  // use three-arg spec to create two different arrows with the common values:
  overlays = [
    [ "Arrow", { location:0.8 }, arrowCommon ],
    [ "Arrow", { location:0.2, direction:-1 }, arrowCommon ]
  ];

  var uuid_source = node1.getAttribute("id") + "-" + port1;
  var uuid_target = node2.getAttribute("id") + "-" + port2;

  instance.connect({uuids:[uuid_source, uuid_target]});
}


node1和node2是源节点和目标节点的引用,port1和port2是源端口和目标端口的名字。

使用instance.connect方法来创建连接。 overlays用来添加连接线的箭头效果或者其他风格,我这里没有使用,因为觉得都不是很好看。大家如果要用,只要把overlays加入到instance.connect的方法参数就可以了。

调用以上方法来创建节点,端点和连接线。

var node1 = addNode('container-id','node1', 'node1', {x:'80px',y:'20px'});
var node2 = addNode('container-id','node2', 'node2', {x:'280px',y:'20px'});

addPorts(instance, node1, ['out1','out2'],'output');
addPorts(instance, node2, ['in','in1','in2'],'input');

connectPorts(instance, node1, 'out2', node2, 'in');


这里我们创建了两个节点,第一个节点有两个输出端口,第二个节点有三个输入端口,然后把第一个节点的out2端口连接到第二个端点的in端口。效果如下:

最后我们给节点增加drag&drop的功能,这样我们就可以拖动这些节点来改变图的布局了。

instance.draggable($('.node'));


这里似乎依赖于JQuery-UI,我还不是很清楚。

交互式创建节点

我们已经初步具有了创建图的功能,可是节点的创建必须通过程序,我们希望用交互的方式来创建节点。

通常我们希望有一个tree view的控件,让后通过拖拽来创建对应类型的节点。这里我使用了这个开源的tree view,基于bootstrap https://github.com/jonmiles/bootstrap-treeview

我们先创建一个tree view:

function getTreeData() {
  var tree = [
    {
      text: "Nodes",
      nodes: [
        {
          text: "Node1",
        },
        {
          text: "Node2"
        }
      ]
    }
  ]; 

  return tree;
}
//Initialize Control Tree View
$('#control-panel').treeview({data: getTreeData()});


树上有两个节点:

然后我实现从树上拖拽对应的节点,到流程图上的逻辑。

//Handle drag and drop
$('.list-group-item').attr('draggable','true').on('dragstart', function(ev){
  //ev.dataTransfer.setData("text", ev.target.id);
  ev.originalEvent.dataTransfer.setData('text',ev.target.textContent);
  console.log('drag start');
});

$('#container-id').on('drop', function(ev){
  //avoid event conlict for jsPlumb
  if (ev.target.className.indexOf('_jsPlumb') >= 0 ) {
    return;
  }

  ev.preventDefault();
  var mx = '' + ev.originalEvent.offsetX + 'px';
  var my = '' + ev.originalEvent.offsetY + 'px';

  console.log('on drop : ' + ev.originalEvent.dataTransfer.getData('text'));
  var uid = new Date().getTime();
  var node = addNode('flow-panel','node' + uid, 'node', {x:mx,y:my});
  addPorts(instance, node, ['out'],'output');
  addPorts(instance, node, ['in1','in2'],'input');
  instance.draggable($(node));
}).on('dragover', function(ev){
  ev.preventDefault();
  console.log('on drag over');
});


这里要注意的是要避免和jsPlumb拖拽端点的逻辑冲突,当检测到target是jsPlumb对象是需要直接从drop方法中退出以执行对应的jsPlumb的drop逻辑。

好了,一个绘制流程图的软件工具初步完工。

我把代码放在oschina的代码托管服务上了, 大家有兴趣可以去试试。