jsp
- jsp的简单使用
- 导包
<!-- jsp导包 --> <%@page import="java.util.Date" %>
- 脚本片段
<% System.out.println("HelloWorld"); out.write("你好"); %>
- 表达式
<!-- jsp表达式 在页面输出内容 --> <%="HelloWorld"%> <%=new Date()%>
- 结果
- 页面字符问题
- jsp问题:windows->preferences->jsp
- 整个项目的页面字符问题,在这个文件的最后加上这句话
- jsp运行原理
- jsp页面被翻译成一个servlet
- 该servlet继承HttpJspBase,而HttpJspBase继承自HttpServlet
- 每次请求都调用_jspService()方法
- 基本语法:
- 模板元素
<!-- jsp模板元素 :jsp页面中静态HTML内容 Html写页面结构 定义页面结构 --> <h1>你好</h1> <script type="text/javascript"> alert("你好"); </script>
- 脚本表达式
<!-- jsp表达式:在页面输出内容 在页面输出内容 注意点:表达式里面的所有内容都是被串参进 out.print(),因此不能写';'。 --> <%=new Date()%>
- 脚本片段
<!-- jsp脚本片段 在脚本片段里面编写java代码 out.print();向页面输出内容 脚本片段会原封不动传入到到java文件里的service里 脚本可以写多个,还可以拆分写多个,合起来必须是合法而且是完整的 --> <% int age=18; if(age>=18){ out.print("lbwnb");%> <h1>你好</h1> <% }else{ out.print("zclnb"); } %>
- 声明
<!-- jsp声明:声明里的代码都会写在jspservice方法之外,jspServlet类里 声明比较少用 --> <%! private String name="username"; public void test(){ System.out.println("我是test方法"); } %> <h1><%=name%></h1> <%test();%>
- 注释
<!-- jsp注释 --> <!-- 这是html注释 --> <%--这是jsp注释 --%>
- 注释比较
- jsp指令
<!-- jsp指令:<% 指令名 属性名=属性值%> page指令:定义页面如何解析 include指令:静态包含,可以包含web-inf下的页面 taglib指令:在页面引入其他标签库 -->
- page指令
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!--page属性 1.import:用来在页面导包 2.pageEncoding:指定页面使用的字符集,也是告诉jsp引擎使用指定的编码翻译 3.contentType:设置响应头,页面如何响应给浏览器 4.errorPage:指定页面发生错误去向的页面 5.isErrorPage:表示当前页面是一个错误页面,如果在错误处理页面定义了这个属性为true,则在该页面可以获取前一个页面抛出的错误 6.session:默认值是true,当前页面是否可以参与会话,是否可以使用session对象 7.isELIgnored:是否会忽略EL表达式,默认false,代表不忽略,设置为true-忽略 8.info:定义页面的信息,描述一个页面 -->
- include指令:静态包含
<!-- include指令:静态包含 可以把另外一个页面包含进来,采用的方式是将整个页面复制过来 jsp引擎不翻译和编译要引入的页面 --> <%@ include file="error.jsp"%>
- taglib指令:在页面引入标签库
- jsp标签:jsp里面内置了很多标签,每个标签哦都有不同的功能,执行一段代码,action元素
<!--<jsp:include page="">:也是在页面包含另一个页面,动态包含,page属性表示要包含的页面,要过编译和翻译这一步--> <jsp:include page="index.jsp"></jsp:include>
<!--<jsp:forword page=""/> 里面可以加参数,但如果不加参数则不能留空格,参数可以在转发到的页面提取出来 --> <jsp:forward page="index.jsp"> <jsp:param value="leifengyang" name="xingming"/> </jsp:forward> <jsp:forward page="index.jsp"></jsp:forward>
- jsp九大隐含对象
隐含对象:是我们在页面中可以直接使用的对象
五大常规对象: Throwable exception=null; 代表捕获异常对象 ServletConfig config; 代表servlet配置信息 servlet->jsp页面对应的servlet config->jsp页面对应的servlet的配置信息 config.getServletName(); JspWriter out = null; 代表可以在页面输出数据的out对象 out.write(); Object page = this; 代表当前的jsp 还不如使用this对象 HttpServletResponse response 代表当前响应的对象 response.getWrite();
无论在哪个位置response.getWrite().write();的内容总是在out.write();的前面显示。刷新清空缓存即可恢复页面中原先的顺序。
四大域对象,用来在其他资源共享数据 PageContext pageContext=null; HttpSession session = null; ServletContext application; HttpServletRequest request;
- PageContext pageContext=null;
- 获取其他隐含对象 pageContext.getXXX();
- 作为域对象共享数据,只能在当前页面共享数据,离开页面就无法共享
String key,Object value
通过调用域对象.setAttribute(key,value),给相应的域中设置内容
域对象.getAttribute(key) 获取域中的内容
- HttpServletRequest request; 代表封装当次请求详细信息的对象
- 在同一个请求对象中共享数据,只要是同一次请求,就可以共享数据
- 如果在页面中是使用a标签跳转,则在新页面中无法获取属性,jsp:forword则可以获取属性。原因:forword是请求转发,仍是同一个请求。
- HttpSession session = null; 代表会话对象
- 同义词会话共享数据,浏览器打开-》开始会话 浏览器关闭-》结束会话,会话就是和web应用沟通,所以不同web应用就是不同会话
- ServletContext application; 代表整个web应用
- application,只要在同一个web应用中都可以共享数据,web应用只要不卸载就能应用
Scope.jsp <% //给pageContext域中设置内容 pageContext.setAttribute("pageUser","pageName"); //给request域中设置内容 request.setAttribute("reqUser", "reqName"); //给session域中设置内容 session.setAttribute("sessUser","sessName"); //给application域设置内容 application.setAttribute("appUser", "appName"); %> <%=pageContext.getAttribute("pageUser")%> <%=request.getAttribute("reqUser")%> <%=session.getAttribute("sessUser")%> <%=application.getAttribute("appUser")%> <!-- <jsp:forward page="Scope2.jsp"></jsp:forward> --> <a href="Scope2.jsp">scope2</a>
Scope2.jsp pageContext:<%=pageContext.getAttribute("pageUser")%></br> request:<%=request.getAttribute("reqUser")%></br> session:<%=session.getAttribute("sessUser")%></br> application:<%=application.getAttribute("appUser")%></br>
- 将html页面改为jsp页面
jsp页面html就差一个page指令头
相关链接也必须改
引入页面,将相关的菜单抽取出来并引入,用静态包含或者动态包含都可以
在页面上相对路径不靠谱,需要使用绝对路径,由于页面相对路径基本都写好了,所以我们可以使用base标签给所有相对路径一个基准路径,所有页面要引入css文件,还要引入jquery文件
<!-- 所有页面引入的资源 base标签的链接需要时动态获取的,而不是指定的 http://localhost:8080/BookStore_02/ 协议://主机名:端口号/项目名 --> 协议:<%=request.getScheme()%> 主机名:<%=request.getServerName()%> 端口号:<%=request.getServerPort()%> 项目名:<%=request.getContextPath()%>
- 登录,注册,如果发生错误
- 用户输入用户名密码
- 发送登录请求
- 登录servlet来处理请求-》查用户
-成功-》重定向到页面
-失败-》转发到登录页面
- 又会在浏览器上显示登录页面,想要在登录页面动态获取错误信息,在转发之前,设置一个错误消息提示,放在域中,jsp就可以在域中取数据了
- base标签:为了让页面上的其他相对路径不受当前资源影响,受base指定的路径影响
- 优化servlet的逻辑
- 一个请求对应了一个servlet
- 和用户相关的请求——》UserServlet
- 和图书相关的请求——》BookServlet
- 在需要提交数据的表单action属性中再加上?method=判断的类型,然后在UserServlet获取method的属性,对比类型,根据不同的类型进行不同的处理,但如果是使用get请求,则需要在表单中增加一个text的元素,将method的值放在里面,并将属性设置为hidden
- 为了不陷入层层的if判断,我们可以利用反射来做这个事情
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //处理用户请求login --UserServlet regist--UserServlet String method=request.getParameter("method"); try { Method method2=this.getClass().getDeclaredMethod(method, HttpServletRequest.class,HttpServletResponse.class); //把方法权限设大 method2.setAccessible(true); //invoke(对象,参数); method2.invoke(this, request,response); } catch (Exception e) { e.printStackTrace(); } } protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {} protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
- 所有的servlet都是通过反射来调用方法,可以抽取一个BaseServlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //处理用户请求login --UserServlet regist--UserServlet String method=request.getParameter("method"); try { Method method2=this.getClass().getDeclaredMethod(method, HttpServletRequest.class,HttpServletResponse.class); //把方法权限设大 method2.setAccessible(true); //invoke(对象,参数); method2.invoke(this, request,response); } catch (Exception e) { e.printStackTrace(); } }
- request域中获取数据:
-表单提交的:key-value方式提取
-url地址后面的:对于get请求,getParameter是获取?后面的数据;
对于post请求:参数是带在请求体中的。
-标签是get请求,也可以在地址后面+?+数据
- 我们使用分层架构
Servlet->Service->Dao->Bean:在系统中数据都使用对象包装
注册:第一步:来到注册Servlet,获取数据封装对象
登录:第一步:来到登录Servlet,获取数据封装对象
导入beanutils.jar包,使用举例
import java.lang.reflect.InvocationTargetException; import org.apache.commons.beanutils.BeanUtils; import com.aiguigu.bean.User; public class BeanUtilsTest { public static void main(String[] args){ //setProperty(bean, name, value); //bean代表要给哪个对象设置属性值 //name代表要设置的属性名 //value要设置的值 User user=new User(); System.out.println("设置之前:"+user); try { BeanUtils.setProperty(user,"username","zhoucanlong"); System.out.println("设置之后:"+user); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //JavaBean属性值的设置是按照getter settter方法定的 //属性的真正名字是get或者set后面的字符串
WebUtils
- 第一种方法
public static<T> T param2bean(HttpServletRequest request,T t){ //1.获取所有声明的属性 Field[] fields=t.getClass().getDeclaredFields(); //2.每个属性都有name值,属性名 for(Field field:fields){ //获取属性名 String name=field.getName(); //获取属性值 String value=request.getParameter(name); try { BeanUtils.setProperty(t, name, value); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } return t; }
- 第二种方法
public static<T> T param2bean2(HttpServletRequest request,T t){ //pupulate将map中的键值对,直接映射到javaBean中 Map map=request.getParameterMap(); BeanUtils.populate(t, map); return t; }
BeanUtils.populate(t,map):将map中的属性映射到JavaBean中
BeanUtils.setProperty(t,name,value):为JavaBean的某个属性赋值
return t;
}
* 第二种方法 ```java public static<T> T param2bean2(HttpServletRequest request,T t){ //pupulate将map中的键值对,直接映射到javaBean中 Map map=request.getParameterMap(); BeanUtils.populate(t, map); return t; }
BeanUtils.populate(t,map):将map中的属性映射到JavaBean中
BeanUtils.setProperty(t,name,value):为JavaBean的某个属性赋值