JavaWeb 知识点汇总

JavaEE

JavaEE 开发技术的简介

产生

为了满足开发多层体系结构的企业级应用的需求,Java公司的创始人Sun公司在早期的J2SE(Java 2 Platform Standard Edition)基础上,针对企业级应用的各种需求,提出了J2EE(Java 2 Plantform Enterprise Edition).

特点

定义:泛指那些为大型组织部门创建的应用程序。注:并不是特指为企业开发的应用软件。

企业级应用程序一般具有以下特点:

1)分布式:通过局域网运行在一个组织内部,或通过Internet连接分布在世界各地的部门或用户。

2)高速反应:不断地改变业务规则来适应社会信息的高速变化。

3)安全性:不但要实现应用系统的正常操作和运转,还必须保证系统运行的安全可靠。

4)可扩展性:充分考虑用户群体膨胀给应用带来的性能上的扩展需求。

5)集成化:对老的系统进行集成。

Java的体系结构

在这里插入图片描述

Servlet

基础

  • 什么是servlet

    Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的,一般情况下,人们将Servlet理解为后者。

    Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议Web服务器

  • 主要内容

在这里插å¥å›¾ç‰‡æè¿°

  • 请求响应

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-go7SrAEb-1608173515354)(C:\Users\le\AppData\Roaming\Typora\typora-user-images\image-20201211152606659.png)]

响应的完整流程

  1. 客户端发送请求,tomcat通过请求头获知浏览器访问的是哪个主机
  2. 再通过请求⾏获取访问的是哪个⼀个web应⽤
  3. 再通过请求⾏中的请求路径获知访问的是哪个资源
  4. 通过获取的资源路径在配置中匹配到真实的路径,
  5. 服务器会创建servlet对象,(如果是第⼀次访问时,创建servlet实例,并调⽤init⽅法进⾏初始化
    操作)
  6. 调⽤service(request, response)⽅法来处理请求和响应的操作
  7. 调⽤service完毕后返回服务器 由服务器讲response缓冲区的数据取出,以http响应的格式发送给
    浏览器
  • 生命周期

    其中,init( ),service( ),destroy( )是Servlet生命周期的方法。代表了Servlet从“出生”到“工作”再到“死亡 ”的过程。Servlet容器(例如TomCat)会根据下面的规则来调用这三个方法:

    1. init( ),当Servlet第一次被请求时,Servlet容器就会开始调用这个方法来初始化一个Servlet对象出来,但是这个方法在后续请求中不会在被Servlet容器调用,就像人只能“出生”一次一样。我们可以利用init( )方法来执行相应的初始化工作。调用这个方法时,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化。

    2. service( )方法,每当请求Servlet时,Servlet容器就会调用这个方法。就像人一样,需要不停的接受老板的指令并且“工作”。第一次请求时,Servlet容器会先调用init( )方法初始化一个Servlet对象出来,然后会调用它的service( )方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。

    3. destory,当要销毁Servlet时,Servlet容器就会调用这个方法,就如人一样,到时期了就得死亡。在卸载应用程序或者关闭Servlet容器时,就会发生这种情况,一般在这个方法中会写一些清除代码。

配置

  • web.xml 中Servlet的注解
<servlet>
         <!-- servlet的内部名称,自定义 -->
        <servlet-name>DemoAction</servlet-name>
        <!-- servlet的类全名:包名+类名 -->
        <servlet-class>com.uplooking.controller.DemoAction</servlet-class>
        <load-on-startup>1</load-on-startup>
