java分页标签使用详解

java分页标签使用详解

1. 使用 tag 文件定义自定义标签.
 
1). 可以使用 tag 文件的方式来定义自定义标签. 先前使用过标签处理器类来定义自定义标签.
 
2). 不能直接访问这个 tag 文件
 
3). tag 文件是扩展名必须为 tag
 
4). tag 文件的结构几乎和 JSP 文件相同:
一个 Tag 文件中可以有普通的 HTML 标记符、某些特殊的指令标记、 成员变量和方法的声明、Java 程序片段和 Java 表达式
 
5). tag文件只能放在如下位置:
     ①*. WEB-INF/tags
     ②*. WEB-INF/tags 的子目录
     ③. WEB-INF/ lib 中 jar 包的 META-INF/tags
     ④. WEB-INF/ lib 中 jar 包的 META-INF/tags 下的子目录
     ⑤. jar 包中的 tag 文件需要 tld
     
6). 使用 <taglib> 指令标记引入自定义标签库.
<taglib>指令的格式如下: <%@ taglib tagdir=”自定义标记库的位置” prefix=”前缀”>
 
7). 若 JSP 页面调用一个 tag 文件时需要动态地向该 tag 文件传递信息, 则需要使用带有标记体的标签, tag 文件通过使用 <jsp:doBody />
标签处理 JSP 页面传递过来的标签体
 
8). tag 文件的 tag 指令:     
 
I. tag 文件中的 tag 指令类似于 JSP 文件中的 page 指令. tag 文件通过使用 tag 指令可以指定某些属性的值, 以便从总体上影响 tag 文件的
处理和表示. tag指令的语法为: <%@ tag 属性1=”属性值” 属性2=”属性值” … 属性n=”属性值”%>
一个 tag 文件中可以使用多个 tag 指令, 因此经常使用多个 tag 指令为属性指定需要的值:
 <%@ tag 属性1=”属性值”%>
 <%@ tag 属性2=”属性值”%>
 …
 
II. tag 指令可以操作的属性有: body-content、language、import、pageEncoding。
 
III^^. body-content 属性可以确定 JSP 页面使用 Tag 标记定义的自定义标签是否可以有标记体, 如果允许有标记体, 该属性会给出标记体内容的类型。
     > body-content属性值有: empty、 tagdependentscriptless . 默认值是scriptless。 
     > 属性的值是 empty: 标签体为空
     > 属性的值是 tagdependent  scriptless : 有标签体
     > 属性值是 scriptless, 则标签体中不能有 Java 代码. 属性值是 tagdependent , 则标签体内容按纯文本处理.
     
IV. language 属性的值指定 tag 文件使用的脚本语言, 目前只能取值java, 其默认值就是java.
 
V.  import 属性的作用是为 tag 文件引入需要的包或类. import 属性可以取多个值.
默认引入的类: “java.lang.*”、 “javax.servlet.*”、javax.servlet.jsp.*”、”javax.servlet.http.*”。
 
VI. pageEncoding 属性: 指定 tag 文件的字符编码, 其默认值是 ISO-8859-1
 
9). include 指令: tag 文件中也有和 JSP 文件类似的 include 指令, 使用方法和作用与 JSP 文件中的 include 指令类似
 
10). attribute指令: tag 文件中通过使用 attribute 指令, 让使用它的 JSP 页面向该 tag 文件传递需要的属性.
attribute指令的格式为: <%@ attribute name=”属性名” required=”true”|”false” type=”对象的类型”%>
例如: <%@ attribute name=”length” required=”true” %>
 
11)^^. variable 指令: tag 文件通过使用 variable 指令可以将 tag 文件中的对象返回给调用该 tag 文件的 JSP页面.
I. variable 指令的格式: <%@ variable name-given=”对象名字” variable-class=”对象的类型” scope=”有效范围” %>
 
     > variable-class: 对象的类型必须带有包名
     > scope: AT_BEGIN; NESTED; AT_END.
       NESTED: 只可以在标签体内使用的对象. AT_END: 在 tag 标记结束后才可以使用对象。
     > 例: <%@ variable name-given=”time” variable-class=”java.util.Date” scope=”AT_END” %>
 
