Spring MVC

Struts2 简介

控制层框架

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

  2. Struts2 与 Struts1 完全没有关系

  3. Struts2 的前身是 WebWorks

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

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

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

配置Struts2

Struts2核心jar包

配置步骤:

  1. 下载Struts2的jar包

    • 从struts.apache.org 下载

      1. 解压缩

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

    • 使用maven下载

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

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

  2. 配置主控制器

    • 控制器类

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

      • 在struts-core-xxxx.jar 包中

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

      • filter

      • filter-mapping

  3. 添加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!步骤

  1. 修改配置文件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作为用户看的视图。

  2. 添加类 com.tedu.HelloAction

    • 包含 String execute()

    • 方法中 return "success";

  3. 添加 /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>

由控制器向页面传递消息

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

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

  3. 在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>

从页面向控制器传递值

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

  1. 基本Bean属性传递方式

  2. 域模型属性传递方式

1. 基本属性传递方式

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

  2. 添加Bean属性的getxxx setxxx方法。

  3. 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. 手工整合

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

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

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

  4. 添加Spring配置文件。

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

2. 利用Maven整合

  1. 创建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

  2. 找到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最便捷的特点。

  3. 配置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配置文件的存储位置

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

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

  5. 启动容器进行测试。

参考代码:

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. 编写测试案例测试整合结果

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

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

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

  4. 添加测试用的视图JSP

  5. 测试

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

关键点:

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

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

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

  2. ValueStack结构,两个区域

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

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

  3. 存储数据:

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

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

      • ActionContext ctx = ActionContext.getContext();

      • ctx.getValueStack().push(obj);

      • 不常见。

    • Contents中的数据是顺序查询的

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

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

    • 与EL的作用雷同

  5. Struts2 拦截了EL,底层就是ValueStack

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

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

OGNL 表达式

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

  1. 读取root区域数据

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

  2. 读写 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

步骤:

  1. 导入包

  2. 创建配置文件

    • 配置数据库连接

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

  3. 创建实体对象。

  4. 创建 Session

  5. 调用 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>

  1. 添加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&amp;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. 临时状态

  2. 持久状态

  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容器进行管理。

步骤:

  1. 导入Hibernate

    • 导入数据库驱动

    • 数据连接池:DBCP C3P0 阿里

  2. 导入Spring

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

  4. 配置Spring

    • 配置数据源(连接池)

    • 配置Hibernate SessionFactory

      • Hibernate的参数配置进去

    • 配置 事务管理

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

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

  6. 实现DAO

    • 注入HibernateTemplate,利用HibernateTemplate实现CRUD

  7. 测试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容器进行管理。

步骤:

  1. 导入Hibernate

    • 导入数据库驱动

    • 数据连接池:DBCP C3P0 阿里

  2. 导入Spring

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

  4. 配置Spring

    • 配置数据源(连接池)

    • 配置Hibernate SessionFactory

      • Hibernate的参数配置进去

    • 配置 事务管理

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

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

  6. 实现DAO

    • 注入HibernateTemplate,利用HibernateTemplate实现CRUD

  7. 测试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!!

添加软件的业务层

步骤:

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

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

  2. 实现业务方法

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

    • 需要一些工具方法

  3. 测试业务接口

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. 实现业务方法

实现业务方法,要点

  1. 注入数据访问层DAO

  2. 务必开启事务处理

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

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>