</servlet>
<!-- servlet的映射配置 -->
<servlet-mapping>
        <!-- servlet的内部名称,一定要和上面的内部名称保持一致 -->
        <servlet-name>DemoAction</servlet-name>
        <!-- servlet的映射路径(访问serclet的名称 -->
        <url-pattern>/DemoAction</url-pattern>
</servlet-mapping>
  1. 首先,从浏览器中发送请求,是从当前工程中的路径与servlet-mapping标签中的url-pattern的标签值进行匹配。
  2. 根据这个映射值,找到servlet-mapping标签中的servlet-name的值与servlet标签中的servlet-name进行匹配
  3. 匹配到以后,找到servlet标签中的servlet-class标签中对应servlet类的src文件夹下的全路径。
  4. 从而调用并执行相应的servlet类。
# Init 初始化参数
1 <init-param>
2             <param-name>abc</param-name>
3             <param-value>123</param-value>
4 </init-param>
# 一个Servlet可以配置一个或多个初始化参数。

# 在应用程序中,可以使用Servlet的getInitParameter(String param)来读取初始化param对应的参数;若要读取所有的初始化参数名称,则可以使用getInitParameterNames()方法获得所有的参数名称,类型为枚举(Enumeration)。
//获取所有初始化参数
 Enumeration<String> strs=this.getInitParameterNames();
 while(strs.hasMoreElements()) {
         str=strs.nextElement();
        System.out.println(str+"     "+this.getInitParameter(str));
         //-->abc 123
        //-->aaa 111
    }
     
#  这些初始化参数也可以由ServletConfig对象获取,Servlet提供getServletConfig()方法提供ServletConfig对象。由ServletConfig获取初始化参数和由Servlet获取初始化参数的方法是一样的。  
//两种调用getInitParameter的情况,视情况而定
//this是指ServletConfig的对象config
String str=this.getInitParameter("abc");  //第一种

String str=config.getInitParameter("abc");//第二种

上下文参数

1 <context-param>
2          <param-name>root</param-name>
3          <param-value>123</param-value>
4  </context-param>

获取context-param需要使用ServletContext对象。ServletContext对象可以通过在Servlet中的getServletConfig().getServletContext()方法获得。得到ServletContext对象后,使用getInitParameter(String param)方法获取名为param的参数值,通过getInitParameterNames()获取所有的context-param名称。

ServletContext context=this.getServletContext();
String root=context.getInitParameter("root");
System.out.println("root="+root);
  • 注解访问

只需在对应的servlet类中添加servlet注解即可,从浏览器发送请求时,是用当前“工程”下的路径,会去对应servlet类的上面寻找是否存在对应url名称的@webServlet注解,存在的话,调用并执行对应的servlet类。

1 @WebServlet("/DemoAction")
2 public class DemoAction  extends HttpServlet{
3 }

对请求的处理方式

HttpServlet抽象类
  • HttpServlet抽象类是继承于GenericServlet抽象类而来的。使用HttpServlet抽象类时,还需要借助分别代表Servlet请求和Servlet响应的HttpServletRequest和HttpServletResponse对象。

  • HttpServletRequest接口扩展于javax.servlet.ServletRequest接口,HttpServletResponse接口扩展于javax.servlet.servletResponse接口。

  • 接下来我们再看看service方法是如何工作的,我们会发现在service方法中还是没有任何的服务逻辑,但是却在解析HttpServletRequest中的方法参数,并调用以下方法之一:doGet,doPost,doHead,doPut,doTrace,doOptions和doDelete。这7种方法中,每一种方法都表示一个Http方法。doGet和doPost是最常用的。所以,如果我们需要实现具体的服务逻辑,不再需要覆盖service方法了,只需要覆盖doGet或者doPost就好了。

HttpServletRequest接口

HttpServletRequest 表示Http环境的Servlet请求。它扩展于javax.servlet.ServletRequest接口,并添加了几个方法。

String getContextPath();//返回请求上下文的请求URI部分

Cookie[] getCookies();//返回一个cookie对象数组

String getHeader(String var1);//返回指定HTTP标题的值

String getMethod();//返回生成这个请求HTTP的方法名称

String getQueryString();//返回请求URL中的查询字符串

HttpSession getSession();//返回与这个请求相关的会话对象
HttpServletResponse接口

在Service API中,定义了一个HttpServletResponse接口,它继承自ServletResponse接口,专门用来封装HTTP响应消息。 由于HTTP请求消息分为状态行,响应消息头,响应消息体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码,响应消息头,响应消息体的方法

通过Response设置响应
void addCookie(Cookie var1);//给这个响应添加一个cookie

void addHeader(String var1, String var2);//给这个请求添加一个响应头

void sendRedirect(String var1) throws IOException;//发送一条响应码,讲浏览器跳转到指定的位置

void setStatus(int var1);//设置响应行的状态码
Response的乱码问题
  • response.setCharacterEncoding(“utf-8”);
  • response.setHeader(“Content-type”,"text/html;charset=utf-8);

  • response.setContentType(“text/html;charset=utf-8”);

会话管理

Session介绍

服务器会为每个浏览器 创建单独Session对象,Session对象用来保存与对应浏览器相关会话数据

Session原理

1、当客户端访问服务器,第一次 request.getSession() API得到执行,随机创建Session对象,为对象创建唯一编号 id
2、服务器会将创建Session 的编号 id 以Cookie形式 发送给客户端
3、客户端接收 session的编号,保存起来(会话级别、持久级别)
4、客户端下次访问服务器,因为cookie中含有session的id ,会自动携带session的id
5、服务器端,从cookie中获得session的id,并且request.getSession()时,根据session的id查找到服务器端对应Session对象

Session的配置

服务器有着N个session,浏览器关闭后服务器端的session不会立马删除,只是失去关联,而是等30分钟后清除(很占内存资源,一个项目里面不要过多地使用session);可以在web.xml文件中设置超时时间

<session-config>
	<session-timeout>30<.session-timeout> # 设置过期时间
</session-config>
        
        
# java 实现session
HttpSession session = request.getSession();
        //将数据存储到session中
        session.setAttribute("data", "孤傲苍狼");
        //获取session的Id
        String sessionId = session.getId();
        //判断session是不是新创建的
        if (session.isNew()) {
            response.getWriter().print("session创建成功,session的id是:"+sessionId);
        }else {
            response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);
        }

Session和Cookie的区别
  • session是服务端存储,cookie是浏览器端存储
  • Cookie是把用户的数据写给用户的浏览器。
  • Session技术把用户的数据写到用户独占的session中。
  • Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。

重定向和请求转发

重定向

response.sendRedirect()

是一种客户端行文,从本质上讲等同于两次请求,前一次请求对象不会保存,地址栏的URL地址会改变。

请求转发

request.getRequestDispatcher().forward(request,response)

是一种服务器的行为,客户端只有一次请求,服务器端转发后会将请求对象保存,地址栏中的URL地址不会改变,得到响应后服务器端再将响应发给客户端;

两者的区别
  1. 重定向访问服务器两次,转发只访问服务器一次
  2. 重定向可以看见目标页面的url,转发只能看见第一访问的页面的url,以后的工作都是服务器来做的
  3. 重定向跳转后必须加上return,也不然页面跳转了,但是还会执行跳转后的语句,转发是执行了跳转页面,下面的代码就不会在执行了
  4. 在request级别使用信息共享,使用重定向必然出错,数据会丢失
  5. 重定向可以访问自己web应用资源以外的资源

补充

JavaWeb的四大作用域为:PageContextServletRequestHttpSessionServletContext

PageContext

生命周期

当对JSP的请求时开始,当响应结束时销毁。

作用范围

整个JSP页面,是四大作用域中最小的一个,即超过这个页面就不能够使用了。(所以使用pageContext对象向其它页面传递参数是不可能的.)

作用

(1)获取其它八大隐式对象,可以认为是一个入口对象。

(2)获取其所有域中的数据

pageContext 操作所有域中属性的方法

public java.lang.Object getAttribute(java.lang.String name,intscope)

public void setAttribute(java.lang.String name, java.lang.Objectvalue,int scope)

public void removeAttribute(java.lang.String name,int scope)

pageContext 中代表域的常量

PageContext.APPLICATION_SCOPE

PageContext.SESSION_SCOPE

PageContext.REQUEST_SCOPE

PageContext.PAGE_SCOPE

findAttribute方法,在四大域中搜寻属性,搜寻的顺序是page域、request域、session域、application域,

从小域到大域开始搜索,如果搜索到就直接获取该值,如果所有域中都找不到,返回一个null(与el表达式不同,此处返回null,对网页是不友好的)

(3) 跳转到其他资源,其身上提供了forward和include方法,简化重定向和转发的操作。

ServletRequest

生命周期

在service 方法调用前由服务器创建,传入service方法。整个请求结束,request生命结束。

作用范围

整个请求链(请求转发也存在)

作用

在整个请求链中共享数据。最常用到:在Servlet 中处理好的数据交给Jsp显示,此时参数就可以放置在Request域中带过去。

HttpSession

生命周期

在第一次调用 request.getSession() 方法时,服务器会检查是否已经有对应的session,如果没有就在内存 中创建一个session并返回。

当一段时间内session没有被使用(默认为30分钟),则服务器会销毁该session。

如果服务器非正常关闭(强行关闭),没有到期的session也会跟着销毁。

如果调用session提供的invalidate(),可以立即销毁session。

注意: 服务器正常关闭,再启动,Session对象会进行钝化和活化操作。同时如果服务器钝化的时间在session 默认销毁时间之内,则活化后session还是存在的。否则Session不存在。如果JavaBean 数据在session钝化时,没有实现Serializable 则当Session活化时,会消失。

作用范围

一次会话。

作用

  • 可以防止表单二次提交
ServletContext

生命周期

当Web应用被加载进容器时创建代表整个web应用的ServletContext对象,当服务器关闭或Web应用被移除时,ServletContext对象跟着销毁。

作用范围

整个Web应用。

作用

  1. 在不同Servlet 之间转发
  2. 读取资源文件。

JSP

什么是JSP?

基于java平台的动态web页面技术,利用这种技术,可以实现html语言和Java服务端语法元素的融合,能够是页面的表示逻辑与服务端运行的代码分离,便于程序的维护。


为什么要使用JSP?

对web开发者来说,引入jsp,可以把动态网页的表示逻辑从臃肿的Servlet代码中分离出来,即实现web应有的前后端分离,有利于程序的维护


JSP三大指令
Page

<%@page language=”java” info=”xxx”…%>

  • pageEncoding和contentType:
    pageEncoding:它指定当前jsp页面的编码,只要不说谎,就不会有乱码!在服务器要把jsp编译成.java时需要使用pageEncoding!
    contentType:它表示添加一个响应头:Content-Type!等同与response.setContentType(“text/html;charset=utf-8”);
    如果两个属性只提供一个,那么另一个的默认值为设置那一个。
    如果两个属性都没有设置,那么默认为iso
  • import:导包!可以出现多次
  • errorPage和isErrorPage
    errorPage:当前页面如果抛出异常,那么要转发到哪一个页面,由errorPage来指定
    isErrorPage:它指定当前页面是否为处理错误的页面!当该属性为true时,这个页面会设置状态码为500!而且这个页面可以使用9大内置对象中的exception
<error-page>有两种使用方式:
<error-code><location>子元素;
<exception-type><location>子元素;
其中<error-code>是指定响应码;<location>指定转发的页面;<exception-type>是指定抛出的异常类型。

eg:

 <error-page>
    <error-code>404</error-code>
    <location>/error/errorPage.jsp</location>
 </error-page>
 <error-page>
 	<exception-type>java.lang.RuntimeException</exception-type>
    <location>/index.jsp</location>
 </error-page>
  • autoFlush和buffer

    autoFlush:指定jsp的输出流缓冲区满时,是否自动刷新!默认为true,如果为false,那么在缓冲区满时抛出异常!
    buffer:指定缓冲区大小,默认为8kb,通常不需要修改!

  • isELIgnored:是否忽略el表达式,默认值为false,不忽略,即支持!

  • (以下了解即可):
    language:指定当前jsp编译后的语言类型,默认值为java。
    info:信息!
    isThreadSafe:当前的jsp是否支持并发访问!
    session:当前页面是否支持session,如果为false,那么当前页面就没有session这个内置对象!
    extends:让jsp生成的servlet去继承该属性指定的类!

include -> 静态包含
  • 与RequestDispatcher的include()方法的功能相似!
  • <<%@include%> >它是在jsp编译成java文件时完成的!他们共同生成一个java(就是一个servlet)文件,然后再生成一个class!
  • RequestDispatcher的include()是一个方法,包含和被包含的是两个servlet,即两个.class!他们只是把响应的内容在运行时合并了!
  • 作用:把页面分解了,使用包含的方式组合在一起,这样一个页面中不变的部分,就是一个独立jsp,而我们只需要处理变化的页面。
taglib -> 导入标签库

两个属性

prefix:指定标签库在本页面中的前缀!由我们自己来起名称!
uri: 指定标签库的位置!
<%@taglib prefix=”s” uri=”/struts-tags”%> 前缀的用法 ``

九大内置对象
  • 在jsp中无需声明即可直接使用的9个对象

    • out(JspWriter):等同与response.getWriter(),用来向客户端发送文本数据;
    • config(ServletConfig):对应“真身”中的ServletConfig;
    • page(当前JSP的真身类型):当前JSP页面的“this”,即当前对象,引用为Object类型;
    • pageContext(PageContext):页面上下文对象,它是最后一个没讲的域对象;
    • exception(Throwable):只有在错误页面中可以使用这个对象;
    • request(HttpServletRequest):即HttpServletRequest类的对象;
    • response(HttpServletResponse):即HttpServletResponse类的对象;
    • application(ServletContext):即ServletContext类的对象;
    • session(HttpSession):即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个页面不能使用session。
  • pageContext(一个顶9个!)

    • Servlet中有三大域,而JSP中有四大域!
      ServletContext:整个应用程序
      session:整个会话(一个会话中只有一个用户)
      request:一个请求链!
      pageContext:一个jsp页面!这个域是在当前jsp页面和当前jsp页面中使用的标签之间共享数据!
      域对象
      代理其他域:pageContext.setAttribute(“xxx”, “XXX”, PageContext.SESSION_SCOPE);
      全域查找:pageContext.findAttribute(“xxx”);从小到大,依赖查找!
      获取其他8个内置对象:
JSP动作标签

动作标签是由tomcat(服务器)来解释执行!而html标签由浏览器来执行!

  • <jsp:include>
    

    例如:

    <jsp:include page="xxx"/>
    

    用来包含指定的页面。假如有两个jsp. 分别为a.jsp和b.jsp,他们分别编码成Servlet,然后在执行Servlet时才会执行包含过程。这也是include指令与include标签的区别。

    • 注意:

      <jsp:include page="<%myfile%>">
      

      这是可以的!因为include指令是在执行时才完成的包含,在执行时已经可以确定myfile这个变量的值。

    • 该标签内部使用的是RequestDispatcher#include()方法完成的包含

  • <jsp:forward>
    

    例如:

    <jsp:forward page="xxxx">  用来转发到指定页面 例如在a.jsp中存在如下内容:<jsp:forward page="b.jsp"> ,a.jsp中的内容不会显示在浏览器上,而只是显示b.jsp的内容。而且在<jsp:forward>标签下面的内容不会被执行。
    
  • <jsp:param> 
    该标签是和的子标签,用来向其他页面传递参数
    

# 示例
<jsp:include page="/b.jsp">
    <jsp:param value="zhangSan" name="username"/> 
</jsp:include>
# 在b.jsp中可以使用request.getParameter(“username”)来获取参数值。

EL表达式

什么是EL表达式

EL表达式的语法,都是用“${ }”表示的。
关于EL表达式和使用Java代码的区别:

在Servlet中:

request.setAttribute("username","zhangsan");
request.setAttribute("password","123");
// 在JSP中使用Java脚本:
用户名:<%=request.getAttribute("username")%><br />
密码:  <%=request.getAttribute("password")%>
// 使用EL表达式
用户名:${username}<br />
密码:  ${password}

EL表达式不仅能获取Servlet中存储的数据,也能简化JSP中的代码量,使程序简单易维护,另外,当域对象里面的值不存在时,使用EL表达式获取域对象里面的值返回空字符串;而使用Java脚本方式获取,返回值是null,会报空指针异常。

EL中的运算符

点运算符(.)

EL表达式中的点运算符,用于访问JSP页面中某些对象的属性,如JavaBean对象、List集合、Array数组等。

${user.username}

方括号([])

EL表达式中的方括号运算符与点运算符的功能相同,都用于访问JSP页面中某些对象的属性。当获取的属性名中包含一些特殊符号,如“_”或“-”“?”等并非数字或字母的符号,就只能使用方括号运算符来访问该属性。

${user[“user_name”]}

  • 点运算符和方括号运算符在某种情况下可以互换,如${user.username}等价于${user["username"]}
  • 方括号运算符还可以访问List集合或数组中指定索引的某个元素,如表达式${users[0]}用于访问集合或数组中第一个元素。在这种情况下,只能使用方括号运算符,不能使用点运算符。
  • 方括号运算符和点运算符可以相互结合使用,如${users[0].username},表示访问集合或者数组中的第一个元素的username属性。
算术运算符
算数运算符说明算术表达式结果
+${1+1}2
-${1-1}0
*${1*1}1
/ (或div)${1/1}或${1 div 1}1
% (或mod)取余(取模)${1%1}或${1 mod 1}0
比较运算符

EL表达式中的比较运算符用于比较两个操作数的大小,操作数可以是各种常量、EL表达式、EL变量,所有的运算执行结果都是布尔类型。

比较运算符说明算术表达式结果
==(或eq)等于${10==2}或${10 eq 2}false
!=(或ne)不等于${10!=2}或${10 ne 2}true
<(或lt)小于${10<2}或${10 lt 2}false
>(或gt)大于${10>2}或${10 gt 2}true
<=(或le)小于等于${10<=2}或${10 le 2}false
>=(或ge)大于等于${10>=2}或${10 ge 2}true
逻辑运算符
逻辑运算符说明算术表达式结果
&&(and)逻辑与${true&&false}或${true and false}false
|| (or)逻辑或${false||true}true
!(not)逻辑非${!=true} 或${not true}false
empty运算符

EL表达式中的empty运算符用于判断某个对象是否为null或"",结果为布尔类型,其基本的语法格式如下:

${empty var}

  • var变量不存在(没有定义),结果返回true
  • var变量的值为null,结果返回true
  • var变量引用集合(Set、Map、List)类型对象,并且在集合对象中不包含任何元素时,结果返回true
条件表达式

EL表达式中条件运算符用于执行某种条件判断,类似于Java中的if-else语句,其语法格式如下:

${A?B:C}

  • var变量不存在(没有定义),结果返回true
  • var变量的值为null,结果返回true
  • var变量引用集合(Set、Map、List)类型对象,并且在集合对象中不包含任何元素时,结果返回true
”()“运算符

EL表达式中的圆括号用于改变其他运算符的优先级。

EL隐式对象

不需要new就能使用的对象,自带的对象

  • 作用域访问对象(EL隐式对象):pageScope、requestScope、sessionScope、applicationScope
  • 参数访问对象
  • JSP隐式对象
隐含对象名称描述
pageContext对应于JSP页面中的pageContext对象
pageScope代表page域中用于保存属性的Map对象
requestScope代表request域中用于保存属性的Map对象
sessionScope代表session域中用于保存属性的Map对象
applicationScope代表application域中用于保存属性的Map对象
param表示一个保存了所有请求参数的Map对象
paramValues表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是String类型数组
header表示一个保存了所有HTTP请求头字段的Map对象
headerValues表示一个保存了所有HTTP请求头字段的Map对象,返回的是String类型数组
cookie用来取得使用者的cookie值,cookie的类型是Map
initParam表示一个保存了所有Web应用初始化参数的Map对象

JavaBean

什么是JavaBean?

JavaBean是一个遵循特定写法的Java类,它通常具有如下特点:

  • 这个Java类必须具有一个无参的构造函数
  • 属性必须私有化。
  • 私有化的属性必须通过public类型的方法暴露给其它程序,并且方法的命名也必须遵守一定的命名规范。
使用JavaBean的原因

程序中往往有重复使用的段落,JavaBean就是为了能够重复使用而设计的程序段落,而且这些段落并不只服务于某一个程序,而且每个JavaBean都具有特定功能,当需要这个功能的时候就可以调用相应的JavaBean。从这个意义上来讲,JavaBean大大简化了程序的设计过程,也方便了其他程序的重复使用。

JavaBean传统应用于可视化领域,如AWT(窗口工具集)下的应用。而现在,JavaBean更多地应用于非可视化领域,同时,JavaBean在服务器端的应用也表现出强大的优势。非可视化的JavaBean可以很好地实现业务逻辑、控制逻辑和显示页面的分离,现在多用于后台处理,使得系统具有更好的健壮性和灵活性。JSP + JavaBean和JSP + JavaBean + Servlet成为当前开发Web应用的主流模式。

JavaBean的特点
  1. 易于维护、使用、编写
  2. 可实现代码的重用性
  3. 可移植性强,但只限于Java平台
  4. 便于传输,不限于本地还是网络
  5. 可以以其他部件的模式进行工作
JavaBean的属性

​  JavaBean的属性可以是任意类型,并且一个JavaBean可以有多个属性。每个属性通常都需要具有相应的setter、 getter方法,setter方法称为属性修改器,getter方法称为属性访问器。属性修改器必须以小写的set前缀开始,后跟属性名,且属性名的第一个字母要改为大写,例如,name属性的修改器名称为setName,password属性的修改器名称为setPassword。 属性访问器通常以小写的get前缀开始,后跟属性名,且属性名的第一个字母也要改为大写,例如,name属性的访问器名称为getName,password属性的访问器名称为getPassword。 一个JavaBean的某个属性也可以只有set方法或get方法,这样的属性通常也称之为只写、只读属性。

简单的JavaBean


public class SimpleBean{  
    private String name;  
    private int age;  
    public void setName(String name){  
        this.name = name;  
    }  
    public void setAge(int age){  
        this.age = age;  
    }  
    public String getName(){  
        return this.name;  
    }  
    public int getAge(){  
        return this.age;  
    }  
}
Jsp中使用JavaBean

SP技术提供了三个关于JavaBean组件的动作元素,即JSP标签,它们分别为:

  • <jsp:useBean>标签:用于在JSP页面中查找或实例化一个JavaBean组件。
  • <jsp:setProperty>标签:用于在JSP页面中设置一个JavaBean组件的属性。
  • <jsp:getProperty>标签:用于在JSP页面中获取一个JavaBean组件的属性。
 <jsp:useBean>标签用于在指定的域范围内查找指定名称的JavaBean对象,如果存在则直接返回该JavaBean对象的引用,如果不存在则实例化一个新的JavaBean对象并将它以指定的名称存储到指定的域范围中。 
  常用语法:
    <jsp:useBean id="beanName" class="package.class"                                       scope="page|request|session|application"/>
  "id"属性用于指定JavaBean实例对象的引用名称和其存储在域范围中的名称。
  "class"属性用于指定JavaBean的完整类名(即必须带有包名)。
  "scope"属性用于指定JavaBean实例对象所存储的域范围,其取值只能是page、request、session和application等四个值中的一个,其默认值是page。

<jsp:useBean>标签使用范例:

<%@ page contentType="text/html" pageEncoding="GBK"%>  
<jsp:useBean id="simple" scope="page" class="blog.csdn.joywy.SimpleBean"/>  
<html>  
<head><title>欢迎来到望星空</title></head>  
<body>  
<%  
    simple.setName("Joywy");  
    simple.setAge(23);  
%>  
<h3>姓名:<%=simple.getName()%></h3>  
<h3>年龄:<%=simple.getAge()%></h3>  
</body>  
</html> 

<jsp:setProperty>标签使用范例:

 <jsp:setProperty>标签用于设置和访问JavaBean对象的属性。 
  语法格式一:
    <jsp:setProperty name="beanName" property="propertyName" value="string字符串"/>

  语法格式二:
    <jsp:setProperty name="beanName" property="propertyName" value="<%= expression %>" />

  语法格式三:
    <jsp:setProperty name="beanName" property="propertyName" param="parameterName"/>

  语法格式四:
    <jsp:setProperty name="beanName" property= "*" />
  name属性用于指定JavaBean对象的名称。 
  property属性用于指定JavaBean实例对象的属性名。
  value属性用于指定JavaBean对象的某个属性的值,value的值可以是字符串,也可以是表达式。为字符串时,该值会自动转化为JavaBean属性相应的类型,如果value的值是一个表达式,那么该表达式的计算结果必须与所要设置的JavaBean属性的类型一致。  
  param属性用于将JavaBean实例对象的某个属性值设置为一个请求参数值,该属性值同样会自动转换成要设置的JavaBean属性的类型。

<jsp:getProperty>标签使用范例:

<jsp:getProperty property="username" name="user1"/>
# 输出user1这个javaBean的username属性值

# 等同与 
User user1 = (User)pageContext.getAttribute(“user1”); 
out.print(user1.getUsername());
EL表达式
介绍:
1、EL简介
1)语法结构
       ${expression}