12). taglib 指令: 一个 tag 文件可以使用 tag 标记来调用其它标签
一:首先继承SimpleTagSupport类(一般不建议使用这种做法,原因为通过类的方式写jsp效率低)

import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;
 
public class TestTag extends SimpleTagSupport{
     
@Override
public void doTag() throws JspException, IOException {
  //向页面上输出文字
  getJspContext().getOut().print( “hello world!”);
     }
}

二:通过.tag文件来定义分页标签(本质上还是继承了SimpleTagSupport )

index.tag
<%@ tag language=“java”pageEncoding=“UTF-8” %>
<%@ tag import=“java.util.Date” %>
<%@ tag body-content= “scriptless” %>
<%@ attribute name=“username” required =“true” rtexprvalue=“true” %>
hello World.now:<%= new Date() %><%= username %>
 
<%@ page language=“java” contentType=“text/html; charset=UTF-8”
    pageEncoding= “UTF-8”%>
<%@ taglib tagdir=“/WEB-INF/tags” prefix= “yafei” %>   
<!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd”>
<html>
<head>
<meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”>
<title> Insert title here</title >
</head>
<body>
     <yafei:helloworld username=${param.username }></yafei:helloworld >
</body>
</html>
 
 
运行 mytest.jsp(内含index.tag),可实现功能,username需要添加到url地址栏
实战:
pagination.tag

<%@tag pageEncoding=“UTF-8” %>
 
<%@ attribute name=“page” type=“org.springframework.data.domain.Page” required=“true” %>
<%@ attribute name=“paginationSize” type=“java.lang.Integer” required=“true”%>
 
<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
 
<c:set value= ${pageContext.request.contextPath } var=“ctx” ></c:set>
<div style=” text-align:right ; padding :6px 6px 0 0;”>
 
     共 ${page.totalElements} 条记录
     &nbsp;&nbsp;
     
     当前第 ${page.number + 1} 页/共 ${page.totalPages} 页
     &nbsp;&nbsp;
     
     <% if (page.hasPreviousPage()){ %>
           <a href=‘?page=1&sortType= ${sortType}&${searchParams} >首页 </a>
           &nbsp;&nbsp;
           <a href= ‘?page=${page.number + 1-1}&sortType=${sortType}&${searchParams}> 上一页</a >
           &nbsp;&nbsp;
     <%}%>
     
     <% if (page.hasNextPage()){ %>
           <a href= ‘?page=${page.number + 1+1}&sortType=${sortType}&${searchParams}> 下一页</a >
           &nbsp;&nbsp;
           <a href=‘?page= ${page.totalPages}&sortType=${sortType} &${searchParams}>末页</ a>
           &nbsp;&nbsp;
     <%}%>
     
     转到 <input id= “pageNo” size =‘1’/> 
     &nbsp;&nbsp;
 
</div>
 
<script type= “text/javascript” src =${ctx }/static/jquery/jquery-1.9.1.min.js” ></script>
<script type= “text/javascript”>
 
     $(function(){
          
          $( “#pageNo”).change(function (){
              
               var pageNo = $(this).val();
               var reg = /^\d+$/;
               if(!reg.test(pageNo)){
                   $( this).val(“” );
                   alert( “输入的页码不合法” );
                    return;
              }
              
               var pageNo2 = parseInt(pageNo);
               if(pageNo2 < 1 || pageNo2 > parseInt(“${page.totalPages}” )){
                   $( this).val(“” );
                   alert( “输入的页码不合法” );
                    return;
              }
              
               //查询条件需要放入到 class=’condition’ 的隐藏域中.
              window.location.href = window.location.pathname
                   + “?page=” + pageNo2 + “&sortType=${sortType}&${searchParams}” ;
              
          });
     })
</script>
<%@ taglib tagdir=“/WEB-INF/tags” prefix=“atguigu” %>
<atguigu:pagination paginationSize=“5” page=${page }></atguigu:pagination>

jpa概述

jpa概述

①what

