Struts2——整理好的学习资料

    xiaoxiao2022-07-13  164

    Spring MVC

     

    Struts2 简介

        控制层框架

    来自Apache基金会的软件: http://struts.apache.org

    Struts2 与 Struts1 完全没有关系

    Struts2 的前身是 WebWorks

    Spring MVC\Struts2\Struts1 都是 MVC 模式的Web框架

    MVC是非常流行的 用户界面设计模式。

    MVC是3层架构中的表现层。

     

    配置Struts2

    Struts2核心jar包

    配置步骤:

    下载Struts2的jar包

    从struts.apache.org 下载

    解压缩

    将*.jar复制到 /WEB-INF/lib 文件夹

    使用maven下载

    使用Eclipse内嵌搜索,搜索到 struts2-core 的“坐标(xml)”,保存pom.xml

    使用 maven.tedu.cn/nexus (maven.aliyun.com/nextus) 在线搜索, 搜索到 struts2-core 的“坐标(xml)”,保存pom.xml

    配置主控制器

    控制器类

    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

    在struts-core-xxxx.jar 包中

    编辑文件 web.xml(部署描述文件)

    filter

    filter-mapping

    添加struts的配置文件

    位置:package中(classpath中)

    文件名:struts.xml, struts的filter会自动按照文件名struts.xml找到这个文件, 文件名不能错!!!

    web.xml:

    <?xml version="1.0" encoding="UTF-8"?>

    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns="http://java.sun.com/xml/ns/javaee"

    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

    version="2.5">

    <!-- Struts2 MVC 配置 -->

    <!-- filter 会自动找package中的struts.xml -->

    <filter>

    <filter-name>mvc</filter-name>

    <filter-class>

    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

    </filter-class>

    </filter>

    <filter-mapping>

    <filter-name>mvc</filter-name>

    <url-pattern>/*</url-pattern>

    </filter-mapping>

     

    </web-app>

    空白 struts.xml

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

    <struts>

     

    </struts>

    Hello World!步骤

    修改配置文件struts.xml 添加web请求的处理路径

    namespace="/test" 表示处理一级路径 /test

    extends="struts-default" 继承现有struts的参数

    name="hello"处理2级路径 /test/hello.action

    class="com.tedu.HelloAction"

    在处理url请求时候执行HelloAction 的 execute() 方法,

    execute方法一定有String返回值,常见的值有 "success" "error"

    /WEB-INF/msg.jsp

    与action方法的返回值配合, 表示返回 “success”时候,转发到msg.jsp页面,msg.jsp作为用户看的视图。

    添加类 com.tedu.HelloAction

    包含 String execute()

    方法中 return "success";

    添加 /WEB-INF/msg.jsp

    struts.xml 文件参考:

    <?xml version="1.0" encoding="UTF-8"?>

    <!-- struts.xml -->

    <!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

    <struts>

    <!-- 用于配置请求路径与控制器的匹配关系 -->

    <!-- /test 请求被这个包进行处理 -->

    <package name="test" namespace="/test"

    extends="struts-default">

    <!-- 请求/test/hello.action时候

    执行HelloAction的execute()方法 -->

    <action name="hello"

    class="com.tedu.HelloAction">

    <!-- execute方法返回success

    时候,转发到msg.jsp-->

    <result name="success">

    /WEB-INF/msg.jsp

    </result>

    </action>

    </package>

    </struts>

    HelloAction.java :

    package com.tedu;

     

    public class HelloAction {

    /**

    * 方法名必须是execute

    */

    public String execute(){

    System.out.println("Hello World!");

    //返回值时候success

    return "success";

    }

    }

    msg.jsp:

    <%@ page language="java"

    contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8" %>

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="utf-8">

    <title>Hello</title>

    </head>

    <body>

    <h1>Hello World!</h1>

    </body>

    </html>

    由控制器向页面传递消息

    在控制器中添加属性,并且为属性添加get方法

    在控制器方法中向属性赋值

    在JSP页面上使用 EL 表达式读取属性值

    EL表达式实际上执行属性的get方法,如果没有get方法就无法获取属性值。

     

    案例:

    HelloAction

    public class HelloAction {

    private String message;

    public String getMessage() {

    return message;

    }

    /**

    * 方法名必须是execute

    */

    public String execute(){

    message = "Hi";

    System.out.println("Hello World!");

    //返回值时候success

    return "success";

    }

    }

    msg.jsp

    <%@ page language="java"

    contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8" %>

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="utf-8">

    <title>Hello</title>

    </head>

    <body>

    <h1>Hello World!</h1>

    <!-- 自动调用getMessage方法获取信息 -->

    <h2>${message}</h2>

    </body>

    </html>

    从页面向控制器传递值

    有两种方式可以从页面向控制器传输数据:

    基本Bean属性传递方式

    域模型属性传递方式

    1. 基本属性传递方式

    在控制器中声明与html表单项 name 属性一致的Bean属性。

    添加Bean属性的getxxx setxxx方法。

    Struts会在接受请求时候,自动将表单属性值注入到 Bean 属性中

     

    代码:

    Login.jsp

    <%@ page language="java"

    contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

    <%@taglib prefix="c"

    uri="http://java.sun.com/jsp/jstl/core"%>

    <!DOCTYPE html>

    <!-- /WEB-INF/login.jsp -->

    <html>

    <head>

    <meta charset="utf-8">

    <title>登录</title>

    </head>

    <body>

    <h1>登录</h1>

    <c:url var="url"

    value="/user/login.action"/>

    <form action="${url}" method="post">

    <div>

    <label>用户名:</label>

    <input type="text"

    name="username"/>

    </div>

    <div>

    <label>密码</label>

    <input type="password"

    name="password">

    </div>

    <div>

    <input type="submit" value="登录">

    </div>

    </form>

    </body>

    </html>

    LoginAction.java

    public class LoginAction {

    private String username;

    private String password;

    //getxxx setxxx 称为:Bean 属性访问方法

    public String getPassword() {

    return password;

    }

    public void setPassword(String password) {

    this.password = password;

    }

    public String getUsername() {

    return username;

    }

    public void setUsername(String username) {

    this.username = username;

    }

     

    public String execute(){

    System.out.println(

    username + "," + password);

    //完整的登录逻辑...待续

    return "success";

    }

    }

    ok.jsp

    <%@ page language="java"

    contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="UTF-8">

    <title>成功消息</title>

    </head>

    <body>

    <h1>欢迎 ${username}</h1>

    </body>

    </html>

    struts.xml (片段)

    <package name="user"

    namespace="/user"

    extends="struts-default">

    <!--显示登录页面/user/loginForm.action-->

    <action name="loginForm">

    <result>/WEB-INF/login.jsp</result>

    </action>

    <!-- 处理登录请求/user/login.action -->

    <action name="login"

    class="com.tedu.LoginAction">

    <result name="success">

    /WEB-INF/ok.jsp

    </result>

    </action>

    </package>

    2. 域模型属性传递方式

    利用域模型打包传递表单数据, 优点: 1. 可以便捷的处理表单输入项目很多 2. 特别是在表单被项目重用时候,显得更加方便。

     

    原理:

     

    步骤: 1. 创建域模型对象 User - 添加属性 id 和 pwd - 添加bean属性访问方法 2. 在控制器中添加User属性user和get set方法 3. 在表单中的输入项目name属性值为:user.id

    代码:

    User.java

    public class User implements Serializable{

     

    private String id;

    private String pwd;

     

    public String getId() {

    return id;

    }

    public void setId(String id) {

    this.id = id;

    }

    public String getPwd() {

    return pwd;

    }

    public void setPwd(String pwd) {

    this.pwd = pwd;

    }

    @Override

    public String toString() {

    return "User [id=" + id + ", pwd=" + pwd + "]";

    }

    }

    Login2Action.java

    public class Login2Action {

    private User user;

    public void setUser(User user) {

    this.user = user;

    }

    public User getUser() {

    return user;

    }

    public String execute(){

    System.out.println(user);

    //其他登录逻辑

    return "success";

    }

    }

    login2.jsp (片段)

    <h1>登录</h1>

    <c:url var="url"

    value="/user/login2.action"/>

    <form action="${url}" method="post">

    <div>

    <label>用户名:</label>

    <input type="text" name="user.id"/>

    </div>

    <div>

    <label>密码</label>

    <input type="password" name="user.pwd">

    </div>

    <div>

    <input type="submit" value="登录">

    </div>

    </form>

     

    struts.xml(片段)

    <!-- 显示 login2.jsp -->

    <action name="login2Form">

        <result>/WEB-INF/login2.jsp</result>

    </action>

    <action name="login2"

        class="com.tedu.Login2Action">

        <result name="success">

            /WEB-INF/ok.jsp;

        </result>

    </action>

     

     

     

     

    ServletContextListener

    Servlet

    Servlet:在服务器上运行的处理HTTP请求的程序片段,不是完整程序。只能在Web容器环境中执行。Web容器已经开发好,只需要添加程序片Servlet,就可以完成Web开发。

    ServletContext 是什么?

    Context:上下文,特指运行环境

    ServletContext: 就是指Servlet的当前运行环境,如:Tomcat环境。提供了获取环境信息的方法。

    ServletContextListener

    Servlet环境有创建-运行-销毁的过程,也就是Servlet上下文的生命周期。

    ServletContextListener: 可以用于监听 Servlet环境(上下文)的创建和销毁。 - contextInitialized(): ServletContext初始化以后执行 - contextDestroyed(): ServletContext销毁以后执行

    用途: 用在系统数据初始化,系统环境初始化。比如:Spring容器环境初始化就是利用ServletContextListener接口实现的。

    Struts2

    Spring + Struts2

    Struts2 提供了 spring 整合插件 struts2-spring-plugin.jar

     

    只要将这个插件添加到/WEB-INF/lib 文件夹中,就会自动将spring整合到Struts2. 整合以后Struts2 的Action对象将由Spring容器创建

     

    1. 手工整合

    分别到Spring和Struts2网站下载jar包

    将jar包复制到/WEB-INF/lib 文件夹中

    修改web.xml文件添加Spring容器初始化监听器

    添加Spring配置文件。

    提示: 这个整合过程过于繁琐,请同学自行实验,正是这个整合过程非常繁琐,才能体现Maven这种自动化工具的优点。

    2. 利用Maven整合

    创建Maven项目,导入Struts2组件,并且配置struts.xml和web.xml

    <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-core</artifactId>

    <version>2.3.8</version>

    </dependency>

    配置struts.xml和web.xml 请参考day01.html

    找到struts2-spring组件坐标添加到Struts2项目的pom.xml,然后保存

    <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-spring-plugin</artifactId>

    <version>2.3.8</version>

    </dependency>

    注意:插件版本必须与 Struts2 的版本必须一致!!!

    Maven会自动导入插件依赖的Spring包。这是Maven最便捷的特点。

    配置web.xml,利用Spring提供的监听器在Web容器启动时候初始化Spring容器。

    <listener>

    <listener-class>

    org.springframework.web.context.ContextLoaderListener

    </listener-class>

    </listener>

    <context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>classpath:spring-*.xml</param-value>

    </context-param>

    其中context-param用于指定Spring配置文件的存储位置

    创建Spring配置文件: spring-context.xml

    注意这个配置文件要与 Spring版本配合,版本不能错误。

    启动容器进行测试。

    参考代码:

    pom.xml(片段):

    <dependencies>

    <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-core</artifactId>

    <version>2.3.24</version>

    </dependency>

    <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-spring-plugin</artifactId>

    <version>2.3.24</version>

    </dependency>

    </dependencies>

    web.xml 片段:

    <!-- 配置 Listener 用于初始化Spring容器 -->

    <!-- 在Web容器启动时候自动初始化Spring容器-->

    <listener>

    <listener-class>

    org.springframework.web.context.ContextLoaderListener

    </listener-class>

    </listener>

    <!-- 配置Spring配置文件的位置 -->

    <context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>classpath:spring-*.xml</param-value>

    </context-param>

     

    <!-- Struts2 主控制器配置 -->

    <filter>

    <filter-name>mvc</filter-name>

    <filter-class>

    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

    </filter-class>

    </filter>

    <filter-mapping>

    <filter-name>mvc</filter-name>

    <url-pattern>/*</url-pattern>

    </filter-mapping>

    struts.xml:

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

    <struts>

    </struts>

    spring-context.xml:

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"

    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"

    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"

    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"

    xmlns:jpa="http://www.springframework.org/schema/data/jpa"

    xsi:schemaLocation="

    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd

    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd

    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd

    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

    http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd

    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

     

    </beans>

    部署到Web容器测试配置结果...

    3. 编写测试案例测试整合结果

    在Spring配置文件中添加组件扫描

    添加控制器类,并且在类上添加注解

    在Struts2 配置文件中添加控制配置,其中class属性引用Spring的Bean ID

    添加测试用的视图JSP

    测试

    spring-context.xml (片段):

    <context:component-scan base-package="com.tedu"/>

    HelloAction.class

    @Controller

    @Scope("prototype") //必须是多例避免线程安全问题

    public class HelloAction {

     

    @Resource

    private DemoService demoService;

     

    private String message;

    public String getMessage(){

    return message;

    }

     

    public String execute(){

    message = demoService.hello();

    return "success";

    }

    }

    DemoService.java

    @Service

    public class DemoService {

    public String hello(){

    return "Hello World!";

    }

    }

    msg.jsp:

    <%@ page language="java"

    contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="UTF-8">

    <title>Insert title here</title>

    </head>

    <body>

    <h1>${message}</h1>

    </body>

    </html>

    struts.xml (局部):

    <package name="demo" namespace="/demo"

    extends="struts-default">

    <!-- 在有了Spring plugin 以后,action

    的class属性就可以使用Spring组件的ID了 -->

    <action name="hello"

    class="demoAction">

    <result name="success">

    /WEB-INF/msg.jsp

    </result>

    </action>

    </package>

    Result 常用类型

    Struts2 支持多种Result类型,其中常用的有: 1. dispatcher 转发 2. redirectAction 重定向到 其他Action 3. redirect 重定向到 其他URL 4. stream 流:用于处理图片或者下载 5. json:用于处理ajax请求

    转发类型是在Struts的主配置文件中定义 struts-default.xml json: 在struts2-json-plugin 插件中定义

    1. dispatcher 转发

    是默认的Result, 也是最常用的类型。

    2. redirectAction 重定向到 其他Action

    用于处理重定向结果: 详细语法请参考API手册 org.apache.struts2.dispatcher.ServletActionRedirectResult

    语法:

    <result type="redirectAction">

    hello

    </result>

     

    或者:

     

    <result type="redirectAction">

    <param name="actionName">

    hello

    </param>

    </result>

     

    其中:<param name="actionName"> 是可以省略的

     

    案例:

    <action name="test">

    <result type="redirectAction">

    <param name="actionName">

    hello

    </param>

    </result>

    </action>

    <action name="test1">

    <result type="redirectAction">

    hello

    </result>

    </action>

    测试:

    请求: http://localhost:8080/demo/test

    重定向到:http://localhost:8080/demo/hello.action

     

    请求: http://localhost:8080/demo/test1

    重定向到:http://localhost:8080/demo/hello.action

    3. redirect 重定向到 其他URL

    用于处理重定向结果: 详细语法请参考API手册 org.apache.struts2.dispatcher.ServletRedirectResult

    语法:

    <result type="redirect">

    <param name="location">http://doc.tedu.cn</param>

    </result>

    或者:

    <result type="redirect">

    http://doc.tedu.cn

    </result>

    提示: <param name="location"> 是可以省略的

    案例:

    <action name="test2">

    <result type="redirect">

    http://doc.tedu.cn

    </result>

    </action>

    <action name="test3">

    <result type="redirect">

    <param name="location">http://doc.tedu.cn</param>

    </result>

    </action>

    测试:

    请求: http://localhost:8080/demo/test2

    重定向到:http://doc.tedu.cn

     

    请求: http://localhost:8080/demo/test3

    重定向到:http://doc.tedu.cn

    Result 的 name 值不仅仅可以是success,还可以是 任何的值:

    案例:

    @Controller

    @Scope("prototype")

    public class SwitchAction {

    int num;

    public void setNum(int num) {

    this.num = num;

    }

     

    public String doSwitch(){

    return Integer.toString(num);

    }

    }

    struts.xml:

    <action name="sw"

    class="switchAction"

    method="doSwitch">

    <result name="1">

    /WEB-INF/msg.jsp

    </result>

    <result name="2" type="redirect">

    http://doc.tedu.cn

    </result>

    <result name="3" type="redirect">

    http://tmooc.cn

    </result>

    <result name="4" type="redirectAction">

    hello

    </result>

    </action>

    测试:

    请求: http://localhost:8080/demo/sw?num=1

    转发到:/WEB-INF/msg.jsp

     

    请求: http://localhost:8080/demo/sw?num=2

    重定向到:http://doc.tedu.cn

     

    请求: http://localhost:8080/demo/sw?num=3

    重定向到:http://tmooc.cn

     

    请求: http://localhost:8080/demo/sw?num=4

    重定向到:http://localhost:8080/demo/hello.action

    4. stream 流:用于处理图片或者下载

    stream result用于处理图片或者下载,具体语法请参考: org.apache.struts2.dispatcher.StreamResult

    关键语法:

    <result name="success" type="stream">

    <param name="contentType">image/jpeg</param>

    <param name="inputName">imageStream</param>

    <param name="contentDisposition">attachment;filename="document.pdf"</param>

    <param name="bufferSize">1024</param>

    </result>

    说明: - contentType: 定义媒体类型: image/png 等 - inputName: 必须是一个inputStream类型的流,用于获取发送到客户端的字节数据。如果是图片就是图片编码以后的字节流。 - contentDisposition: 可选参数,如果使用就可以强制下载保存 - bufferSize:可选参数,指定缓存区大小

    动态图片处理:

     

    原图片:

     

     

    处理后:

     

    案例:

    @Controller

    @Scope("prototype")

    public class ImageAction {

     

    private InputStream image;

    public InputStream getImage() {

    return image;

    }

     

    private String name;

    public void setName(String name) {

    this.name = name;

    }

     

    public String card() throws Exception{

    //读取图片

    //在 包(package)中读取文件

    InputStream in =

    getClass().getClassLoader()

    .getResourceAsStream("1.jpg");

    BufferedImage img = ImageIO.read(in);

    in.close();

    Graphics2D g=img.createGraphics();

     

    g.setRenderingHint(

    RenderingHints.KEY_RENDERING,

    RenderingHints.VALUE_RENDER_QUALITY);

    g.setRenderingHint(

    RenderingHints.KEY_ANTIALIASING,

    RenderingHints.VALUE_ANTIALIAS_ON);

     

    g.setColor(Color.WHITE);

    g.setFont(new Font("微软雅黑",

    Font.BOLD, 20));

    g.drawString("“"+name+"我在这里等你...”",

    5, 40);

    ByteArrayOutputStream out=

    new ByteArrayOutputStream();

    ImageIO.write(img, "png", out);

    out.close();

    byte[] data=out.toByteArray();

    image=new ByteArrayInputStream(data);

    return "success";

    }

     

    }

    struts.xml:

    <action name="card"

    class="imageAction"

    method="card">

    <result name="success"

    type="stream">

    <param name="contentType">

    image/png

    </param>

    <param name="inputName">

    image

    </param>

    <!--

    <param name="contentDisposition">

    attachment;filename="hello.png"

    </param> -->

     

    </result>

    </action>

    测试:

    请求: http://localhost:8080/demo/card?name=李鸿鹤

    结果:

     

    5. json:用于处理ajax请求

    json 不是struts默认的result类型,需要使用一个插件来支持这个类型,具体手册:org.apache.struts2.json.JSONResult

    用两种使用方式: 1. 将Action的全部属性发送到客户端 - <result name="success" type="json"></result> 2. 将Action的一个属性发送到客户端(最常用) -<result name="success"type="json"> - <param name="root">value</param> - </result> - 其中value是Action的属性名 - 可以将value类型定义为集合,这样就可以将对各数据发送到客户端了。

    提示:json返回结果必须使用 struts2-json-plugin 插件支持,必须先导入json插件。

    案例1: 返回Action的全部属性:

    pom.xml (局部): 导入struts2-json-plugin 插件

    <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-json-plugin</artifactId>

    <version>2.3.8</version>

    </dependency>

    JsonAction.java:

    @Controller

    public class JsonAction {

    private int id;

    public int getId() {

    return id;

    }

    private String message;

    public String getMessage() {

    return message;

    }

    public String execute(){

    id = 100;

    message="Hello!";

    return "success";

    }

    }

    struts.xml(局部):

    <!-- json-default 来自struts2-json-plugin.jar -->

    <package name="jsondemo" namespace="/json" extends="json-default">

    <action name="demo" class="jsonAction">

    <result name="success" type="json">

    </result>

    </action>

    </package>

    测试(JsonAction全部属性值):

    请求:/json/demo.action

    结果:

    {"id":100;"message":"Hello!"}

    案例2: 将Action的一个属性发送到客户端:

    JsonAction.java:

    public class JsonAction {

    private int id;

    public int getId() {

    return id;

    }

    private String message;

    public String getMessage() {

    return message;

    }

    //用于保存,向用户发送的JSON数据

    private Map<String, Object> value =

    new HashMap<String, Object>();

    public Map<String, Object> getValue() {

    return value;

    }

    public String execute(){

    value.put("name", "Tom");

    value.put("age", 100);

    value.put("message", "你吃了吗?");

    value.put("error", "吃到吐!");

    //....

    id = 100;

    message="Hello!";

    return "success";

    }

    }

    struts.xml(局部):

    <package name="jsondemo" namespace="/json" extends="json-default">

    <action name="demo" class="jsonAction">

    <result name="success" type="json">

    <!-- value是JsonAction中需要向客户端发送的数据 -->

    <param name="root">value</param>

    </result>

    </action>

    </package>

    测试:

    请求:/json/demo.action

    结果:

    {"name":"Tom","message":"你吃了吗?","error":"吃到吐!","age":100}

     

     

    拦截器

    Struts2 也提供了拦截器功能,Struts2的很多默认功能也是通过其内部的拦截器实现的。

     

    拦截器原理:

     

    使用拦截器:

    DemoInterceptor.java:

    public class DemoInterceptor implements Interceptor {

    public void destroy() {

    }

    public void init() {

    }

    public String intercept(ActionInvocation in) throws Exception {

    System.out.println("开始拦截");

    //执行被拦截的 Action

    in.invoke();

    System.out.println("结束拦截");

    return null;

    }

    }

    struts.xml(局部):

    <!-- 引入拦截器 -->

    <interceptors>

    <interceptor name="demo"

    class="com.tedu.web.DemoInterceptor"/>

    </interceptors>

     

    <action name="hello"

    class="helloAction">

    <!-- 声明当前Action被demo拦截 -->

    <interceptor-ref name="demo"/>

    <result name="success">

    /WEB-INF/msg.jsp

    </result>

    </action>

    利用拦截器处理异常:

    创建拦截器类:

    public class ExceptionInterceptor

    extends AbstractInterceptor{

     

    public String intercept(

    ActionInvocation invocation)

    throws Exception {

    try {

    String val=invocation.invoke();

    System.out.println("正常");

    return val;

    } catch (Exception e) {

    e.printStackTrace();

    JsonResult result=new JsonResult(e);

    Object action = invocation.getAction();

    if(action instanceof JsonAction){

    ((JsonAction)action).setJsonResult(result);

    }

    System.out.println("错误");

    return "error";

    }

    }

    }

    继承AbstractInterceptor可以简单代码编写

    配置拦截器:

    <interceptors >

    <interceptor name="exceptionInc"

    class="cn.tedu.note.web.ExceptionInterceptor"/>

     

    <interceptor-stack name="expStack">

    <interceptor-ref name="basicStack"></interceptor-ref>

    <interceptor-ref name="exceptionInc"></interceptor-ref>

    </interceptor-stack>

    </interceptors>

     

     

    <action name="login"

    class="cn.tedu.note.action.LoginAction"

    method="execute">

     

    <interceptor-ref name="expStack"/>

     

    <result name="success"

    type="json">

    <param name="root">

    jsonResult

    </param>

    </result>

    <result name="error"

    type="json">

    <param name="root">

    jsonResult

    </param>

    </result>

    </action>

    提示: 必须带上原有的拦截器栈basicStack,否则原有Struts2的功能失效。

    测试: ...

     

    ValueStack

    关键点:

    Struts中用于共享数据的数据结构

    控制器到JSP页面之间共享数据。

    拦截器之间,拦截器和控制器JSP之间

    ValueStack结构,两个区域

    Contents(内容):数据共享区域

    Context(上下文环境):当前环境信息

    存储数据:

    Action 本身自动存储在 Contents, 可以直接获取Action

    可以在Action中调用API向ValueStack中添加数据。

    ActionContext ctx = ActionContext.getContext();

    ctx.getValueStack().push(obj);

    不常见。

    Contents中的数据是顺序查询的

    Context区域:是一个Map,使用#key读取

    OGNL: 不用代码,使用表达式调用对象的方法。

    与EL的作用雷同

    Struts2 拦截了EL,底层就是ValueStack

    提示: 在Struts2中ValueStack是软件的消息中心的作用。软件的数据和相关环境信息都缓存在这个对象中。其作用于JSP中的 pageContext 类似。

    JSP 页面中使用 <s:debug/> 标签可以展示 ValueStack 的内容

     

    OGNL 表达式

    OGNL 可以在网页 struts 标签中使用,在Struts2中用于读写ValueStack的数据。

     

    读取root区域数据

    从栈顶到栈底逐一搜索 Bean 属性,找到属性就输出

    读写 context 区域使用 #key 的方式查找

    #session.loginName

    提示:OGNL与ValueStack配合可以从控制器向页面传递数据。

    ValueStack与EL

    Struts2 中的拦截了EL表达式,使其从ValueStack中获取数据,也就是说使用EL就可以很好的访问ValueStack.

    案例:

    DemoAction.java

    @Controller

    public class DemoAction {

     

    String message;

    public String getMessage() {

    return message;

    }

     

    public String test(){

    ActionContext context =

    ActionContext.getContext();

    ValueStack stack=context.getValueStack();

     

    Person p = new Person(

    1, "Jerry", "Hello Jerry");

    //将数据添加到值栈中

    stack.push(p);

     

    context.getSession()

    .put("loginName", "Robin");

     

    message = "demo";

    System.out.println(

    "Demo Action test()");

    return "success";

    }

    }

    Person.class

    public class Person {

    int id;

    String pname;

    String message;

    public Person() {

    }

     

    public Person(int id, String pname, String message) {

    super();

    this.id = id;

    this.pname = pname;

    this.message = message;

    }

     

     

    public int getId() {

    return id;

    }

    public void setId(int id) {

    this.id = id;

    }

    public String getPname() {

    return pname;

    }

    public void setPname(String pname) {

    this.pname = pname;

    }

    public String getMessage() {

    return message;

    }

    public void setMessage(String message) {

    this.message = message;

    }

    }

    struts.xml(局部)

    <package name="test"

    namespace="/test"

    extends="json-default">

    <action name="demo"

    class="demoAction"

    method="test">

    <result name="success">

    /WEB-INF/msg.jsp

    </result>

    </action>

    </package>

    msg.jsp

    <%@ page language="java"

    contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

    <!-- 引入struts2 标签库 -->

    <%@taglib prefix="s" uri="/struts-tags" %>

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="UTF-8">

    <title></title>

    </head>

    <body>

    <h1>test</h1>

    <!-- 利用OGNL表达式读取值栈中的数据 -->

    <s:property value="message"/> <br>

    <s:property value="#session.loginName"/><br>

    <!-- 利用EL表达式读取值栈中的数据 -->

    ${message} <br>

    ${loginName}

    <!-- s:debug 标签可以输出 ValueStack 中的数据 -->

    <s:debug></s:debug>

    </body>

    </html>

    Hibernate (冬眠)

    将对象存储到关系型数据库中。将对象与关系数据的行对应起来。 ORM 对象关系映射。只要操作对象就自动操作数据库。

    使用Hibernate

    步骤:

    导入包

    创建配置文件

    配置数据库连接

    配置实体对象与表的映射关系。

    创建实体对象。

    创建 Session

    调用 Session 的方法

    CRDU方法——增删改查

    C 创建 R 寻回(查找)D 删除 U更新

    ### 1. 导入Hibernate的相关包

    由于是开源软件,其包的依赖关系不够完善,有的Hibernate 版本在导入以后会出现 ClassNotFound 异常。请尝试更换其他版本。

    Hibernate pom.xml 坐标:

    <dependency>

    <groupId>org.hibernate</groupId>

    <artifactId>hibernate-core</artifactId>

    <version>3.6.9.Final</version>

    </dependency>

    <dependency>

    <groupId>javassist</groupId>

    <artifactId>javassist</artifactId>

    <version>3.8.0.GA</version>

    </dependency>

    2. 导入数据库的驱动程序

    JDBC 驱动 pom.xml 坐标

    <dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    <version>5.1.36</version>

    </dependency>

    添加Hibernate主配置文件

    hibernate.cfg.xml:

    <?xml version='1.0' encoding='UTF-8'?>

    <!DOCTYPE hibernate-configuration PUBLIC

    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>

     

    <session-factory>

    <property name="dialect">

    org.hibernate.dialect.MySQLDialect

    </property>

    <property name="connection.url">

    jdbc:mysql://localhost:3306/cloud_note?useUnicode=true&characterEncoding=utf8

    </property>

    <property name="connection.username">root</property>

    <property name="connection.password">123456</property>

    <property name="connection.driver_class">

    com.mysql.jdbc.Driver

    </property>

     

    <!-- 加载映射描述文件 -->

    <mapping resource="User.hbm.xml" />

     

    </session-factory>

     

    </hibernate-configuration>

    4. 添加Hibernate映射配置文件

    User.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>

    <!DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping>

    <class name="com.tedu.entity.User"

    table="cn_user">

    <!-- 定义主键映射 -->

    <id name="id" column="cn_user_id"

    type="string">

    </id>

    <!-- 定义非主键映射 -->

    <property name="name"

    column="cn_user_name"

    type="string">

    </property>

    <property name="password"

    column="cn_user_password"

    type="string">

    </property>

    <property name="token"

    column="cn_user_token"

    type="string">

    </property>

    <property name="nick"

    column="cn_user_nick"

    type="string">

    </property>

    </class>

    </hibernate-mapping>

    5. 添加实体类

    注意:建议有ID的实体类实现 equals 和 hashCode 方法! 使用Eclipse生成即可。

    User.java

    package com.tedu.entity;

     

    import java.io.Serializable;

     

    public class User implements Serializable{

    private String id;

    private String name;

    private String password;

    private String token;

    private String nick;

     

    public User() {

    }

     

    public User(String id, String name, String password, String token, String nick) {

    super();

    this.id = id;

    this.name = name;

    this.password = password;

    this.token = token;

    this.nick = nick;

    }

     

    public String getId() {

    return id;

    }

     

    public void setId(String id) {

    this.id = id;

    }

     

    public String getName() {

    return name;

    }

     

    public void setName(String name) {

    this.name = name;

    }

     

    public String getPassword() {

    return password;

    }

     

    public void setPassword(String password) {

    this.password = password;

    }

     

    public String getToken() {

    return token;

    }

     

    public void setToken(String token) {

    this.token = token;

    }

     

    public String getNick() {

    return nick;

    }

     

    public void setNick(String nick) {

    this.nick = nick;

    }

     

    @Override

    public String toString() {

    return "User [id=" + id + ", name=" + name + ", password=" + password + ", token=" + token + ", nick=" + nick

    + "]";

    }

     

    @Override

    public int hashCode() {

    final int prime = 31;

    int result = 1;

    result = prime * result + ((id == null) ? 0 : id.hashCode());

    return result;

    }

     

    @Override

    public boolean equals(Object obj) {

    if (this == obj)

    return true;

    if (obj == null)

    return false;

    if (getClass() != obj.getClass())

    return false;

    User other = (User) obj;

    if (id == null) {

    if (other.id != null)

    return false;

    } else if (!id.equals(other.id))

    return false;

    return true;

    }

     

    }

    6. 调用Hibernate API 就可以自动生成SQL访问数据库了

    @Test

    public void test1(){

    Configuration cfg = new Configuration();

    //读取数据库连接参数

    cfg.configure("hibernate.cfg.xml");

    SessionFactory factory = cfg.buildSessionFactory();

    //获取Session对象

    Session session = factory.openSession();

    //session 可以自动生成SQL查询DB

    String id = "022ada2e14f544dbb49468b7cb6f3d42";

    User u=(User)session.get( User.class, id);

    System.out.println(u);

    session.close();

    }

    测试CURD方法

    案例:

    public class TestCase {

     

    SessionFactory factory;

    @Before

    public void init(){

    Configuration cfg=new Configuration();

    cfg.configure("hibernate.cfg.xml");

    factory=cfg.buildSessionFactory();

    }

    @Test

    @Ignore

    public void testGetUser()

    throws Exception {

    Session session=factory.openSession();

    String id="39295a3d-cc9b-42b4-b206-a2e7fab7e77c";

    User user=(User)session.get(User.class, id);

    System.out.println(user);

     

    //session.save(arg0);//insert

    //session.update(arg0);//update

    //session.delete(arg0);//delete

    }

     

    //@Test

    public void testSaveUser(){

    Session session = null;

    Transaction tx = null;

    try {

    session = factory.openSession();

    tx=session.beginTransaction();

    User u = new User("123",

    "Andy", "123", "", "Andy");

    session.save(u);

    User one = (User)session.get(

    User.class, "123");

    System.out.println(one);

    tx.commit();

    } catch (Exception e) {

    e.printStackTrace();

    tx.rollback();

    }finally {

    session.close();

    }

    }

     

    @Test

    public void testUpdateUser(){

    Session session = null;

    Transaction tx = null;

    try {

    session = factory.openSession();

    tx=session.beginTransaction();

    User u = (User)session.get(

    User.class, "123");

    System.out.println(u);

    //session.evict(u);

    u.setName("John");

    session.update(u);

    u = (User)session.get(

    User.class, "123");

    System.out.println(u);

    tx.commit();

    } catch (Exception e) {

    e.printStackTrace();

    tx.rollback();

    }finally {

    session.close();

    }

    }

    //@Test

    public void testDeleteUser(){

    Session session = null;

    Transaction tx = null;

    try {

    session = factory.openSession();

    tx=session.beginTransaction();

    User u = (User)session.get(

    User.class, "123");

    System.out.println(u);

    u.setName("Wang");

    session.delete(u);

    u = (User)session.get(

    User.class, "123");

    System.out.println(u);

    //session.evict(arg0);

    tx.commit();

    } catch (Exception e) {

    e.printStackTrace();

    tx.rollback();

    }finally {

    session.close();

    }

    }

     

    }

    对象状态

    被Hibernate管理的实体对象有3种状态:

    临时状态

    持久状态

    游离状态

     

    1. 临时状态

    刚刚创建的对象或者被删除的对象,数据库中没有对应的记录,这时对象的状态为 临时状态。

    调用了 save 或者 saveOrUpdate方法以后, 对象将被保存到数据库中,对象状态将转换为持久状态.

    案例 向数据库中添加数据:

    @Test

    public void testSaveTeacher(){

    Session session=openSession();

    Transaction t=session.beginTransaction();

    t.begin();

    Teacher tom = new Teacher("Tom");

    System.out.println(tom);

    session.save(tom);

    System.out.println(tom);

    t.commit();

    session.close();

    }

    2. 持久状态

    保存以后的对象或者从数据库中获取的对象其状态是持久状态,持久状态下改变对象的数据将生成相应的sql语句,将对象的状态保存到数据库中。

    案例,改变对象的属性:

    @Test

    //更新属性实验

    public void testUpdateName(){

    Session s = openSession();

    Transaction t=s.beginTransaction();

    t.begin();

    Student stu =

    (Student)s.get(Student.class, 1);

    System.out.println(stu);

    //持久状态:更新对象属性会自动更新数据库

    stu.setName("M1");

    stu.setName("M1");

    stu.setName("Mac");

    System.out.println(stu);

    t.commit();

    s.close();

    }

    3. 游离状态

    对称被从Session的缓存中清理出来对象状态变成游离状态,游离状态对象脱离于数据库的联系,更改对象的属性,不再影响数据库,如果需要将游离状态的对象数据更新到数据库可以调用 update 方法,update方法执行以后,对象又还原回 持久状态,并且将已经更改的属性更新到数据库。

    案例:

    更新游离更新游离状态对象的属性,不影响数据库的数据

    @Test

    //游离状态测试

    public void testObject(){

    Session s = openSession();

    Transaction t=s.beginTransaction();

    t.begin();

    //get获取的对象是持久状态的

    Student stu=(Student)s.get(

    Student.class, 2);

    //从session缓存中将stu踢出,离开

    //session对象变成游离状态,与数据库

    //脱离联系

    System.out.println(stu);

    s.clear();//将session缓存的全部对象踢出

    //s.evict(stu);//踢出一个对象

    //脱离持久状态的对象更新属性不再改变

    //数据库的值了

    stu.setName("Andy");

    System.out.println(stu);

    t.commit();

    s.close();

    }

    案例:

    将游离状态状态对象的属性更新到数据库:

    @Test

    public void testUpdate(){

    Session s=openSession();

    Transaction t=s.beginTransaction();

    t.begin();

    Student stu=(Student)s.get(

    Student.class, 3);

    System.out.println(stu);

    s.evict(stu);//使stu变成游离状态

    stu.setName("Nemo");

    System.out.println(stu);

    s.update(stu);//update使stu从新返回持久状态

    t.commit();

    s.close();

    }

    Spring 与 Hibernate 整合

    整合的目的: 将Hibernate的对象交给Spring容器,由Spring容器进行管理。

    步骤:

    导入Hibernate

    导入数据库驱动

    数据连接池:DBCP C3P0 阿里

    导入Spring

    导入Spring-ORM 是Spring整合Hibernate的扩展插件

    配置Spring

    配置数据源(连接池)

    配置Hibernate SessionFactory

    Hibernate的参数配置进去

    配置 事务管理

    配置 HibernateTemplate,封装了Hibernate提供CRUD方法

    编写数据访问层(DAO)接口

    实现DAO

    注入HibernateTemplate,利用HibernateTemplate实现CRUD

    测试DAO

    1. 导入Hibernate

    分别导入 Hibernate 和 JDBC Driver 以及 连接池C3p0

    提示:连接池可以使用 DBCP C3P0 或者阿里云的 druid

    pom.xml:

    <dependency>

    <groupId>org.hibernate</groupId>

    <artifactId>hibernate-core</artifactId>

    <version>3.6.9.Final</version>

    </dependency>

    <dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    <version>5.1.36</version>

    </dependency>

    <dependency>

    <groupId>c3p0</groupId>

    <artifactId>c3p0</artifactId>

    <version>0.9.1</version>

    </dependency>

    2. 导入Spring

    Spring 并不是最新版本最好,要与Hibernate的版本配合才行。

    Spring 与 Hibernate 的版本配合情况,以实际测试结果为准。

    pom.xml

    <dependency>

    <groupId>org.springframework</groupId>

    <artifactId>spring-core</artifactId>

    <version>3.0.5.RELEASE</version>

    </dependency>

    3. 导入Spring-ORM 是Spring整合Hibernate的扩展插件

    这个插件是Spring提供的, 用于在Spring中整合支持Hibernate。

    提示:spring-orm 的版本要与Spring-core的版本一致

    pom.xml:

    <dependency>

    <groupId>org.springframework</groupId>

    <artifactId>spring-orm</artifactId>

    <version>3.0.5.RELEASE</version>

    </dependency>

    4. 配置Spring

    利用Spring的配置文件,配置Hibernate 相关组件,将Hibernate交给Spring容器进行管理。

    添加Spring配置文件: spring-context.xml

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"

    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"

    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"

    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"

    xmlns:jpa="http://www.springframework.org/schema/data/jpa"

    xsi:schemaLocation="

    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd

    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd

    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd

    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

    http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd

    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

     

    </beans>

    配置数据源:

    <bean id="dataSource"

    class="com.mchange.v2.c3p0.ComboPooledDataSource">

    <property name="driverClass"

    value="com.mysql.jdbc.Driver" />

    <property name="jdbcUrl"

    value="jdbc:mysql://localhost:3306/cloud_note" />

    <property name="user" value="root"/>

    <property name="password" value="123456" />

    <property name="maxPoolSize" value="10" />

    </bean>

    提示:不同厂商提供的数据源参数是有区别的,以相关的手册为准。

    配置Hibernate SessionFactory

    <!-- 配置Hibernate SessionFactory -->

    <!-- 其创建的Bean类型是SessionFactory -->

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

    <!-- 连接到的数据库 -->

    <property name="dataSource"

    ref="dataSource" />

    <!-- Hibernate 参数 -->

    <property name="hibernateProperties">

    <props>

    <prop key="hibernate.dialect">

    org.hibernate.dialect.MySQLDialect

    </prop>

    <prop key="hibernate.show_sql">true</prop>

    <prop key="hibernate.format_sql">true</prop>

    </props>

    </property>

    <!-- 映射文件参数 -->

    <property name="mappingLocations">

    <list>

    <value>classpath:User.hbm.xml</value>

    <!--

    <value>classpath:Book.hbm.xml</value>

    -->

    </list>

    </property>

    </bean>

    提示: LocalSessionFactoryBean 是Spring提供的工厂Bean,这个Bean会创建 SesisonFactory对象。

    配置 事务管理

    <!-- 配置事务管理器 -->

    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

    <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    <!-- 打开注解驱动的事务管理 -->

    <tx:annotation-driven transaction-manager="txManager"/>

    提示:利用事务管理器,就可以将Hibernate的事务托管到Spring,利用Spring提供的注解就可以管理事务的开启提交和关闭。可以大大简化编码。

    配置 HibernateTemplate,template封装了Hibernate提供CRUD方法,用法比Hibernate Session 更加简便。

    <!-- 配置Hibernate 模板Bean -->

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">

    <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    开启组件扫描支持:

    <context:component-scan base-package="com.tedu"/>

    注意:要扫描具体的项目包com.tedu,不要扫描com包!com包包含的子包太多了!!!

    5. 编写数据访问层(DAO)接口

    编写实体类 User

    public class User implements Serializable{

     

    private static final long serialVersionUID = 4406629431472824631L;

     

    private String id;

    private String name;

    private String password;

    private String token;

    private String nick;

     

    public User() {

    }

     

    public User(String id, String name, String password, String token, String nick) {

    this.id = id;

    this.name = name;

    this.password = password;

    this.token = token;

    this.nick = nick;

    }

     

    public String getId() {

    return id;

    }

     

    public void setId(String id) {

    this.id = id;

    }

     

    public String getName() {

    return name;

    }

     

    public void setName(String name) {

    this.name = name;

    }

     

    public String getPassword() {

    return password;

    }

     

    public void setPassword(String password) {

    this.password = password;

    }

     

    public String getToken() {

    return token;

    }

     

    public void setToken(String token) {

    this.token = token;

    }

     

    public String getNick() {

    return nick;

    }

     

    public void setNick(String nick) {

    this.nick = nick;

    }

     

    @Override

    public String toString() {

    return "User [id=" + id + ", name=" + name + ", password=" + password + ", token=" + token + ", nick=" + nick + "]";

    }

     

    @Override

    public int hashCode() {

    final int prime = 31;

    int result = 1;

    result = prime * result + ((id == null) ? 0 : id.hashCode());

    return result;

    }

     

    @Override

    public boolean equals(Object obj) {

    if (this == obj)

    return true;

    if (obj == null)

    return false;

    if (getClass() != obj.getClass())

    return false;

    User other = (User) obj;

    if (id == null) {

    if (other.id != null)

    return false;

    } else if (!id.equals(other.id))

    return false;

    return true;

    }

    }

    编写实体类的 DAO 接口,声明实体CRUD方法

    public interface UserDao {

    void save(User user);

    void delete(User user);

    void update(User user);

    User findById(String id);

    List<User> findAll();

    User findByName(String name);

    }

    6. 实现DAO

    利用Spring注解注入 hibernateTempalet 对象,就可以非常便捷的实现DAO接口。hibernateTempalet封装了Hibernate提供的CRUD功能。

    @Repository("userDao")

    @Transactional

    public class HibernateUserDao implements UserDao {

    @Autowired

    private HibernateTemplate hibernateTemplate;

     

    public void save(User user) {

    hibernateTemplate.save(user);

    }

     

    public void delete(User user) {

    hibernateTemplate.delete(user);

    }

     

    public void update(User user) {

    hibernateTemplate.update(user);

    }

     

    @SuppressWarnings("rawtypes")

    public User findById(String id) {

    String hql = "from User where id=?";

    List list = hibernateTemplate.find(hql, id);

    if(list.size()==0){

    return null;

    }else{

    return (User)list.get(0);

    }

    }

     

    @SuppressWarnings("unchecked")

    public List<User> findAll() {

    String hql = "from User";

    List<User> list= hibernateTemplate.find(hql);

    return list;

    }

     

    @SuppressWarnings("rawtypes")

    public User findByName(String name) {

    String hql= "from User where name=:name";

    List list=hibernateTemplate.findByNamedParam(hql, "name", name);

    if(list.isEmpty()){

    return null;

    }

    return (User)list.get(0);

    }

     

    }

    7. 测试 DAO

    导入 JUnit API

    <dependency>

    <groupId>junit</groupId>

    <artifactId>junit</artifactId>

    <version>4.12</version>

    </dependency>

    添加测试类:

    public class TestCase {

     

    ApplicationContext ctx;

     

    @Before

    public void init(){

    ctx=new ClassPathXmlApplicationContext(

    "spring-context.xml");

    }

     

    @Test

    public void testFindByName(){

    UserDao dao =

    ctx.getBean("userDao", UserDao.class);

    User user = dao.findByName("tedu");

    System.out.println(user);

    }

    }

     

    测试! Good Luck!!

     

     

    Hibernate

    ORM 框架:将对象映射存储数据库中的行。

    Hibernate: 面向对象,已对象的方式访问数据库,复杂 MyBatis:面向数据库,从数据库角度考虑问题,轻量简单

    Spring 与 Hibernate 整合

    整合的目的: 将Hibernate的对象交给Spring容器,由Spring容器进行管理。

    步骤:

    导入Hibernate

    导入数据库驱动

    数据连接池:DBCP C3P0 阿里

    导入Spring

    导入Spring-ORM 是Spring整合Hibernate的扩展插件

    配置Spring

    配置数据源(连接池)

    配置Hibernate SessionFactory

    Hibernate的参数配置进去

    配置 事务管理

    配置 HibernateTemplate,封装了Hibernate提供CRUD方法

    编写数据访问层(DAO)接口

    实现DAO

    注入HibernateTemplate,利用HibernateTemplate实现CRUD

    测试DAO

    1. 导入Hibernate

    分别导入 Hibernate 和 JDBC Driver 以及 连接池C3p0

    提示:连接池可以使用 DBCP C3P0 或者阿里云的 druid

    pom.xml:

    <dependency>

    <groupId>org.hibernate</groupId>

    <artifactId>hibernate-core</artifactId>

    <version>3.6.9.Final</version>

    </dependency>

    <dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    <version>5.1.36</version>

    </dependency>

    <dependency>

    <groupId>c3p0</groupId>

    <artifactId>c3p0</artifactId>

    <version>0.9.1</version>

    </dependency>

    2. 导入Spring

    Spring 并不是最新版本最好,要与Hibernate的版本配合才行。

    Spring 与 Hibernate 的版本配合情况,以实际测试结果为准。

    pom.xml

    <dependency>

    <groupId>org.springframework</groupId>

    <artifactId>spring-core</artifactId>

    <version>3.0.5.RELEASE</version>

    </dependency>

    3. 导入Spring-ORM 是Spring整合Hibernate的扩展插件

    这个插件是Spring提供的, 用于在Spring中整合支持Hibernate。

    提示:spring-orm 的版本要与Spring-core的版本一致

    pom.xml:

    <dependency>

    <groupId>org.springframework</groupId>

    <artifactId>spring-orm</artifactId>

    <version>3.0.5.RELEASE</version>

    </dependency>

    4. 配置Spring

    利用Spring的配置文件,配置Hibernate 相关组件,将Hibernate交给Spring容器进行管理。

    添加Spring配置文件: spring-context.xml

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"

    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"

    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"

    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"

    xmlns:jpa="http://www.springframework.org/schema/data/jpa"

    xsi:schemaLocation="

    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd

    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd

    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd

    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

    http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd

    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

     

    </beans>

    配置数据源:

    <bean id="dataSource"

    class="com.mchange.v2.c3p0.ComboPooledDataSource">

    <property name="driverClass"

    value="com.mysql.jdbc.Driver" />

    <property name="jdbcUrl"

    value="jdbc:mysql://localhost:3306/cloud_note" />

    <property name="user" value="root"/>

    <property name="password" value="123456" />

    <property name="maxPoolSize" value="10" />

    </bean>

    提示:不同厂商提供的数据源参数是有区别的,以相关的手册为准。

    配置Hibernate SessionFactory

    <!-- 配置Hibernate SessionFactory -->

    <!-- 其创建的Bean类型是SessionFactory -->

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

    <!-- 连接到的数据库 -->

    <property name="dataSource"

    ref="dataSource" />

    <!-- Hibernate 参数 -->

    <property name="hibernateProperties">

    <props>

    <prop key="hibernate.dialect">

    org.hibernate.dialect.MySQLDialect

    </prop>

    <prop key="hibernate.show_sql">true</prop>

    <prop key="hibernate.format_sql">true</prop>

    </props>

    </property>

    <!-- 映射文件参数 -->

    <property name="mappingLocations">

    <list>

    <value>classpath:User.hbm.xml</value>

    <!--

    <value>classpath:Book.hbm.xml</value>

    -->

    </list>

    </property>

    </bean>

    提示: LocalSessionFactoryBean 是Spring提供的工厂Bean,这个Bean会创建 SesisonFactory对象。

    配置 事务管理

    <!-- 配置事务管理器 -->

    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

    <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    <!-- 打开注解驱动的事务管理 -->

    <tx:annotation-driven transaction-manager="txManager"/>

    提示:利用事务管理器,就可以将Hibernate的事务托管到Spring,利用Spring提供的注解就可以管理事务的开启提交和关闭。可以大大简化编码。

    配置 HibernateTemplate,template封装了Hibernate提供CRUD方法,用法比Hibernate Session 更加简便。

    <!-- 配置Hibernate 模板Bean -->

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">

    <property name="sessionFactory" ref="sessionFactory" />

    </bean>

    开启组件扫描支持:

    <context:component-scan base-package="com.tedu"/>

    注意:要扫描具体的项目包com.tedu,不要扫描com包!com包包含的子包太多了!!!

    5. 编写数据访问层(DAO)接口

    编写实体类 User

    public class User implements Serializable{

     

    private static final long serialVersionUID = 4406629431472824631L;

     

    private String id;

    private String name;

    private String password;

    private String token;

    private String nick;

     

    public User() {

    }

     

    public User(String id, String name, String password, String token, String nick) {

    this.id = id;

    this.name = name;

    this.password = password;

    this.token = token;

    this.nick = nick;

    }

     

    public String getId() {

    return id;

    }

     

    public void setId(String id) {

    this.id = id;

    }

     

    public String getName() {

    return name;

    }

     

    public void setName(String name) {

    this.name = name;

    }

     

    public String getPassword() {

    return password;

    }

     

    public void setPassword(String password) {

    this.password = password;

    }

     

    public String getToken() {

    return token;

    }

     

    public void setToken(String token) {

    this.token = token;

    }

     

    public String getNick() {

    return nick;

    }

     

    public void setNick(String nick) {

    this.nick = nick;

    }

     

    @Override

    public String toString() {

    return "User [id=" + id + ", name=" + name + ", password=" + password + ", token=" + token + ", nick=" + nick + "]";

    }

     

    @Override

    public int hashCode() {

    final int prime = 31;

    int result = 1;

    result = prime * result + ((id == null) ? 0 : id.hashCode());

    return result;

    }

     

    @Override

    public boolean equals(Object obj) {

    if (this == obj)

    return true;

    if (obj == null)

    return false;

    if (getClass() != obj.getClass())

    return false;

    User other = (User) obj;

    if (id == null) {

    if (other.id != null)

    return false;

    } else if (!id.equals(other.id))

    return false;

    return true;

    }

    }

    编写实体类的 DAO 接口,声明实体CRUD方法

    public interface UserDao {

    void save(User user);

    void delete(User user);

    void update(User user);

    User findById(String id);

    List<User> findAll();

    User findByName(String name);

    }

    6. 实现DAO

    利用Spring注解注入 hibernateTempalet 对象,就可以非常便捷的实现DAO接口。hibernateTempalet封装了Hibernate提供的CRUD功能。

    @Repository("userDao")

    @Transactional

    public class HibernateUserDao implements UserDao {

    @Autowired

    private HibernateTemplate hibernateTemplate;

     

    public void save(User user) {

    hibernateTemplate.save(user);

    }

     

    public void delete(User user) {

    hibernateTemplate.delete(user);

    }

     

    public void update(User user) {

    hibernateTemplate.update(user);

    }

     

    @SuppressWarnings("rawtypes")

    public User findById(String id) {

    String hql = "from User where id=?";

    List list = hibernateTemplate.find(hql, id);

    if(list.size()==0){

    return null;

    }else{

    return (User)list.get(0);

    }

    }

     

    @SuppressWarnings("unchecked")

    public List<User> findAll() {

    String hql = "from User";

    List<User> list= hibernateTemplate.find(hql);

    return list;

    }

     

    @SuppressWarnings("rawtypes")

    public User findByName(String name) {

    String hql= "from User where name=:name";

    List list=hibernateTemplate.findByNamedParam(hql, "name", name);

    if(list.isEmpty()){

    return null;

    }

    return (User)list.get(0);

    }

     

    }

    7. 测试 DAO

    导入 JUnit API

    <dependency>

    <groupId>junit</groupId>

    <artifactId>junit</artifactId>

    <version>4.12</version>

    </dependency>

    添加测试类:

    public class TestCase {

     

    ApplicationContext ctx;

     

    @Before

    public void init(){

    ctx=new ClassPathXmlApplicationContext(

    "spring-context.xml");

    }

     

    @Test

    public void testFindByName(){

    UserDao dao =

    ctx.getBean("userDao", UserDao.class);

    User user = dao.findByName("tedu");

    System.out.println(user);

    }

    }

    测试! Good Luck!!

    添加软件的业务层

    步骤:

    添加业务层接口,定义软件的业务功能

    可能会根据业务的需要定义业务异常

    实现业务方法

    业务数据从数据层DAO中获取。

    需要一些工具方法

    测试业务接口

    1. 添加业务层接口

    定义软件的业务功能:

    public interface UserService {

    /**

    * 登录功能

    * @param username 用户名

    * @param password 密码

    * @return 登录成功返回用户信息

    * @throws NameOrPwdException 登录失败

    */

    User login(String username, String password) throws NameOrPwdException;

    /**

    * 显示全部系统用户

    * @return 系统用户列表

    */

    List<User> list();

    }

    定义业务异常:

    public class NameOrPwdException extends Exception {

     

    private static final long serialVersionUID = -3976559209959446209L;

     

    public NameOrPwdException() {

    }

    public NameOrPwdException(String message) {

    super(message);

    }

    public NameOrPwdException(Throwable cause) {

    super(cause);

    }

    public NameOrPwdException(String message, Throwable cause) {

    super(message, cause);

    }

    public NameOrPwdException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {

    super(message, cause, enableSuppression, writableStackTrace);

    }

    }

    2. 实现业务方法

    实现业务方法,要点

    注入数据访问层DAO

    务必开启事务处理

    最后对方法的入口参数进行检验,提高软件的健壮性。

    UserServiceImpl.java

    //在Spring容器中注册Bean userService

    @Service("userService")

    @Transactional

    public class UserServiceImpl

    implements UserService{

     

    @Autowired

    private UserDao userDao;

     

    @Transactional(readOnly=true)

    public User login(

    String username, String password)

    throws NameOrPwdException {

    if(username==null || username.trim().isEmpty()){

    throw new NameOrPwdException("用户名不能空");

    }

    if(username.length()>20){

    throw new NameOrPwdException("用户名太长了!");

    }

    if(password==null || password.trim().isEmpty()){

    throw new NameOrPwdException("密码不能为空");

    }

    User someone = userDao.findByName(username);

    if(someone==null){

    throw new NameOrPwdException("用户名或密码错误");

    }

    String pwd=MD5Util.md5(password);

    if(someone.getPassword().equals(pwd)){

    return someone;

    }

    throw new NameOrPwdException("用户名或密码错误");

    }

     

    @Transactional(readOnly=true)

    public List<User> list() {

    return userDao.findAll();

    }

    }

    导入编码工具包:

    <dependency>

    <groupId>commons-codec</groupId>

    <artifactId>commons-codec</artifactId>

    <version>1.10</version>

    </dependency>

    添加MD5工具类:

    public class MD5Util {

    public static String md5(String str){

    try {

    MessageDigest digest =

    MessageDigest.getInstance("MD5");

    byte[] data=str.getBytes("utf-8");

    byte[] md5=digest.digest(data);

    return Base64.encodeBase64String(md5);

    } catch (NoSuchAlgorithmException e) {

    e.printStackTrace();

    throw new RuntimeException(e);

    } catch (UnsupportedEncodingException e) {

    e.printStackTrace();

    throw new RuntimeException(e);

    }

     

    }

    }

    3. 测试业务接口

    @Test

    public void testLogin(){

    String username="tedu";

    String password="123456";

    UserService service = ctx.getBean("userService", UserService.class);

    try{

    User user = service.login(username, password);

    System.out.println(user);

    service.login(username, "12");

    }catch(Exception e){

    e.printStackTrace();

    }

    }

    整合Struts2 + Spring + Hibernate

    1. 导入相关的包

    导入Struts2

    <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-core</artifactId>

    <version>2.3.24</version>

    </dependency>

    导入Struts2-spring 插件

    <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-spring-plugin</artifactId>

    <version>2.3.24</version>

    </dependency>

    导入struts2-json 插件

    <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-json-plugin</artifactId>

    <version>2.3.24</version>

    </dependency>

    添加struts2 配置文件 struts.xml

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

    <struts>

    </struts>

    2. 封装JSON返回值类

    Result.java

    public class Result<T> implements Serializable {

    public static final int SUCCESS=0;

    public static final int ERROR=1;

     

    private int state=SUCCESS;

     

    private String message = "";

     

    private T data;

     

    public Result() {

    }

     

    public Result(Exception e){

    state = ERROR;

    message=e.getMessage();

    }

    public Result(T data){

    state = SUCCESS;

    message = "SUCCESS";

    this.data = data;

    }

    public Result(int state, String message){

    this.state = state;

    this.message = message;

    }

    public Result(String message){

    state = SUCCESS;

    this.message = message;

    }

     

    public int getState() {

    return state;

    }

     

    public void setState(int state) {

    this.state = state;

    }

     

    public String getMessage() {

    return message;

    }

     

    public void setMessage(String message) {

    this.message = message;

    }

     

    public T getData() {

    return data;

    }

     

    public void setData(T data) {

    this.data = data;

    }

     

    @Override

    public String toString() {

    return "Result [state=" + state + ", message=" + message + ", data=" + data + "]";

    }

    }

    Action基础类

    public abstract class BaseAction

    extends ActionSupport

    implements Serializable, RequestAware,

    SessionAware, ApplicationAware{

     

    protected Map<String, Object> request;

    protected Map<String, Object> session;

    protected Map<String, Object> application;

    public Map<String, Object> getRequest() {

    return request;

    }

    public void setRequest(Map<String, Object> request) {

    this.request = request;

    }

    public Map<String, Object> getSession() {

    return session;

    }

    public void setSession(Map<String, Object> session) {

    this.session = session;

    }

     

     

    public Map<String, Object> getApplication() {

    return application;

    }

    public void setApplication(Map<String, Object> application) {

    this.application = application;

    }

     

     

    @Autowired

    protected UserService userService;

     

    /**

    * Json 返回值

    */

    protected Result result;

    public Result getResult() {

    return result;

    }

    }

    3. 实现用户登录功能

    定义UserAction 类

    @Controller

    @Scope("prototype")

    public class UserAction extends BaseAction{

     

    //接收用户输入参数

    private String username;

    private String password;

    public void setUsername(String username) {

    this.username = username;

    }

    public void setPassword(String password) {

    this.password = password;

    }

    /**

    * 登录 Action

    */

    public String login(){

    try {

    User loginUser=userService.login( username, password);

    session.put("loginUser", loginUser);

    //成功返回登录用户信息

    result = new Result<User>(loginUser);

    } catch (Exception e) {

    e.printStackTrace();

    //失败

    result = new Result(e);

    }

    return SUCCESS;

    }

     

    }

    在struts.xml 中添加Action配置

    <package name="user" namespace="/user" extends="json-default">

    <action name="login" class="userAction" method="login">

    <result name="success" type="json">

    <param name="root">result</param>

    </result>

    </action>

    </package>

    4. 部署到Tomcat,测试。

    5. 实现用户列表功能

    导入JSTL

    <dependency>

    <groupId>javax.servlet</groupId>

    <artifactId>jstl</artifactId>

    <version>1.2</version>

    </dependency>

    添加控制器方法

    UserAction.java

    private List<User> list;

    public List<User> getList() {

    return list;

    }

     

    public String list(){

    try{

    list = userService.list();

    return SUCCESS;

    }catch(Exception e){

    e.printStackTrace();

    return ERROR;

    }

    }

    添加显示界面JSP

    list-user.jsp

    <%@ page language="java"

    contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

    <%@taglib prefix="c"

    uri="http://java.sun.com/jsp/jstl/core" %>

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="UTF-8">

    <title>用户列表</title>

    </head>

    <body>

    <h1>用户列表</h1>

    <table>

    <tr>

    <th>编号</th><th>姓名</th>

    </tr>

    <c:forEach var="user" items="${list}">

    <tr>

    <td>${user.id}</td>

    <td>${user.name}</td>

    </tr>

    </c:forEach>

    </table>

     

    </body>

    </html>

    添加错误处理页面:

    error.jsp

    <%@ page language="java"

    contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

    <%@taglib prefix="c"

    uri="http://java.sun.com/jsp/jstl/core" %>

    <!DOCTYPE html>

    <html>

    <head>

    <meta charset="UTF-8">

    <title>ERROR</title>

    </head>

    <body>

    <h1>有错误了!</h1>

    </body>

    </html>

    添加控制器配置:

    struts.xml

    <action name="list" class="userAction" method="list">

    <result name="success">/WEB-INF/list-user.jsp</result>

    <result name="error">/WEB-INF/error.jsp</result>

    </action>

     

     

     

    最新回复(0)