2[].运算符
     EL 提供.[]两种运算符来存取数据。
     当要存取的属性名称中包含一些特殊字符,如.?等并非字母或数字的符号,就一定要使用 []。
例如:
         ${user.My-Name}应当改为${user["My-Name"] }
     如果要动态取值时,就可以用[]来做,而.无法做到动态取值。例如:
         ${sessionScope.user[data]}中data 是一个变量
3)变量
     EL存取变量数据的方法很简单,例如:${username}。它的意思是取出某一范围中名称为
username的变量。
     因为我们并没有指定哪一个范围的username,所以它会依序从Page、Request、Session、
Application范围查找。
     假如途中找到username,就直接回传,不再继续找下去,但是假如全部的范围都没有找到时,
就回传null。
     属性范围在EL中的名称
         Page         PageScope
         Request         RequestScope
         Session         SessionScope
         Application     ApplicationScope
  • EL:Expression Language,它是可以在JSP页面中直接使用的语言!
    JSP页面也可以忽略EL:<@page isELIgnored=”true”%>
    EL用来代替<%=…%>
  • EL 11个内置对象

EL可以输出的东西都在11个内置对象中!11个内置对象,其中10个是Map!pageContext不是map,它就是PageContext类型,1一个顶九个

  • ${pageScope.xxx}、
  • ${requestScope.xxx}、
  • ${sessionScope.xxx}、
  • ${applicationScope.xxx}
  • param:对应参数,它是一个Map,其中key参数名,value是参数值,适用于单值的参数。
  • paramValues:对应参数,它是一个Map,其中key参数名,value是多个参数值,适用于多值的参数。
  • header:对应请求头,它是一个Map,其中key表示头名称,value是单个头值,适用于单值请求头
  • headerValues:对应请求头,它是一个Map,其中key表示头名称,value是多个头值,适用于多值请求头
  • initParam:获取``内的参数!
  • cookie:Map类型,其中key是cookie的name,value是cookie对象。 ${cookie.username.value}
  • pageContext:它是PageContext类型!${pageContext.request.contextPath}
  • EL操作四大域的内置对象:它们是Map类型
    pageScope
    requestScope
    sessionScope
    applicationScope

