Struts中常用的几个技术
数据回显
数据回显,必须使用Struts标签
//Action
// 进入修改页面
public String viewUpdate() {
// 模拟一个对象(先获取一个id,再根据id调用service查询,把查到的结果保存到域)
User userInfo = new User();
userInfo.setUserName("Jack");
userInfo.setEmail("yuanjie@itcast.cn");
ActionContext ac = ActionContext.getContext();
// Map<String,Object> request = (Map<String, Object>) ac.get("request");
// request.put("userInfo", userInfo);
/************* 数据回显***************/
// 获取值栈
ValueStack vs = ac.getValueStack();
vs.pop();// 移除栈顶元素
vs.push(userInfo); // 入栈
// 进入修改页面
return "viewUpdate";
}
//JSP页面
<body>
<%@taglib uri="/struts-tags" prefix="s" %>
<br/>
<!-- 在页面文本框内,显示要修改记录的数据 -->
<!-- 手动通过value设置显示的值
<s:form action="#">
用户名: <s:textfield name="user.userName" value="%{#request.userInfo.userName}"></s:textfield> <br/>
邮箱: <s:textfield name="user.email" value="%{#request.userInfo.email}"></s:textfield> <br/>
</s:form>
-->
<!-- 数据回显技术:s:textfield会自动查找根元素数据(Ognl表达式语言取值) -->
<s:form action="#">
用户名: <s:textfield name="userName"></s:textfield> <br/>
邮箱: <s:textfield name="email"></s:textfield> <br/>
</s:form>
</body>
模型驱动
Struts运行时候,或执行默认的拦截器栈,其中有一个拦截器,是模型驱动拦截器:
<interceptor
name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
@Override
public String intercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action instanceof ModelDriven) {
ModelDriven modelDriven = (ModelDriven) action;
ValueStack stack = invocation.getStack();
Object model = modelDriven.getModel();
if (model != null) {
stack.push(model);
}
if (refreshModelBeforeResult) {
invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
}
}
return invocation.invoke();
}
引入
prams拦截器,可以把请求数据自动填充的action的属性中
//举例1:
JSP
<input type=text name=userName />
<input type=text name=pwd />
Action
class UserAction{
// 封装请求数据
private String userName;
private String pwd;
//.. set方法
}
举例2:
JSP
<input type=text name=user.userName />
<input type=text name=user.pwd />
Action
class UserAction{
// 封装请求数据
private User user;
..
}
举例3:(模型驱动)
JSP
<input type=text name=userName />
<input type=text name=pwd />
Action
class UserAction{
// 封装请求数据
private User user;
..
}
步骤及原理
步骤:
- 实现ModelDriver接口
- 实现接口方法:接口方法返回的就是要封装的对象
- 对象一定要实例化
分析:
/**
* 1. 数据回显
* 2. 模型驱动
*/
public class UserAction extends ActionSupport implements ModelDriven<User> {
// 封装请求数据
private User user = new User();
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return user;
}
// 实现模型驱动接口方法
@Override
public User getModel() {
return user;
}
public String add() {
// 测试: 使用了模型驱动,是否数据正常? Ok
System.out.println(user);
return "success";
}
防止表单重复提交
Struts提供了防止表单重复提交拦截器:
<interceptor name="token"
class="org.apache.struts2.interceptor.TokenInterceptor"/>
综合案例
目的: 综合运用上面技术。
步骤:
1.建库,建表
-- 创建数据库
CREATE DATABASE hib_demo DEFAULT CHARACTER SET utf8;
-- 建表
CREATE TABLE employee (
id INT PRIMARY KEY AUTO_INCREMENT,
empName VARCHAR(20),
workDate DATE -- 入职时间
)
2. 环境搭建
搭建Struts环境(由于我使用的Idea,可以直接生成Struts2环境)
引入jar包:c3p0/dbutils/驱动的jar包
3.开发
3.1 引入c3p0-config.xml
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///hib_demo</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">10</property>
</default-config>
<named-config name="oracleConfig">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///day17</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">10</property>
</named-config>
</c3p0-config>
3.2 写JdbcUtils.java
package utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.QueryRunner;
import javax.sql.DataSource;
/**
* Created by Administrator on 2017/1/12.
*/
public class JdbcUtils {
private static DataSource dataSource;
static {
dataSource = new ComboPooledDataSource();
}
public DataSource getDataSource(){
return dataSource;
}
public static QueryRunner getQueryRunner(){
return new QueryRunner(dataSource);
}
}
3.3 Employee实体类
import java.util.Date;
/**
* Created by Administrator on 2017/1/12.
*/
public class Employee {
//与数据库中Employee表的字段要一致
private int id;
private String empName;
private Date workDate;
...
getter && setter方法;
}
3.4 DAO
package dao;
import entity.Employee;
import java.util.List;
/**
* IEmployeeDao
* Created by Administrator on 2017/1/12.
*/
public interface IEmployeeDao {
/**
* 查询全部员工
*/
List<Employee> getAll();
/**
* 根据主键查询
*/
Employee findById(int id);
/**
* 添加员工
*/
void save(Employee emp);
/**
* 修改员工
*/
void update(Employee emp);
}
package dao.impl;
import dao.IEmployeeDao;
import entity.Employee;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import utils.JdbcUtils;
import java.sql.SQLException;
import java.util.List;
/**
* EmployeeDao
* Created by Administrator on 2017/1/12.
*/
public class EmployeeDao implements IEmployeeDao {
@Override
public List<Employee> getAll() {
String sql = "select * from employee";
try {
return JdbcUtils.getQueryRunner().query(
sql,new BeanListHandler<Employee>(Employee.class)
);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public Employee findById(int id) {
String sql = "select * from employee where id=?";
try {
return JdbcUtils.getQueryRunner().query(
sql,new BeanHandler<Employee>(Employee.class),id
);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void save(Employee emp) {
String sql = "insert into employee(empName,workDate) values(?,?)";
try {
JdbcUtils.getQueryRunner().update(sql,emp.getEmpName(),emp.getWorkDate());
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void update(Employee emp) {
String sql = "update employee set empName=?,workDate=? where id=?";
try {
JdbcUtils.getQueryRunner().update(sql,emp.getEmpName(),emp.getWorkDate(),emp.getId());
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
3.5 Service
package service;
import entity.Employee;
import java.util.List;
/**
* IEmployeeService 业务逻辑层接口
* Created by Administrator on 2017/1/12.
*/
public interface IEmployeeService {
/**
* 查询全部员工
*/
List<Employee> getAll();
/**
* 根据主键查询
*/
Employee findById(int id);
/**
* 添加员工
*/
void save(Employee emp);
/**
* 修改员工
*/
void update(Employee emp);
}
package service.impl;
import dao.IEmployeeDao;
import dao.impl.EmployeeDao;
import entity.Employee;
import service.IEmployeeService;
import java.util.List;
/**
* EmployeeService
* Created by Administrator on 2017/1/12.
*/
public class EmployeeService implements IEmployeeService {
private IEmployeeDao employeeDao = new EmployeeDao();
@Override
public List<Employee> getAll() {
try {
return employeeDao.getAll();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Employee findById(int id) {
try {
return employeeDao.findById(id);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void save(Employee emp) {
try {
employeeDao.save(emp);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void update(Employee emp) {
try {
employeeDao.update(emp);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
3.6 Action
package action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.util.ValueStack;
import entity.Employee;
import service.IEmployeeService;
import service.impl.EmployeeService;
import java.util.List;
/**
* 员工管理Action
* Created by Administrator on 2017/1/12.
*/
public class EmployeeAction extends ActionSupport implements ModelDriven<Employee> {
/*****数据封装*****/
private Employee employee = new Employee();
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
//重写模型驱动的方法
@Override
public Employee getModel() {
return employee;
}
/*****调用的Service*****/
private IEmployeeService employeeService = new EmployeeService();
/**
* 1.添加员工
*/
public String save(){
try {
//调用service保存
employeeService.save(employee);
return list();
//return "addSuccess";
} catch (Exception e) {
e.printStackTrace();
return ERROR;
}
}
/**
* 2.列表显示
*/
public String list(){
try {
//查询全部
List<Employee> listEmp = employeeService.getAll();
//保存到request域
ActionContext.getContext().getContextMap().put("listEmp",listEmp);
return "list";
} catch (Exception e) {
e.printStackTrace();
return ERROR;
}
}
/**
* 3. 进入修改页面
*/
public String viewUpdate(){
try {
//3.1获取当前修改的记录的主键值
int id = employee.getId();
//3.2service查询
Employee emp = employeeService.findById(id);
//3.3数据回显
ValueStack vs = ActionContext.getContext().getValueStack();
vs.pop(); //移除栈顶元素
vs.push(emp);//emp放入栈顶
return "update";
} catch (Exception e) {
e.printStackTrace();
return ERROR;
}
}
/**
* 修改员工
*/
public String update(){
try {
employeeService.update(employee);
return list();
} catch (Exception e) {
e.printStackTrace();
return ERROR;
}
}
}
3.7 structs.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>
<!--更改主题-->
<constant name="struts.ui.theme" value="simple"></constant>
<package name="emp" extends="struts-default">
<!--全局视图-->
<global-results>
<result name="error">/error/error.jsp</result>
</global-results>
<action name="emp_*" class="action.EmployeeAction" method="{1}">
<!--防表单重复提交,第二步:配置拦截器-->
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="token">
<!--指定拦截器那些方法需要防止表单重复提交-->
<param name="includeMethods">save</param>
</interceptor-ref>
<!--防表单重复提交,第三步:如果用户重复提交了,跳转到指定的错误页面-->
<result name="invalid.token" type="redirectAction">emp_list</result>
<!--首页显示-->
<result name="list">/WEB-INF/list.jsp</result>
<!--进入修改页面-->
<result name="update">/WEB-INF/update.jsp</result>
<!--<result name="addSuccess" type="redirectAction">emp_list</result>-->
</action>
</package>
</struts>
3.8 JSP页面
//add.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Add</title>
</head>
<body>
<s:form action="/emp_save" method="POST">
<%--防止表单重复提交,第一步:生成id(客户端、服务端)--%>
<s:token></s:token>
<table>
<tr>
<td>员工名:</td>
<td><s:textfield name="empName" /></td>
</tr>
<tr>
<td>日期:</td>
<td><s:textfield name="workDate" /></td>
</tr>
<tr>
<td colspan="2">
<s:submit value="保存员工"></s:submit>
</td>
</tr>
</table>
</s:form>
</body>
</html>
//list.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>list</title>
</head>
<body>
<table border="1" align="center">
<tr>
<th>序号</th>
<th>编号</th>
<th>员工名称</th>
<th>日志日期</th>
<th>操作</th>
</tr>
<%--1.先判断; 2.再迭代--%>
<s:if test="#request.listEmp != null">
<s:iterator var="emp" value="#request.listEmp" status="st">
<tr>
<td><s:property value="#st.count"/></td>
<td><s:property value="#emp.id"/></td>
<td><s:property value="#emp.empName"/></td>
<td><s:property value="#emp.workDate"/></td>
<td>
<s:a href="emp_viewUpdate?id=%{#emp.id}">修改</s:a>
</td>
</tr>
</s:iterator>
</s:if>
<s:else>
<tr>
<td colspan="5">对不起,没有你要显示的数据</td>
</tr>
</s:else>
</table>
</body>
</html>
//update.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Update</title>
</head>
<body>
<s:form action="/emp_update" method="POST">
<%--隐藏域,保存主键--%>
<s:hidden name="id"></s:hidden>
<table>
<tr>
<td>员工名:</td>
<td><s:textfield name="empName" /></td>
</tr>
<tr>
<td>日期:</td>
<%-- <td><s:textfield name="workDate" />
<s:hidden name="workDate"></s:hidden>
</td>--%>
<td><s:textfield name="workDate" /></td>
</tr>
<tr>
<td colspan="2">
<s:submit value="修改员工"></s:submit>
</td>
</tr>
</table>
</s:form>
</body>
</html>