Java Persistence API:用于对象持久化的 API
Java EE 5.0 平台标准的 ORM 规范,使得应用程序以统一的方式访问持久层
JPA 是 hibernate 的一个抽象(就像JDBC和JDBC驱动的关系):
JPA 是规范:JPA 本质上就是一种  ORM 规范,不是ORM 框架 —— 因为 JPA 并未提供 ORM 实现,它只是制订了一些规范,提供了一些编程的 API 接口,但具体实现则由 ORM 厂商提供实现
Hibernate 是实现:Hibernate 除了作为 ORM 框架之外,它也是一种 JPA 实现
从功能上来说, JPA 是 Hibernate 功能的一个子集
ORM  映射元数据:JPA 支持 XML 和  JDK 5.0 注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。
JPA 的 API:用来操作实体对象,执行CRUD操作,框架在后台完成所有的事情,开发者从繁琐的 JDBC和 SQL代码中解脱出来。
查询语言(JPQL):这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序和具体的  SQL 紧密耦合。
②How
1)使用JPA持久化对象的步骤
创建 persistence.xml, 在这个文件中配置持久化单元
需要指定跟哪个数据库进行交互;
需要指定 JPA 使用哪个持久化的框架以及配置该框架的基本属性
创建实体类, 使用 annotation 来描述实体类跟数据库表之间的映射关系.
使用 JPA API 完成数据增加、删除、修改和查询操作
创建 EntityManagerFactory (对应 Hibernate 中的 SessionFactory);
创建 EntityManager (对应 Hibernate 中的Session);
注意:JPA 规范要求在类路径的 META-INF 目录下放置persistence.xml,文件的名称是固定的
详解:
@Entity:标注用于实体类声明语句之前,指出该Java 类为实体类,将映射到指定的数据库表。如声明一个实体类 Customer,它将映射到数据库中的 customer 表上。
@Table:当实体类与其映射的数据库表名不同名时需要使用 @Table 标注说明,该标注与 @Entity 标注并列使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行。
@Table 标注的常用选项是 name,用于指明数据库的表名
@Table标注还有一个两个选项 catalog 和 schema 用于设置表所属的数据库目录或模式,通常为数据库名。uniqueConstraints 选项用于设置约束条件,通常不须设置。

@Id 标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。
@Id标注也可置于属性的getter方法之前。(一般建议放在 getter方法前)
@GeneratedValue  用于标注主键的生成策略,通过 strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer 对应 identity,MySQL 对应 auto increment。
在 javax.persistence.GenerationType 中定义了以下几种可供选择的策略:
IDENTITY:采用数据库 ID自增长的方式来自增主键字段,Oracle 不支持这种方式;
AUTO: JPA自动选择合适的策略,是默认选项;
SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式
TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。
@Basic 表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的 getXxxx() 方法,默认即为@Basic
fetch: 表示该属性的读取策略,有 EAGER 和 LAZY 两种,分别表示主支抓取和延迟加载,默认为 EAGER.
optional:表示该属性是否允许为null, 默认为true
当实体的属性与其映射的数据库表的列不同名时需要使用@Column 标注说明,该属性通常置于实体的属性声明语句之前,还可与 @Id 标注一起使用。
@Column 标注的常用属性是 name,用于设置映射数据库表的列名。此外,该标注还包含其它多个属性,如:unique 、nullable、length 等。
@Column 标注的 columnDefinition 属性: 表示该字段在数据库中的实际类型.通常 ORM 框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是TIMESTAMP.此外,String的默认映射类型为VARCHAR, 如果要将 String 类型映射到特定数据库的 BLOB 或TEXT 字段类型.
@Column标注也可置于属性的getter方法之前
@Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.
如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,否则,ORM框架默认其注解为@Basic
@Temporal在核心的 Java API 中并没有定义 Date 类型的精度(temporal precision).  而在数据库中,表示 Date 类型的数据有 DATE, TIME, 和 TIMESTAMP 三种精度(即单纯的日期,时间,或者两者 兼备). 在进行属性映射时可使用@Temporal注解来调整精度.

用 table 来生成主键详解
将当前主键的值单独保存到一个数据库的表中,主键的值每次都是从指定的表中查询来获得
这种方法生成主键的策略可以适用于任何数据库,不必担心不同数据库不兼容造成的问题。