示例

${pageScope.user}:输出pageContext.getAttribute("user")
${requestScope.user}:输出request.getAttribute("user");
${sessionScope.user}:输出session.getAttribute("user");
${applicationScope.user}:输出application.getAttribute("user");

# initParam
initParam取得设定web站点的环境参数(Context)
例:一般的方法String userid = (String)application.getInitParameter("userid");
     可以使用 ${initParam.userid}来取得名称为userid
# pageContext
pageContext取得其他有关用户要求或页面的详细信息。
     ${pageContext.request.queryString}         取得请求的参数字符串
     ${pageContext.request.requestURL}         取得请求的URL,但不包括请求之参数字符串
     ${pageContext.request.contextPath}         服务的web application 的名称
     ${pageContext.request.method}           取得HTTP 的方法(GET、POST)
     ${pageContext.request.protocol}         取得使用的协议(HTTP/1.1、HTTP/1.0)
     ${pageContext.request.remoteUser}         取得用户名称
     ${pageContext.request.remoteAddr }         取得用户的IP 地址
     ${pageContext.session.new}             判断session 是否为新的
     ${pageContext.session.id}               取得session 的ID
     ${pageContext.servletContext.serverInfo}   取得主机端的服务信息
EL函数

迭代标签

语法:<c:forEach items=“collection” var=“name” varStatus=“status” begin=int“ 
end=int” step=int>
      //循环体</c:forEach>
     说明:1)items:是集合,用EL表达式;
       2)var:变量名,存放items
       3)varStatus: 显示循环状态的变量
					 ①index:0开始;
                     ②count:元素位置,1开始;
                     ③first:如果是第一个元素则显示true;
                     ④last:如果是最后一个元素则显示true;
       4)begin:循环的初始值(整型)5)end: 循环结束 ;
       6)step:步长,循环间隔的数值;

选择标签

IF / CHOOSE:
<c:if test="${var.index % 2 == 0}">
*
</c:if>
判定条件一般为一个EL表达式。
<c:if>并没有提供else子句,使用的时候可能有些不便,此时我们可以通过<c:choose>
tag来达到类似的目的:
<c:choose>
<c:when test="${var.index % 2 == 0}">
*
</c:when>
<c:otherwise>
!
</c:otherwise>
</c:choose>
类似Java 中的switch 语句,<c:choose>提供了复杂判定条件下的简化处理手法。其
中<c:when>子句类似case子句,可以出现多次。上面的代码,在奇数行时输出“*”号,
而偶数行时输出“!”。

<<c:param>>标签

说明:<c:param>标签用来传递参数给一个重定向或包含页面,它有以下属性属 性 描 述 是否
必须 缺省值
name 在request参数中设置的变量名 是 无
value 在request参数中设置的变量值 否 无
例子:
<c:redirect url="login.jsp">
<c:param name="id" value="888"/>
</c:redirect>

<c:redirect>标签

说明:标签将请求重新定向到另外一个页面,它有以下属性 属性 描 述 是否必须 缺省值
url url地址 是 无
context /后跟本地web应用程序的名字 否 当前应用程序
例子:
<c:redirect /'>http://www.yourname.com/login.jsp"/>
将请求重新定向到http://www.yourname.com/login.jsp页,相当于response.setRedirect
("http://www.yourname.com/login.jsp");
JSTL
  • JSTL是apache对EL表达式的扩展

jstl标签库

  • core:核心标签库,
  • fmt:格式化标签库
  • sql:数据库标签库,过时;
  • xml:xml标签库,过时。

<<c:core>>

<c:out value=”aaa”/> 输出字符串aaa
<c:out value="${aaa}/> 输出域属性aaa,其中与${aaa}相同
<c:out value="${aaa}default=”xxx”/>如果${aaa}不存在,那么输出xxx字符串
<c:out value="${aaa}" escapeXml=true/>如果${aaa}中包含特殊字符,那么转义它。这可以防止javascript攻击