Struts2——整理好的学习资料相关推荐

  1. 【整理】VBA学习资料整理

    非常全的教程 http://www.360doc.com/userhome/30583536 http://lzhpq.blog.sohu.com/#tp_b639e94216a https://le ...

  2. 2021年最新整理, C++ 学习资料,含C++ 11 / 14 / 17 / 20 / 23 新特性、入门教程、推荐书籍、优质文章、学习笔记、教学视频等

  3. 了解和掌握Python的函数(文末附python学习资料)

    Python之所以灵活,就是因为它函数式编程的特性.今天开始学习Python的一些高级特性. 控制流 Python等程序语言,都是从程序顶端从上到下一行行执行语句,可以把它想象成线性.生活中的很多情况 ...

  4. 软件无线电技术学习资料大汇总

    现在关注软件无线电的同学越来越多了,为方便大家一起交流学习软件无线技术,小编收集整理关于软件无线电学习资料,方便大家学习.如果您有好的学习资料也欢迎分享. [基础教程] GNURadio中文入门教程V ...

  5. 河北工业大学 离散数学学习资料分享(课件,教材,习题,总结)

    本来打算把一些PDF转成图片,然后再上传的,但是这样太过繁琐,还是直接用百度网盘分享吧.虽然这样不直接,但是方便啊. 整理不易,希望大家觉得这些资料很有用的话,不妨点个赞,关注一下吧.以后我会继续整理 ...

  6. 分享一波学习资料福利,赶紧收藏!!!

    众所周知,隔行如隔山,而转行是无比艰辛的,有部分人能坚定自己的信念,攀登悬崖峭壁,一不小心得不偿失.无论转行还是提高工资都需要提升自己的能力,也离不开学习,在这里我为大家整理分享一些学习资料.一分耕耘 ...

  7. 个人微信公众号:AIquantLab,关注回复得1000GB学习资料~~

    最近刚刚创建了一个个人公众号,想记录下学习的过程,所以把之前整理的视频资料分享了出来,公众号也会经常推送 1.机器学习.深度学习等人工智能领域知识. 2.前沿人工智能量化理论以及实际应用成果介绍. 3 ...

  8. 卧槽!华为大佬整理的Linux学习笔记和资料不小心流落到了外网.……

    资料汇总截图 一大牛整理了一套初学到进阶的Linux 学习资料,分享给大家 如何学习 如果是刚开始学习C语言的同学,我建议可以深入看下C语言里面的资料.当然了,如果你对自己的C语言比较自信,可以直接看 ...

  9. three.js学习资料整理

    最近在学three.js,特地整理偶然间碰到的学习资料分享给大家,国内除了大公司,专门学习three.js的太少了,普通的业务前端学它并不会增大面试成功率,又经常加班,react vue新特性,原理都 ...

最新文章

  1. Multiple substitutions specified in non-positional format; did you mean to add the formatted=”false”
  2. asp.net中的参数传递:Context.Handler 的用法
  3. python里遍历筛选xml文件_python xml.etree.ElementTree遍历xml所有节点实例详解
  4. python制作好看的界面_【一点资讯】Python界面如何漂亮的展示树形结构,PyQt5控件之QTreeWidget详解 www.yidianzixun.com...
  5. ppt 的局部分大功能软件介绍.ZoomIt
  6. React学习:生命周期、过滤器、event、axios-学习笔记
  7. C语言fread函数了解
  8. python创建新进程_Python os.fork()方法:创建新进程
  9. 国内首个 App SDK 国家标准成功立项;苹果意外泄露iPhone 12发布时间;TypeScript 4.0 发布| 极客头条
  10. 安装fio命令linux,fio安装和使用方法
  11. iPhone应用可用性的试探性分析
  12. web漏洞扫描器原理_面向WEB的分布式漏洞扫描器的设计与实践
  13. charles https抓包证书安装
  14. DX11编程之计算着色过滤器
  15. 环比和同比的定义和应用
  16. 服务器发送消息给客户端,服务器如何发送消息给客户端
  17. mysql 3389_SQL语句直接开启3389
  18. FutureTask源码解析(2)——深入理解FutureTask 1
  19. DZ先生怪谈国标28181之大型监控组网ntpd校时方案
  20. 高品质蓝牙耳机排行榜,优质蓝牙耳机推荐

热门文章

  1. JIRA自定义字段类型
  2. CF1660C Get an Even String
  3. 090927 恢复单反相机照片的经历
  4. 苹果支持NTFS格式移动硬盘的处理
  5. vue判断map是否为空
  6. 京东刘强东的3次大抉择
  7. 手机屏下摄像头为何难量产?
  8. JavaScript全局变量、局部变量
  9. 前端常用英语单词HTML+CSS+JS+VUE(带音标,个别搜不到的没有音标)
  10. 珍藏多年金馆长熊猫斗图必胜表情包