①JPA相关接口/类:Persistence
Persistence  类是用于获取 EntityManagerFactory 实例。该类包含一个名为 createEntityManagerFactory 的 静态方法 。
createEntityManagerFactory 方法有如下两个重载版本。
带有一个参数的方法以 JPA 配置文件 persistence.xml 中的持久化单元名为参数
带有两个参数的方法:前一个参数含义相同,后一个参数 Map类型,用于设置 JPA 的相关属性,这时将忽略其它地方设置的属性。Map 对象的属性名必须是 JPA 实现库提供商的名字空间约定的属性名。

Struts2运行流程

Struts2运行流程

一:两个主线(初始化主线、请求处理主线)

初始化主线:web应用加载的时候,对当前的环境进行一个初始化操作,这个方法就是在struts核心拦截器的init方法中实现。由于filter的生命周期,可知它是在web应用加载的时候创建对象,然后立即进行初始化也可理解为web应用启动的时候开始。
Struts的核心拦截器由于配置的是/*,所以它一定会拦截所有请求
拦截到请求之后,进行的就是请求处理主线。
运行流程提要
①StrutsPrepareAndExecuteFilter拦截到浏览器请求
②Struts2根据请求信息询问ActionMapper对象:当前请求是否为一个Struts2请求。如果是一个Struts2请求则能够获取到对应的ActionMapping对象,如果不是一个Struts2请求则ActionMapping对象为null。
③如果是Struts2请求则必然对应着一个Action,Struts2不会直接执行目标Action,而是创建ActionProxy对象作为目标Action的代理间接调用目标Action。
④ActionProxy对象首先通过Configuration Manager检索框架的配置文件,以确定目标Action以及目标Action方法。
⑤ActionProxy对象创建ActionInvocation接口的实例对象——DefaultActionInvocation,在DefaultActionInvocation对象初始化过程中将目标Action的实例对象压入对象栈栈顶。
⑥ActionInvocation会根据事先加载的拦截器栈信息,逐一调用拦截器栈中的各个拦截器。
⑦Action执行完毕后,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。调用结果的execute方法,渲染结果。在渲染的过程中可以使用Struts2 框架中的标签。
⑧依照方法栈的顺序,依次调用invocation.invoke()之后的代码。
⑨将执行结果返回给客户端。

SpringSecuritity(3)-自定义登录

SpringSecuritity(3)-自定义登录

applicationContext.xml
<!–
自实现登陆:
1. 创建实现 UserDetailsService 的 bean, 并把其配置到 ioc 容器中
2. 使 security:authentication-provider 节点的 user-service-ref 属性指向 UserDetailsService bean.
–>
<bean id=”userDetailsService” class=”springsecurity.MyUserDetailsService” ></bean>
<security:authentication-manager >
<security:authentication-provider user-service-ref=”userDetailsService” >
</security:authentication-provider>
</security:authentication-manager >

MyUserDetailsService
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
//1.利用传入的username从数据库 加载相应的记录
if(“fm12345” .equals(username)){
//模拟用户名不存在的异常
throw new UsernameNotFoundException(username);
}
//2.创建user对象并返回,实际上user对象是UserDetails接口的一个实现类
//以下信息需要从数据库中获取
String password= “12345”;
//当前 username 对应的 User 是否可用
boolean enabled = true;
//当前的账户是否过期
boolean accountNonExpired = true;
//当前的账户的凭证是否过期
boolean credentialsNonExpired = true;
//账号是否被锁定
boolean accountNonLocked = true;
//用户所具有的权限信息. 通过 debug 透视图知道里面存放的实际上是 GrantedAuthorityImpl 实例
//且 GrantedAuthorityImpl 只有一个属性 role 被赋值, 且该值和配置文件中 authorities 对应
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add( new GrantedAuthorityImpl(“ROLE_USER” ));
if(“admin” .equals(username))
authorities.add( new GrantedAuthorityImpl(“ROLE_ADMIN” ));
User user = new User(username, password, enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, authorities);
return user;
}
}

SpringSecuritity(2)-helloworld

SpringSecuritity系列教程(二)helloworld

1.需求
Spring-security 应用的根目录下有两个 Jsp 页面: index.jsp 和 admin.jsp. admin 用户有权限访问这两个页面, 而 user 用户只能访问 index.jsp
提供”登出”功能
2.准备:
user  user
admin admin
2.1添加jar包
在 Spring 的 Web 应用中添加 spring-security-3.1.0.M1\dist\ spring-security-acl-3.1.0.M1.jar、 spring-security-config-3.1.0.M1.jar、 spring-security-core-3.1.0.M1.jar、 spring-security-taglibs-3.1.0.M1.jar、 spring-security-web-3.1.0.M1.jar
2.2配置 web.xml 文件
将 HTTP 请求委托给 Spring 应用程序上下文中的一个 Bean .  被委托的 Bean 实现了 javax.servlet.Fitler 接口, 但它需要受 Spring IOC 容器管理, 而不是直接在 web.xml 中配置*.
默认情况下, DelegatingFilterProxy 会把 HTTP 请求委托给和它的 <filter-name> 属性相同的 Bean 上(也可以在 targetBeanName 初始参数中覆盖该 Bean 的名字).
 SpringSecurity  在 web 服务器加载当前 web 应用时配置一个名称为 springSecurityFilterChain 的过滤器链(SpringSecurity 即通过该过滤器链为 web 应用提供安全服务), 所以 <filter-name> 应该使用这个名字.
3.配置 applicationContext-security.xml 文件
4.参数详解
<http auto-config=“true”> 元素自动配置好了典型 web 应用程序所需的基本安全服务:
基于表单的登录服务: 为用户提供了用于登入应用程序, 包含登录表单的页面.
登出服务: 提供了让用户能够登出应用程序的处理程序, 这个程序被映射为响应的 URL
匿名登录: 为匿名用户分配一个安全主题并授权, 这样可以像普通用户一样来处理匿名用户.
“记住我”支持: 能在多个浏览器会话中记住用户的身份, 通常是在用户的浏览器中保存 Cookie.
Servlet API 集成: 可以通过类似 HttpServletRequest.isUserInRole() 和 HttpServletRequest.getUserPrincipal() 这样的标准 API 在 web 应用程序中访问安全信息.
<http> 配置元素中, 可以通过一个或多个 <intercept-url> 元素来限制对特定 URL 的访问.
每个 <intercept-url> 元素指定了 URL 模式以及访问这些 URL 所必须的访问属性.
access指定的权限部分, 这些权限标示符都是以 ROLE_ 开头的, 这与Spring Security中的 Voter 机制有着直接的联系, 只有包含了特定前缀的字符串才会被Spring Security处理.
在 URL 模式后总是要带上一个匹配符(*), 否则这个 URL 模式无法匹配带有参数的 URL.
在实际使用中, Spring Security采用的是一种就近原则, 当用户访问的url资源满足多个intercepter-url时,系统将使用第一个符合条件的intercept-url进行权限控制
在 <authentication-provider> 元素中配置身份验证服务.
Spring Security 支持多种用户身份验证方式, 包括根据数据库进行验证或直接在 <user-service> 中定义用户信息:
Authorities 属性定义了当前用户登陆之后将会拥有的权限,与intercept-url 中定义的权限内容一一对应. 每个用户可以同时拥有多个权限.
登出服务提供了一个处理程序来处理登出请求, 可以通过 <http> 的 <logout> 子节点进行配置.
默认被映射到 /j_spring_security_logout, 所以可以添加一个指向该 URL 的链接提供登出功能. 该 URL 可以通过 <logout> 的 logout-url 属性进行自定义.
默认情况下,  成功登出后用户会被重定向到上下文路径的根目录上. 可以通过修改 logout-success-url 来进行自定义.
Spring 提供了包含登录表单的默认页面, 同时允许用户自定义页面来充当登陆页面.
可以通过 <http> 的 <form-login> 子节点配置基于表单的登录.
默认情况下, Spring Security 会自动创建登录页面并将它映射到 /spring_security_login 上. 可以通过修改 <form-login> 的 login-page 属性来修改该映射路径.
若用户直接通过 URL 请求登录页面, 默认情况下在登录成功后会被转发到 web 应用的根目录上. 可以通过修改 default-target-url 属性来修改登录成功后的转发页面
若用户直接通过 URL 请求登录页面, 默认情况下在登录失败时会再次呈现带有错误信息的登录页面. 可以通过修改 authentication-failure-url 属性来修改登录失败后的转发页面.