<<c:set>>

<c:set var=”a” value=”hello”/> 创建名为a,值为hello的域属性,范围:page
<c:set var=”a” value=”hello” scope=”session”/> 范围为session(page、request、session、application)

<<c:remove>>

<c:remove var=”a”/> 删除名为a的域属性
<c:remove var=”a” scope=”page”/> 删除page域中名为a的域属性

<<c:url>>

<c:url value=/AServlet”/> 输出URL:/项目名/AServlet
<c:url value=/AServlet” var=”url” scope=”page”/> 把生成的url保存到page域中,而不会输出
子标签:<c:param>,用来给url后面添加参数,例如:
    <c:url value="/index.jsp">
      <c:param name="username" value="张三"/>  <!--可以对参数进行url编码!!-->
    </c:url>
1
2
3
结果为:/day13_1/index.jsp?username=%ED%2C%3F%ED%2C%3F
1
* var:指定变量名,一旦添加了这个属性,那么url标签就不会再输出到页面,而是把生成url保存到域中。 
* scope:它与var一起使用,用来保存url。

<<c:if>>

*<c:if test=”${条件}> 当条件为true时执行标签体内容 
hello 

<<c:choose>>

<c:set var="score" value="${param.score }"/>
<c:choose>
    <c:when test="${score > 100 || score < 0}">错误的分数:${score }</c:when>[if]
    <c:when test="${score >= 90 }">A级</c:when>
    <c:when test="${score >= 80 }">B级</c:when>
    <c:when test="${score >= 70 }">C级</c:when>
    <c:when test="${score >= 60 }">D级</c:when>
    <c:otherwise>E级</c:otherwise>[else]
</c:choose>

<<c:forEcah>>

<c:forEach var="i" begin="1" end="10">
    ${i}
 </c:forEach>

属性:
* var:循环变量
* begin:设置循环变量从几开始。
* end:设置循环变量到几结束。
* step:设置步长!等同与java中的i++,或i+=2。step默认为1

遍历集合或数组方式:
<%
String[] names = {"zhangSan", "liSi", "wangWu", "zhaoLiu"};
pageContext.setAttribute("ns", names);
%>
<c:forEach var="item" items="${ns }">
    <c:out value="name: ${item }"/><br/>
</c:forEach>
    
    
遍历List
<%
    List<String> names = new ArrayList<String>();
    names.add("zhangSan");
    names.add("liSi");
    pageContext.setAttribute("ns", names);
%>
<c:forEach var="item" items="${ns }">
    <c:out value="name: ${item }"/><br/>
</c:forEach>
    
    
遍历Map
<%
    Map<String,String> stu = new LinkedHashMap<String,String>();
    stu.put("number", "N_1001");
    stu.put("name", "zhangSan");
    pageContext.setAttribute("stu", stu);
%>
<c:forEach var="item" items="${stu }">
    <c:out value="${item.key }: ${item.value }"/><br/>
</c:forEach>    
  • 循环状态

循环状态变量有如下属性:
* count:循环元素的个数
* index:循环元素的下标
* first:是否为第一个元素
* last:是否为最后一个元素
* current:当前元素

<c:forEach items="${list }" var="ele" varStatus="vs">
    ${vs.index} ${vs.count } ${vs.first } ${vs.last } ${vs.current }<br/>
</c:forEach>

JDBC

基本连接

# 加载JDBC驱动
    class.forName(com.mysql.cj.jdbc.Driver);
# 建立连接
    Connection conn = new DriverManager.getConnection("jdbc:mysql://localhost:8080/mysql?serverTimeZone=GMT&useSSL=true");
# 创建语句对象
    String sql = "select * from user";
	PreparedStatedment ps = cnn.preparedStatement(sql);
# 执行sql
    ResultSet rs = ps.excuteQuery();
###  excuteQuery() 返回的是ResultSet的对象
###  excuteUpdate() 返回的是受到影响的行数
# 关闭连接 防止浪费资源
    conn.close();
	ps.close();
	rs.close();

ResultSet

结果集类型,并发性和可持续性

基本的ResultSet

Statement st = conn.CreateStatement
ResultSet rs = Statement.excuteQuery(sqlStr);

可滚动的ResultSet类型

Statement st = conn.createStatement(int resultSetType, int resultSetConcurrency)
ResultSet rs = st.executeQuery(sqlStr)

遍历

// 获取的是list的列表
List<User> user = new ArrayList<>();
while(rs.next()){
    // 通过获取元素遍历
    User user = new User();
    user.setId(res.getInt(1));
    user.setAccount(res.getString("account"));
    user.setPassword(res.getString("password"));
    users.add(user);
}

数据库连接

传统的JDBC连接

public class JDBCUtilsDemo1{      

       static{
              /**
               *1. 加载驱动
               */
              try {
                     Class.forName("com.mysql.jdbc.Driver");    //利用反射加载驱动
              } catch (ClassNotFoundException e) {
                e.printStackTrace();     
              }
       }
       /**
        * 2.建立连接
        */
       public static Connection getConnection() {  
              try {
                     return 	DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8","root", "root");
              } catch (SQLException e) {
                      throw newRuntimeException(e);
              }
       }
       /**
        * 关闭连接
        * @param conn
        * @param prep
        * @param rs
        */
       public static void close(Connection conn,PreparedStatementprep,ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally{
                rs = null;
            }
        }
        if(prep != null){
            try {
                prep.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally{
                prep = null;
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally{
                conn = null;
            }
        }
    }
       /**
        * 测试数据库连通性
        */
       public static void main(String[] args) {
       Connection conn=JDBCUtilsDemo1.getConnection();
              System.out.println(conn);
              JDBCUtilsDemo1.close(conn,null, null);
       }

}

properties配置文件形式

driver=com.mysql.jdbc.Driver

url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8

username=root

password=root

public class JDBCUtilsDemo2{      
       private static Properties prop;
       static {
              prop = new Properties();
              try {
                     prop.load(JDBCUtilsDemo2.class.getClassLoader().getResourceAsStream(
                                   "db.properties"));
                     Class.forName(prop.getProperty("driver"));
              } catch (Exception e) {
                     throw new RuntimeException(e);
              }
       }
    
       public static Connection getConnection(Connection conn) {
              if (conn==null) {
                     try {
                            conn=DriverManager.getConnection(prop.getProperty("url"),
                             prop.getProperty("username"),prop.getProperty("password"));
                     } catch (SQLException e) {
                            throw new RuntimeException(e);
                     }
              }
                return conn;   
       }

       public static void close(Connection conn,PreparedStatementprep,ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally{
                rs = null;
            }
        }
        if(prep != null){
            try {
                prep.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally{
                prep = null;
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally{
                conn = null;
            }
        }
    }

	public static voidmain(String[] args) {
       Connection conn = null;
       conn=JDBCUtilsDemo2.getConnection(conn);
       System.out.println(conn);
       JDBCUtilsDemo2.close(conn,null, null);
	}     

}

数据源的配置 conf/context.xml

<Resource
          name = "jdbc/news"
          auth = "Container"  
          type = "javax.sql.DataSource"  
          maxActive = "100"
    	  maxIdle = "30" 
          maxWait = "10000" 
          username = "root"  # 用户
          password = "123456"  # 密码
    	  driverClassName = "com.mysql.jdbc.Driver"  # 数据库的驱动
          url = "jdbc:mysql://localhost:3306/news"/>

// dao层的调用
public interface Dao {
        
