JSP学习
1.项目格式:
IDEA中使用archetypeweb的构建就可以生成的,但是在Apple MAC上貌似不能用。IDEA中手动穿件标准的mvn项目,因为有web-app目录,IDEA会提示是否转成WEB项目选是。这里介绍一下WEB项目的目录结构
src/main/java: 放一些servlet之类的java文件
src/main/web-app/
/jsp、/js、/img
/WEB-INF/web.xml
这里的Web.xml是部署文件,指定一些servlet、listener之类的配置。Servlet例子。访问http://domain/webroot/result.do的地址,get将访问servlet的GET方法。如果在Form 中 result.do的 POST时候将自动定位到POST方法。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>processServlet</servlet-name> <servlet-class>com.mvnbook.account.web.servlet.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>processServlet</servlet-name> <url-pattern>/result.do</url-pattern> </servlet-mapping> </web-app>
2. 相对路径。
<form url='result.do'></form>
标签中url是submit之后的提交地址,相对于当前Html的路径。 如: 当前Html的路径是 web-app/html/test.html那么提交后的相对地址就是 http://domain/html/test.do 这种情况下去匹配Web.xm中的 servlet是匹配不上的, 因为上述url-pattern是相对于根的。 所以只能是 account-web/result.do这例 account-web是项目的根目录
3. HttpServletRequest和HttpServletResponse对象
关于Request: request 对象的用于获取前端页面的参数 request.getParameter('size'). 也可以获取多个参数request.getParameters('size')如复选框。
request还可以用来转发, HttpRequestDispature dispature = request.getRequestDispature('/jsp文件的路径'); dispature.forward(requst,response);
关于response: Response 对象用来获取输出流的同时可以设置一些输出格式如 response.setContentType('img/jpeg'); 同时还可以往输出流中塞一些非Html的内容。同时还可以往Response中添加一些header字段、cookie值、甚至Redirect到的其他地址(这里 redirect是返回302让客户端做跳转)
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //设置输出格式 resp.setContentType("image/jpeg"); //获取输出流 ServletOutputStream out = resp.getOutputStream(); // 读取资源文件 ServletContext sc = getServletContext(); InputStream is = sc.getResourceAsStream("dowload.jpg"); // 向输出流中塞数据 int read =0; byte[] result = new byte[1024]; while ((read=is.read())!=-1){ out.write(result,0,read); } //输出 out.flush(); out.close(); }
4. ServletConfig, ServletContext
ServletConfig用户获取设置在某个serlvet中的init-parameters,方式
getServletConfig().getInitParameter('param');
getServletContext().getInitParameter('param');
其中Servlet param的设置方式, 例子分别设置init-param 和 context-param
<servlet> <servlet-name>contextParamSevlet</servlet-name> <servlet-class>com.mvnbook.account.web.servlet.ContextParameterServlet</servlet-class> <init-param> <param-name>mail</param-name> <param-value>ygshen@ctrip.com</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>contextParamSevlet</servlet-name> <url-pattern>/servletconfig.do</url-pattern> </servlet-mapping> <context-param> <param-name>sessionid</param-name> <param-value>john</param-value> </context-param>
5. ServletContextListener接口
接口的定义:实现接口的方法 ContextInitialized(ServletContextEvent event), contextDestroyed().
接口的作用: 通常servlet config parmater和servlet context parameter只能存字符串,如果想存储对象(如数据库链接对象时需要借助contextListener)
在initilaize阶段通过event获取servletContext对象并出示话对象,并存储在servletcontext中,其他的Servlet在自己的doget、dopost中可以直接拿蛋这些context中设置的对象,全剧唯一
Lister在Web。xml中的配置
<context-param> <param-name>sessionid</param-name> <param-value>john</param-value> </context-param> <listener> <listener-class>com.mvnbook.account.web.listeners.DogContextListener</listener-class> </listener>
6. JSP 的原理:
JSP文件会被Container编译成Servlet Class文件放在对应的目录下。文件的执行顺序时先
jspInit()-->service()-->destroy()
JSP中的
0. dirctive指令 <%page import='javax.servlet.ServletConfig'%>会被翻译成import语句
1.存在表达式语句: <% 表达式语句1;语句2.。。%> 那么这些代码将在Service方法中执行。
2。如果存在声明语句:会被拿到与service()方法评级的方法、语法块中执行。
<%! String abc=‘aaaa’;
public void test(){}
public void jspInit(){}
%>
3. 如果存在输出块 <% "test"%>将被翻译成 response.getPrintWriter().print("test")输出
7. JSP的隐式对象:
jsp最终是被翻译成servlet执行的,所以Servlet中获取隐式对象的方法 如getServletConfig(), getServletContext()同样适用于语法块中。那么如何设JSP的初时参数呢? 与Serlvet的不同点是<servlet-class>改成了jsp的文件路径。
<servlet> <servlet-name>jspinit</servlet-name> <jsp-file>/jsp/jspinit.jsp</jsp-file> <init-param> <param-name>mail</param-name> <param-value>ygshen@ctrip.com</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>jspinit</servlet-name> <url-pattern>/test.do</url-pattern> </servlet-mapping>
<%
ServletConfig config=getServletConfig().getInitParam('mail');
%>
JSP对ServletContext、Request、Session、Page的支持和Servlet的支持对比
Servlet隐式对象 | JSP中的隐式对象 | |
ServletContext | getServletContext().setAttribute() |
application.setAttribute() application.getAttribute() |
Session | request.getSession().setAttribute() |
session.setAttribute() session.getAttribute() |
request | request | request |
page | N/A |
pageContext.getServletContext().setAttribute()
用来设置和获取Application级别的 变量
pageContext.getSession().setAttribute()
用来设置和获取Session级别的 变量
pageContext.getReqeust().setAttribute() (String)pageContext.getAttribute("servlet",PageContext.REQUEST_SCOPE); 用来设置和获取REQUEST级别的 变量 |
8. JSP中的Script/EL/Scriptless:
上面介绍了在JSP中写JAVA代码的方式 <% %> 但是对于UI工程师写JAVA明显是不现实的,所以一种叫做Scriptless的标签语言诞生了。
举例:Servlet中在Request中保存的对象 带到JSP中取
Servlet Method:
doPost(request,response){
request.setAttribute("name","123");
request.setAttribute("person",new Person("ygshen",34));
}
JSP Page:
如果使用JAVA Script的话:
<% String name=request.getAttribute("name")%> <%= name%>
<% Person person=(Person)request.getAttribute("person")%> <%= person.name%>
如果使用Scritpless的话
<jsp:useBean id="person" class="com.mvnbook.account.beans.Employee" scope="request"></jsp:useBean>
User First Name use bean: <jsp:getProperty name="person" property="firstName"></jsp:getProperty>
注:这里有几个名词
Script - 即在JSP中写的JAVA代码
ScriptLess: 即标签格式的HTML代码. 主要为了解决在JSP中书写JAVA的问题
EL- Expression Language 如${person.name}
9: <jsp:useBean></jsp:useBean> 标签的使用场景
a: 从Servlet跳转到JSP的时候。 Servlet中设置一些对象类型的Attribute 在JSP中可以使用usebean的方式获取设置的对象 以及输出对象的属性
<jsp:useBean id="idsetintheattribute" type="superclassorinterfaces" class="concreateclassname"></jsp:useBean>
输出 <jsp:getProperty name="idsettedintheattribute" property="propertyname">
b: 也可用于jsp到jsp 之间。比如在jsp1中通过form设值 在jsp2中可以用 usebean的方式接受对象
JSP1 文件负责对象属性的赋值:
// JSP1中通过Form的方式设置对象的属性。 // 这里的input标签的name属性至关重要,它与 jsp2中的usebean属性的param名称相同遍可以直接传旨 <%-- Created by IntelliJ IDEA. User: ygshen Date: 17/2/13 Time: 下午11:17 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title></title> </head> <body> <form action="jsp/person-get.jsp" method="post"> User Name: <input type="text" name="name" /> <br> Password: <input type="password" name="password" /> <input type="submit" value="submit"> </form> </body> </html>
JSP2负责对象的初始化 即值的接受
<%-- Created by IntelliJ IDEA. User: ygshen Date: 17/2/13 Time: 下午11:18 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title></title> </head> <body> <jsp:useBean id="person" type="com.mvnbook.account.beans.Person" class="com.mvnbook.account.beans.Employee"> <jsp:setProperty name="person" property="lastName" param="password"></jsp:setProperty> <jsp:setProperty name="person" property="firstName" param="name"></jsp:setProperty> </jsp:useBean> User Name: <jsp:getProperty name="person" property="firstName"></jsp:getProperty> Password : <jsp:getProperty name="person" property="lastName"></jsp:getProperty> </body> </html>
10: EL: JSP Expression Language
如果Servlet保存在attribute的对象属性是简单的数据类型 如果string 等用Usebean的方式看上去非常简单。但是如果对象属性又是对象 那么usebean在嵌套上酒力不从心了。 这里引进了 Expression Language。 格式 ${priopertyidintheservlet.property}
在servlet中设置复杂对象属性/
注意EL默认是不生效的 要默认打开
<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
package com.mvnbook.account.web.servlet; import com.mvnbook.account.beans.Employee; import com.mvnbook.account.model.dog; import com.sun.net.httpserver.HttpServer; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by ygshen on 17/2/13. */ public class ComplicateObjectServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Employee employee = new Employee(); dog doggie = new dog(); doggie.setName("Balk"); doggie.setColor("red"); employee.setFirstName("ygshen"); employee.setDoggie(doggie); req.setAttribute("user",employee); req.getRequestDispatcher("jsp/complicated-object.jsp").forward(req,resp); } }
在JSP中读取对象
<%-- Created by IntelliJ IDEA. User: ygshen Date: 17/2/13 Time: 下午11:55 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title></title> </head> <body> ${user.firstName} has a doogie named ${user.doggie.name} and its color is ${user.doggie.color} </body> </html>
11. EL Function = EL Taglib
定义EL Function 相当于调用一个类的静态方法,如帮助类等。 定义的过程
1. java class 定义一个static 方法
2. tag library xml 定义 *.tld
<?xml version="1.0" encoding="ISO-8859-1"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.0</tlib-version> <short-name>myshortname</short-name> <uri>http://crip.com</uri>
这里name是方法的别名,可以在后续jsp中直接调用
function class 以及signature用于寻找用户自定义类的静态方法 <function> <name>rollDice</name> <function-class>com.ygshen.jsp.el.DiceRoller</function-class> <function-signature>int rollDice()</function-signature> </function> <!-- Invoke 'Generate' action to add tags or functions --> </taglib>
3. jsp中引用<%@ taglib prefix="jsp中用的前置应用标签(mine)" uri="http://ctrip.com" />。 那么这里就可以在jsp中使用该标签引用类中的静态方法了
${mine:rollDice()}
12。 JSTL:JSP Standard Tag Library
注意点:
需要引进第三方库
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
解决的问题:替代在JSP中写JAVA代码的麻烦。
核心库中的标签
<c:out value="${person.name}"></c:out>
<c:forEach items="${person.family.entrySet()}" item=${family}></c:forEach>
实例:在Servlet中设置request scope的attribute 在JSP中使用Java Script和JSTL的方式展示属性
public class HomeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HashMap<String,String> family = new HashMap<String, String>(); family.put("father","John"); family.put("mother","Kelly"); family.put("brother","Done"); Dog mydog = new Dog("旺财",1); Person p = new Person("ygshen",10, mydog,family); req.setAttribute("person",p); req.getRequestDispatcher("index.jsp").forward(req, resp); } }
<%@ page import="java.util.HashMap" %> <%@ page import="com.ygshen.jsp.modal.Person" %> <%@ page import="java.util.Map" %> <%@ page import="java.util.Iterator" %> <%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="mine" uri="http://crip.com" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title></title> </head> <body> <% Person p = (Person)request.getAttribute("person"); HashMap<String,String> family = p.getFamily(); Iterator iterator = family.entrySet().iterator(); %> <!--Use Script --> <table> <thead> ${person.name} </thead> <tbody> <tr> <td> Name </td> <td> ${person.name} </td> </tr> <tr> <td> family members: </td> <td> <% while (iterator.hasNext()){ Map.Entry entry = (Map.Entry)iterator.next(); %> <!---这里用EL 输出上下文中的变量--> <%=entry.getValue()%> <% } %> </td> </tr> </tbody> </table> <!---Use jstl--> <table> <thead> ${person.name} </thead> <tbody> <tr> <td> Name </td> <td> ${person.name} </td> </tr> <tr> <td> family members: </td> <td> <c:forEach items="${person.family.entrySet()}" var="family"> ${family.getValue()} </c:forEach> </td> </tr> </tbody> </table> </body> </html>