        public static DataSource geDataSource() throws DaoException{
                DataSource dataSource=null;
                try {
                        Context context=new InitialContext();
// xxx是context.xml中的resource中name的属性
                        dataSource=(DataSource)context.lookup("java:comp/env/xxx");
                } catch (NamingException ex) {
                        DaoException exp=new DaoException("context.lookup调用异常:"+ex.getMessage());
                        throw exp;
                }
                return dataSource;
        }
        public default Connection getConnection() throws DaoException{
                DataSource dataSource=Dao.geDataSource();
                Connection conn=null;
                try {
                        conn=dataSource.getConnection();
                        
                } catch (SQLException ex) {
                        DaoException exp=new DaoException("建立数据库连接失败:"+ex.getMessage());
                        throw exp;
                }
                return conn;
        }
}
// 调用
xxxDao extends Dao
xxxDaoImpl implments xxxDao
// xxxDaoImpl中的代码
public boolean addManager(Manager manager) throws DaoException {
                String sql="insert into manager values(?,?,?,?,?,?)";
                Connection conn=this.getConnection();
                boolean res=false;
                try {
                     PreparedStatement   psmt = conn.prepareStatement(sql);
                     psmt.setString(1, manager.getUsername());
                     psmt.setString(2, manager.getUserpwd());
                     psmt.setString(3,manager.getUsername());
                     LocalDate dt=LocalDate.now();
                     Date dt1=Date.valueOf(dt);
                     psmt.setDate(4, dt1);
                     psmt.setBoolean(5, manager.getIspass());
                     psmt.setInt(6, manager.getRole());
                     psmt.execute();
                     res = psmt.getUpdateCount()>0;             
                     conn.close();
                } catch (SQLException ex) {
                        throw new DaoException(ex.getMessage());
                }
                return res;
        }

JSTL

使用
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
通用目的标签
<c:out>标签:输出作用域变量
<c:set>标签:定义作用域变量
<c:remove>标签:删除作用域变量
<c:catch>标签:
条件控制标签
<c:if>标签
<c:choose>标签
循环控制标签
<c:forEach>标签
### 示例
    <c:forEach var="book" items="${books}" varStatus="status">
                <tr>
                    <td>${book.id}</td>
                    <td>${book.title}</td>
                    <td>${book.author}</td>
                    <td>${book.publishTime}</td>
                </tr>
            </c:forEach>

JPA

什么是JPA

Java Persistence API:用于对象持久化的 API

Java EE 5.0 平台标准的 ORM 规范,使得应用程序以统一的方式访问持久层

JPA和Hibernate的关系

JPA 是 hibernate 的一个抽象(就像 JDBC 和 JDBC 驱动的关系):

  • JPA 是规范:JPA 本质上就是一种 ORM 规范,不是ORM 框架 —— 因为 JPA 并未提供 ORM 实现,它只是制订了一些规范,提供了一些编程的 API 接口,但具体实现则由 ORM 厂商提供实现
  • Hibernate 是实现:Hibernate 除了作为 ORM 框架之外,它也是一种 JPA 实现 从功能上来说,JPA 是 Hibernate 功能的一个子集
JPA的优势
  • 标准化: 提供相同的 API,这保证了基于JPA 开发的企业应用能够经过少量的修改就能够在不同的 JPA 框架下运行。
  • 简单易用,集成方便: JPA 的主要目标之一就是提供更加简单的编程模型,在 JPA 框架下创建实体和创建 Java 类一样简单,只需要使用 javax.persistence.Entity 进行注释;JPA 的框架和接口也都非常简单,
  • 可媲美JDBC的查询能力: JPA的查询语言是面向对象的,JPA定义了独特的JPQL,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。
  • 支持面向对象的高级特性: JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,最大限度的使用面向对象的模型
基本注解
1. @Entity

@Entity 标注用于实体类声明语句之前,指出该Java 类为实体类,将映射到指定的数据库表。如声明一个实体类 Customer,它将映射到数据库中的 customer 表上。

2. @Table

当实体类与其映射的数据库表名不同名时需要使用 @Table 标注说明,该标注与 @Entity 标注并列使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行。
@Table 标注的常用选项是 name,用于指明数据库的表名
    @Table(name="JPA_CUTOMERS")
    @Entity
    public class Customer {
    }
3. @Id

@Id 标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。
@Id标注也可置于属性的getter方法之前。
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Id
	public Integer getId() {
		return id;
	}
4. @GeneratedValue

@GeneratedValue 用于标注主键的生成策略,通过 strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer 对应 identity,MySQL 对应 auto increment。
在 javax.persistence.GenerationType 中定义了以下几种可供选择的策略: (1). IDENTITY:采用数据库 ID 自增长的方式来自增主键字段,Oracle 不支持这种方式; (2). AUTO:JPA 自动选择合适的策略,是默认选项; (3). SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式 (4). TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。
5. @Basic

@Basic 表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的 getXxxx() 方法,默认即为@Basic
fetch: 表示该属性的读取策略,有 EAGER 和 LAZY 两种,分别表示主支抓取和延迟加载,默认为 EAGER.
optional:表示该属性是否允许为null, 默认为true
6. @Column

当实体的属性与其映射的数据库表的列不同名时需要使用@Column 标注说明, 该属性通常置于实体的属性声明语句之前,还可与 @Id 标注一起使用。
@Column 标注的常用属性是 name,用于设置映射数据库表的列名。此外,该标注还包含其它多个属性,如:unique 、nullable、length 等。
@Column 标注的 columnDefinition 属性: 表示该字段在数据库中的实际类型.通常 ORM 框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是TIMESTAMP.此外,String的默认映射类型为VARCHAR, 如果要将 String 类型映射到特定数据库的 BLOB 或TEXT 字段类型.
@Column标注也可置于属性的getter方法之前
7. @Transient

表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.
如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,否则,ORM框架默认其注解为@Basic
8. @Temporal

在核心的 Java API 中并没有定义 Date 类型的精度(temporal precision). 而在数据库中,表示 Date 类型的数据有 DATE, TIME, 和 TIMESTAMP 三种精度(即单纯的日期,时间,或者两者 兼备). 在进行属性映射时可使用@Temporal注解来调整精度.

    import java.util.Date;
    ...
    private Date createTime;
    //映射到数据库的时间戳类型
    @Temporal(TemporalType.TIMESTAMP)
	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}
	
	private Date birth;
	//映射到数据库的日期类型
	@Temporal(TemporalType.DATE)
	public Date getBirth() {
		return birth;
	}
9. @TableGenerator

将当前主键的值单独保存到一个数据库的表中,主键的值每次都是从指定的表中查询来获得
这种方法生成主键的策略可以适用于任何数据库,不必担心不同数据库不兼容造成的问题。
    //name 属性表示该主键生成策略的名称,它被引用在@GeneratedValue中设置的generator 值中
    //table 属性表示表生成策略所持久化的表名
    //pkColumnName 属性的值表示在持久化表中,该主键生成策略所对应键值的名称
    //valueColumnName 属性的值表示在持久化表中,该主键当前所生成的值,它的值将会随着每次创建累加
    //pkColumnValue 属性的值表示在持久化表中,该生成策略所对应的主键
    //allocationSize 表示每次主键值增加的大小, 默认值为 50
 
    @TableGenerator(name="ID_GENERATOR",table="JPA_ID_GENERATES",pkColumnName="PK_NAME",pkColumnValue="CUSTOMER_ID",valueColumnName="PK_VALUE",allocationSize=100)
	@GeneratedValue(strategy=GenerationType.TABLE,generator="ID_GENERATOR")
	@Id
	public Integer getId() {
		return id;
}
JPA项目的开发步骤

(1). 导入 JPA 依赖的 jar 文件

  • hibernate-release-x.x.x.Final\lib\required*.jar
  • hibernate-release-x.x.x.Final\lib\jpa*.jar
  • 数据库驱动的 jar 包

(2). 配置持久化类

Table(name="JPA_CUTOMERS")
@Entity
public class Customer {
	
	private Integer id;
	private String lastname;
	private String email;
	private int age;
	
	private Date createTime;
	private Date birth;
 
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Id
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	@Column(name="last_name",length=50,nullable=false)
	public String getLastname() {
		return lastname;
	}
	public void setLastname(String lastname) {
		this.lastname = lastname;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Date getCreateTime() {
		return createTime;
	}
	@Temporal(TemporalType.TIMESTAMP)
	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}
	@Temporal(TemporalType.DATE)
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
}

(3). 类路径下的的 META-INF 目录下放置persistence.xml,文件的名称是固定的

    <!-- name 属性用于定义持久化单元的名称  transaction-type 指定 JPA 的事务处理策略 (RESOURCE_LOCAL:默认值,数据库级别 的事务,只能针对一种数据库) -->
	<persistence-unit name="jpa-1" transaction-type="RESOURCE_LOCAL">
		
		<!-- 
		配置使用什么 ORM 产品来作为 JPA 的实现 
		1. 实际上配置的是  javax.persistence.spi.PersistenceProvider 接口的实现类
		2. 若 JPA 项目中只有一个 JPA 的实现产品, 则也可以不配置该节点. 
		-->
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
		
		<class>com.axon.jpa.helloworld.Customer</class>
		
		<properties>
			<!-- 连接数据库的基本信息 -->
			<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
			<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
			<property name="javax.persistence.jdbc.user" value="root"/>
			<property name="javax.persistence.jdbc.password" value=""/>
			
			<!-- 配置hibernate的基本信息 -->
			<!-- 执行操作时是否在控制台打印 SQL -->
			<property name="hibernate.show_sql" value="true" />
			<!-- 是否对 SQL 进行格式化 -->
			<property name="hibernate.format_sql" value="true" />
			<!-- 指定自动生成数据表的策略 -->
			<property name="hibernate.hbm2ddl.auto" value="update" />
			
		</properties>
		
	</persistence-unit>

(4). 持久化单元操作

        // 创建 EntityManagerFactory 对象
		EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("jpa-1");
		// 创建  EntityManager 对象
		EntityManager entityManager = entityManagerFactory.createEntityManager();
		// 开启事务
		EntityTransaction entitytransaction = entityManager.getTransaction();
		entitytransaction.begin();
		//持久化操作
		entityManager.persist(customer);
		//提交事务
		entitytransaction.commit();
		// 关闭 EntityManager
		entityManager.close();
		//关闭 EntityManagerFactory
		entityManagerFactory.close();

Web 服务

EJB

介绍

EJB组件:JavaBean是在编程环境(IDE)中能够被可视化处理的可重用组件,是实现分布式业务逻辑的 Java 组件。我们在开发的时候可以利用这些组件,像搭积木一样建立面向对象的分布式应用。

EJB容器:是EJB组件的运行环境,为部署EJB组件提供服务,包括事务、安全、远程客户端的网络发布、资源管理等。

EJB服务器:管理EJB容器的高端进程或应用程序,并提供对系统服务的访问。调用EJB组件的应该称为EJB客户端,客户端可以运行在Web容器中。

架构

在这里插入图片描述
age-20201211150629805.png)]

EJB是什么?
  1. EJB是sun的JavaEE服务器端组件模型,是一种规范,设计目标与核心应用是部署分布式应用程序。
  2. EJB2.0过于复杂,EJB3.0的推出减轻了开发人员进行底层开发的工作量,它取消或最小化了很多(以前这些是必须实现)回调方法的实现,并且降低了实体Bean及O/R映射模型的复杂性。
  3. EJB大概是J2EE架构中唯一一个没有兑现其能够简单开发并提高生产力承诺的组件。
EJB3.0新特性

相比EJB3以前的版本而言,增加了两个新特性:元数据注解(Annotation) 和依赖注入(Injection),而元数据注解以最大限度的使部署描述符从冗余繁杂中脱离出来。

EJB体系结构

EnterpriseBean和Serializable接口一样,是一个标记性接口。用于标记一个类为一个Bean。它有三种实现:SessionBeanEntityBeanMessageDrivenBean

SessionBean:它是对业务逻辑的封装,类似于我们经常写的Service层。它可以以local, remote, webservice 服务的方式被client调用。

EntityBean:它是对数据库对象的封装,一个EntityBean,就是数据库的一条记录。

MessageDrivenBean:一个messageDrivenBean其实就是一个javax.jms.MessageListener。在JMS中有MessageConsumer,它支持两种接收消息的方式:同步接收采用MessageConsumer#receive()方法,异步接收则是为MessageConsumer设置一个MessageListener,一旦接收到消息,就调用listener#onMessage()。

SessionBean

1、SessionBean服务组件

SessionBean服务端有三大组件Home、EJbObject、SessionBean。

SessionBean是我们编写业务逻辑的地方。譬如数据库操作,进行计算等等。但是它对于客户端是不可见的,一个SessionBean实例的创建、销毁、激活、钝化等都是由EJB容器来管理的。

EJBObject:你可以将EJBObject看作是SessionBean对象的Proxy。需要将你的业务方法同样在EJBObject中复制一份。例如有一个HelloSessionBean#sayHello(str) 业务,如果要将该业务方法暴露出去给Client使用,与之对应的HelloEJBObject中必然得包含#sayHello(str)方法。也就是说Client需要使用EJBObject来达到与SessionBean交互的。

Home:这个名字起的怪异,我们可以将其理解为一个SessionBean的Factory。EJB容器通过Home对象来创建SessionBean对象,并装配出它的代理对象(EJBObject对象)。这是它的唯一用途。

2、Remote与Local

对于Home,和EJBObject,它们俩个都分为两类:Remote,Local。

Remote模式的,主要用于不在同一个JVM进程里,而在同一个进程里使用时,只需要使用Local模式的即可,这样选择自然是为了性能考虑。

3、Client访问处理流程(很容易看出Local性能好在哪里)

3.1 Remote模式下SessionBean 的访问流程

1、客户端通过JNDI获取到Home对象(EJBHome)的引用

2、客户端使用homeRef#create()方法来创建出EJBObject的Stub。

2.1)客户端底层使用Socket通信将次过程发给服务端Skeleton。

2.2)Skeleton调用服务端的Home对象的create方法,分配SessionBean对象(可能是新创建一个,也可能是从对象池中取一个,具体怎样依赖于是否是Stateful的),同时为该SessionBean对象生成一个代理对象(EJBObject实例),然后返回代理对象的引用。

2.3)客户端拿到EJBObject的引用就是Stub对象。

3、客户端访问业务

3.1) 客户端底层使用Socket通信将次过程发给服务端Skeleton。

3.2)Skeleton根据请求找到该EJBObject,调用与之关联的SessionBean的相应的业务。返回结果

3.3)客户端得到调用结果

3.2 Local模型下SessionBean的访问流程

1、客户端通过JNDI获取到Home对象(EJBLocalHome)的引用

2、客户端使用homeRef#create()方法来创建出EJBLocalObject(怎么创建也要依赖于是否的Stateful的)

3、客户端访问业务
常用注解

**@Stateless:**标记类把Java类声明为一个无状态会话bean

**@EJB:**表示注入实例,EJB注入和Resource注入相比,EJB注入只是针对于EJB而言,而Resource注入即是对所有的文件都可以进行注入。

**@Remove:**为会话 Bean 声明远程业务接口。用在接口上时,将该接口指定为远程业务接口。在这种情况下,不提供任何 value()。用在方法上,通过这个注解来说明在调用这个方法之后bean的实例将被清除掉。

**@Local:**用在 Bean 类上时,为会话 Bean 声明本地业务接口。用在接口上时,将该接口指定为本地业务接口。在这种情况下,不提供任何 value()。如:@Local(LawsuitService.class)

**@Stateful:**有状态会话 Bean 的组件定义注释。

**@Timeout:**指定无状态会话 Bean 类或消息驱动 Bean 类上接收该 Bean 的 EJB 计时器过期的方法。

**@TransactionAttribute:**在 TYPE-level 应用时,为会话或消息驱动 Bean 的所有业务方法指定默认事务属性。在方法级应用时,仅为该方法指定事务属性。

如:@TransactionAttribute(TransactionAttributeType.SUPPORTS)、

@TransactionAttribute(TransactionAttributeType.REQUIRED)。

**@Interceptors:**声明类或方法的拦截器的有序列表。

**@Lock:**方法声明一个并发锁的单例bean具有容器管理的并发。

**@Schedule(排程器):**计划时间为自动建立一个超时计划基于一个时间表达式。

**@Startup:**标记一个单例在应用初始化期间。

**@ConcurrencyManagement:**声明单例或有状态bean的并发管理类型

JavaEE 框架技术

配置文件

web.xml 的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <display-name>Sample Application</display-name>
    <description>This is a sample application</description>
    <!-- 在此设定的参数,可以在servlet中用 getServletContext().getInitParameter("my_param") 来取得 -->
    <context-param>    <!-- 用来设定web站台的环境参数 -->
        <param-name>my_param</param-name>
        <param-value>hello</param-value>
    </context-param>
    <filter>
        <!-- 过滤器名,可以随便取,当web应用中有多个过滤器时不允许重名. -->
        <filter-name>SampleFilter</filter-name>
        <!-- 具体的过滤器的类的完整的包名+类名。注意:不能写错了。否则容器不能正确的实例化过滤器 -->
        <filter-class>mypack.SampleFilter</filter-class>
        <init-param>
            <!-- 参数名 -->
            <param-name>initParam1</param-name>
            <!-- 参数值 -->
            <param-value>2</param-value>
        </init-param>
    </filter>
    <!-- Define the SampleFilter Mapping -->
    <filter-mapping>
        <!-- 过滤器名,注意要和上面的<filter-name>里的名字一样。-->
        <filter-name>SampleFilter</filter-name>
        <!--
        指定过滤器负责过滤的URL。这里指定了*.jsp表示在访问任何一个jsp页面时都会先使用mypack.SampleFilter过滤器进行过滤。
        如果写成login.jsp.则只有在访问login.jsp时才会调用该过滤器进行过滤。-->
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    <servlet>
        <!-- Servlet名字,可以随便取,有多个Servlet时不允许重名 -->
        <servlet-name>SampleServlet</servlet-name>
        <!-- 指定实现这个Servlet的类。完整的包名+类名 -->
        <servlet-class>mypack.SampleServlet</servlet-class>
        <!-- 定义Servlet的初始化参数(包括参数名和参数值)
        一个<servlet>元素里可以有多个<init-param>元素。
        在Servlet类中通过ServletConfig类的来访问这些参数。-->
        <init-param>
            <!-- 参数名 -->
            <param-name>initParam1</param-name>
            <!-- 参数值 -->
            <param-value>2</param-value>
        </init-param>
        <!-- 指定当前Web应用启动时装载Servlet的次序。当这个数>=0时,容器会按数值从小到大依次加载。如果数值<0或没有指定,容器将载Web客户首次访问这个Servlet时加载。-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- Define the SampleServlet Mapping -->
    <servlet-mapping>
        <!-- 必须和<servlet>里的<servlet-name>内容一样 -->
        <servlet-name>SampleServlet</servlet-name>
        <!--指定访问这个Servlet的URL。这里给出的是对于整个Web应用的相对URL路径。-->
        <url-pattern>/sample</url-pattern>
    </servlet-mapping>
    <session-config>
        <!--设定HttpSession的生命周期。这里以分钟计算。下面的设定指明Session在最长不活动时间为10分钟。
        过了这个时间,Servlet容器将它作为无效处理。
        注意这里和程序里指定的计数单位不同,程序里是以秒为单位。
        <session-config>只有<session-timeout>这个元素 -->
        <session-timeout>10</session-timeout>
    </session-config>
    <!-- 配置会话侦听器,class表示一个
    HttpSessionListener 或 HttpSessionActivationListener
    或 HttpSessionAttributeListener 或 HttpSessionBindingListener的实现类。
    该节点允许多个 -->
    <listener>
        <listener-class>com.cn.SessionListenerImpl</listener-class>
    </listener>
    <!--在 用户访问Web应用时,如果仅给出Web应用的根访问URL,没有指定具体的文件名,容器会调用
    <weblcome-file- list>元素里指定的文件清单。
    <welcome-file-list>里允许有多个<welcome-file>元素,每个元素代表一个文件。
    容器会先找第一文文件件是否存在,如果存在这把这个文件返回个客户,不再进行其他文件的查找。如果不存在则找第二个文件,依次 类推。
    如果所有文件都不存在,则跑出404错误 -->
    <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
        <welcome-file>index.htm</welcome-file>
    </welcome-file-list>
    <!-- 设置Web应用引用的自定义标签库。下面的代码定义了一个/mytaglib标签库,它对应的TLD文件为/WEB-INF/mytaglib.tld -->
    <taglib>
        <taglib-uri>/mytaglib</taglib-uri>
        <taglib-location>/WEB-INF/mytaglib.tld</taglib-location>
    </taglib>
    <!-- 如果Web应用访问了由Servlet容器管理的某个JNDI Resource必须在这里声明对JNDI Resource的引用 -->
    <resource-ref>
        <!-- 对应用资源的说明 -->
        <description>DB Connection</description>
        <!-- 指定所引用资源的JNDI名字 -->
        <res-ref-name>jdbc/sampleDb</res-ref-name>
        <!-- 指定所引用资源的类名字 -->
        <res-type>javax.sql.DataSource</res-type>
        <!-- 指定管理所引用资源的Manager,
        它有两个可选值:Container和Application.Container表示由容器来创建和管理Resource,Application表示由Web应用来管理和创建Resource -->
        <res-auth>Container</res-auth>
    </resource-ref>
    <security-constraint>
        <web-resource-collection>
            <!-- 这个名字是必须的,由工具使用,别的地方不使用 -->
            <web-resource-name>my application</web-resource-name>
            <!-- 指定要受约束的资源,至少有一个。可以有多个. -->
            <uri-pattern>/*</uri-pattern>
            <!-- 描 述了度可与URL模式指定的资源哪些方法是受约束的,如果没有<http-method>元素,表示任何角色的人都无法访问任何http的方 法
            。这里放置了GET方法,表示只有GET方法是受约束的。其他任何角色的人可以访问POST和其他的方法。但不能访问GET方法。-->
            <http-method>GET</http-method>
        </web-resource-collection>
        <!-- 如果没有<auth-constraint>表示所有角色都能访问GET方法,如果是<auth-constraint/>表示任何角色都不能访问GET方法 -->
        <auth-constraint>
            <!-- 可选的。表示哪些角色能够在指定的资源上调用受约束的方法。这里表示只有拥有Admin和Member角色的人能够访问GET方法
            <security-role>>里的<role-name>值一样 -->
            <role-name>Admin</role-name>
            <role-name>Member</role-name>
        </auth-constraint>
    </security-constraint>
    <!-- 将指定的角色映射到web.xml里 -->
    <security-role>
        <description>The role that is required to log into the my Application
        </description>
        <!-- 以下的角色和tomcat-users.xml里的<tomcat-users>里的<role rolename=""/>里的rolename属性值对应 -->
        <role-name>Guest</role-name>
        <role-name>Admin</role-name>
        <role-name>Member</role-name>
    </security-role>
    <!-- 如果要想进行认证,必须有<login-config>-->
    <login-config>
        <!--认证方式。有4种:BASIC:基本。 DIGEST:摘要。CLIENT-CERT:客户证书(能提供最高强度的认证)。FORM:表单 -->
        <auth-method>FORM</auth-method>
        <realm-name>
            Tomcat Servet Configuraton Form-Based Authentication Area
        </realm-name>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/error.jsp</form-error-page>
        </form-login-config>
    </login-config>
    <error-page> <!-- 用来处理错误代码或异常的页面,有三个子元素: -->
        <error-code>404</error-code> <!-- 指定错误代码 -->
        <exception-type>java.lang.Exception</exception-type> <!-- 指定一个JAVA异常类型 -->
        <location>/error404.jsp</location> <!-- 指定在web站台内的相关资源路径 -->
    </error-page>
    <mime-mapping>        <!-- 定义某一个扩展名和某一个MIME Type做对映,包含两个节点 -->
        <extension>doc</extension>    <!-- 扩展名的名称 -->
        <mime-type>application/vnd.ms-word</mime-type>    <!-- MIME格式 -->
    </mime-mapping>
    <mime-mapping>
        <extension>xls</extension>
        <mime-type>application/vnd.ms-excel</mime-type>
    </mime-mapping>
</web-app>

java部分的代码

//  格式化日期
Date dt = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmSSsss");
String res = sdf.format(dt);

// 设置字符编码
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");

// 获得当前得时间
LocalDate dt=LocalDate.now();
Date dt1=Date.valueOf(dt);

// 操作数据库
 String sql="select username from manager where username=? and userpwd=?";
 conn=this.getConnection();
 PreparedStatement psmt=conn.prepareStatement(sql);
// 替代上面问号的位置
 psmt.setString(1, username);
 psmt.setString(2, userpwd);
 ResultSet rs=psmt.executeQuery();


上传文件的代码

protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        HttpSession session = request.getSession();
        if (session.isNew()) {
            response.sendRedirect("login.jsp");
            return;
        }
        Object oUsername = session.getAttribute("username");
        if (oUsername == null) {
            response.sendRedirect("login.jsp");
            return;
        }
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        String username = (String) oUsername;
        Part part = request.getPart("myfile");
        String clientFileName = part.getSubmittedFileName(); 
        if (clientFileName=="") {
            session.setAttribute("message", "您没有选择文件!");
            response.sendRedirect("show_operation_msg.jsp");
            return;
        }
        
        String webAppPath = this.getServletContext().getRealPath("/");
        String serverFilePath = webAppPath + this.getServletContext().getInitParameter("uploadFilePath");
        String serverFileNameWithPath = serverFilePath + "\\"
                + UploadServlet.produceServerFileNameByUserAndTime(username, clientFileName);
        part.write(serverFileNameWithPath);
        String message="文件:"+clientFileName+"上传成功!<br>"
                +"文件保存到:"+serverFileNameWithPath;
        session.setAttribute("message", message);
        session.setAttribute("back_url", "uploadfile.jsp");
        response.sendRedirect("show_operation_msg.jsp");
    }

拦截器

/**
 * 对任意客户端请求进行过滤,若用户请求url中不包含manage字符串,则将把请求转给对应资源
 * 反之,就检验session中是否存在 username属性,不存在转向index.jsp页面,存在则将请求转给对应资源
 */
@WebFilter(filterName ="checkloginFilter",urlPatterns = {"/*"})
public class CheckLoginFilter extends HttpFilter {
    @Override
    public void doFilter(HttpServletRequest request
            , HttpServletResponse response
            , FilterChain filterChain) throws IOException,ServletException {
        String url=request.getRequestURL().toString();
        boolean isRedirectIndexPage=false;//是否转向index.jsp
        if(url.contains("manage")&&request.getSession().getAttribute("username")==null){
            isRedirectIndexPage=true;
        }
        if(isRedirectIndexPage){
            request.getRequestDispatcher("index.jsp").forward(request,response);
        }else {
            filterChain.doFilter(request,response);
        }
    }
}

MVC 的设计流程

  1. 定义JavaBeans存储数据
  2. 编写servlet处理请求
  3. 数据结果存储在作用域中
  4. 转发请求到JSP页面
  5. 从JavaBeans中提取数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值