Day02
实现一组功能的步骤:
- 1,充分了解需求,包括所有的细节,需要知道要做一个什么样的功能
-
2,设计实体/表
- 正向工程:设计实体、映射文件 建表 (推荐新手)
- 分析美工给的静态页面,设计实体.暂时不实现序列化(implements Serializable),需要时再写.
- 实体:
-
1,有几个实体?
- 一般是一组增删改查对应一个实体。
-
2,实体之间有什么关系?
- 一般是页面引用了其他的实体时,就表示与这个实体有关联关系。
-
3,每个实体中都有什么属性?
- 1,主键。
- 2,关联关系属性。在类图中,关联关系是一条线,有两端,每一端对应一个表达此关联关系的属性。有几个端指向本类,本类中就有几个关联关系属性。
- 3,一般属性。分析所有有关的页面,找出表单中要填写的或是在显示页面中要显示的信息等。
- 4,特殊属性:为解决某问题而设计的属性。比如要显示年龄,但不会设计一个int age字段,而是一个Date birthday字段,年龄是在显示时实时计算出来的。
-
映射文件:
-
1,写注释
- 格式为:?属性,表达的是本对象与?的?关系。
- 例:"department属性,本对象与Department的多对一"
- 2,拷模板:
-
|
|
|
|
|
|
3,填空:
- name属性:属性名(注释中的第1个问号)
- class属性:关联的实体类型(注释中的第2个问号)
-
column属性:
- <many-to-one column="..">:一般可以写成属性名(注释中的第1个问号)加Id后缀(一方的主键作为多方的外键),如属性为department,则column值写成departmentId。
- 一对多中的<key column="..">:从关联的对方(对方是多对一)的映射中把column值拷贝过来。
- 多对多中的<key column="..">:一般可以写成本对象的名加Id后缀,如本对象名为User,则写为userId。
多对多中的<many-to-many column="..">:一般可以写为关联对象的名称加Id后缀。
将几个JavaBean都写好后,再一起将其映射文件写好大半,至于关联关系可以先写完注释,拷模板,将name和class属性填好,将column属性留至最后对照来写.
column属性:先从最简单的多对一关系开始写(只有一行),再写其对应的一对多…
例如以下User,Role和Department:
User:
|
public class User { private Long id; private Department department; private Set<Role> roles = new HashSet<Role>(); //用户与角色多对多
private String loginName; // 登录名 private String password; // 密码 private String name; // 真实姓名 private String gender; // 性别 private String phoneNumber; // 电话号码 private String email; // 电子邮件 private String description; // 说明 ……… } |
Role:
|
public class Role { private Long id; private String name; private String description;
private Set<User> users = new HashSet<User>(); //岗位和用户多对多关系 ……. } |
Department:
|
public class Department { private Long id; private String name; private String description;
private Set<User> users = new HashSet<User>(); //部门和用户一对多 private Set<Department> children= new HashSet<Department>(); //部门和下级部门一对多 private Department parent; //部门和上级部门多对一 …… } |
User.hbm.xml:
|
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.itcast.oa.domain"> <class name="User" table="itcast_user"> <id name="id"> <generator class="native"></generator> </id>
<property name="loginName" column="loginName"></property> <property name="password" column="password"></property> <property name="name" column="name"></property> <property name="gender" column="gender"></property> <property name="phoneNumber" column="phoneNumber"></property> <property name="email" column="email"></property> <property name="description" column="description"></property>
<!-- department属性,表达的是本对象与Department的多对一关系 --> <many-to-one name="department" class="Department" column="departmentId"></many-to-one>
<!-- roles属性,表达的是本对象与Role的多对多关系 --> <set name="roles" table="itcast_user_role"> <key column="userId"></key> <many-to-many class="Role" column="roleId"></many-to-many> </set>
</class> </hibernate-mapping> |
Role.hbm.xml:
|
<!-- users属性,表达的是本对象与User的多对多关系 --> <set name="users" table="itcast_user_role"> <key column="roleId"></key> <many-to-many class="User" column="userId"></many-to-many> </set> |
Department.hbm.xml:
|
<!-- users属性,表达的是本对象与User的一对多关系 --> <set name="users"> <key column="departmentId"></key> <one-to-many class="User"/> </set>
<!-- children属性,表达的是本对象与Department(下级)的一对多 --> <set name="children"> <key column="parentId"></key> <one-to-many class="Department"/> </set>
<!-- parent属性,表达的是本对象与Department(上级)的多对一关系 --> <many-to-one name="parent" class="Department" column="parentId"></many-to-one> |
- 不要忘记载入映射文件.
运行TestSpring中testSessionFactory方法,测试成功则建表完毕.
TestSpring:
|
package cn.itcast.oa.test;
import org.hibernate.SessionFactory; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring {
private ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//测试SessionFactory @Test public void testSessionFactory() throws Exception{ SessionFactory sf = (SessionFactory) ac.getBean("sessionFactory"); System.out.println(sf.openSession()); }
//测试事务管理 @Test public void testTx() throws Exception{ TestService testService = (TestService) ac.getBean("testService"); testService.saveTwoUsers(); }
//测试Action对象的管理 @Test public void testAction() throws Exception{ TestAction testAction = (TestAction) ac.getBean("testAction"); System.out.println(testAction); } } |
- 反向工程:设计表 映射文件、实体
-
3,分析功能
-
分析到每个请求的粒度。

- 得到的结果是我们需要处理多少种请求,其中每种请求对应一个Action方法。
-
按照美工给的静态页面进行分析.再写action之前,先设计好方法名等(最好带有规律).
-
<result name="toList" type="redirectAction">/xxxAction_list</result> |
添加页面和修改页面可以整合成同一个页面.所以addUI()和editUI()的返回值和页面可以分别为:saveUI和saveUI.jsp.
请求转发和重定向两种跳转方式的区别
请求转发:request.getRequsetDispatcher().forward(requset,response);
重定向:response.sendRedirect(),
-
1)转发作用于服务器端,是在服务器内部进行转发。重定向作用于客户端,相当于客户端重新发送一次新的请求。
2)转发后地址栏不会改变。重定向后地址栏改变。(若是转发,刷新一次页面,地址栏不变,则又会发送一次请求,而重定向不会,所以重定向能避免重复提交的问题)
3)转发后资源能获取到请求中的数据。重定向后的资源不能获得原请求中的数据。
4)转发只能在本应用内部资源之间进行。重定向可以跳转到任何网络资源。
5)转发可以访问受保护资源(WEB-INF里的资源)。重定向不能定位到受保护资源。6)转发只有一次请求,重定向包含两次请求.
4,实现功能:
-
1,创建Action,并定义出其中的方法(CRUD的6个方法(方法名、返回值、注释))(还不需要具体实现)。
不要忘记在Action类上加注解 @Controller 和 @Scope("prototype").如:
DepartmentAction:
|
package cn.itcast.oa.view.action; import javax.annotation.Resource; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import cn.itcast.oa.domain.Department; import cn.itcast.oa.service.DepartmentService; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven;
@Controller @Scope("prototype") public class DepartmentAction extends ActionSupport implements ModelDriven<Department>{
private Department model = new Department(); public Department getModel() { return model; } /* @Resource private DepartmentService departmentService;*/
/** * 列表 */ public String list() throws Exception { return "list"; } /** * 删除 */ public String delete() throws Exception { return "toList"; } /** * 添加页面 */ public String addUI() throws Exception { return "saveUI"; } /** * 添加 */ public String add() throws Exception { return "toList"; } /** * 修改页面 */ public String editUI() throws Exception { return "saveUI"; } /** * 修改 */ public String edit() throws Exception { return "toList"; } } |
TIP:增删改查所用的6个Action方法模板:
|
/** 列表 */ public String list() throws Exception { return "list"; } /** 删除 */ public String delete() throws Exception { return "toList"; } /** 添加页面 */ public String addUI() throws Exception { return "saveUI"; } /** 添加 */ public String add() throws Exception { return "toList"; } /** 修改页面 */ public String editUI() throws Exception { return "saveUI"; } /** 修改 */ public String edit() throws Exception { return "toList"; } |
2, 初步创建JSP页面(页面上只写些简单东西,用于测试), 并配置struts.xml.如:

List.jsp:

SaveUI.jsp:

struts.xml:
|
<!-- 部门管理 --> <action name="department_*" class="departmentAction" method="{1}"> <result name="list">/WEB-INF/jsp/departmentAction/list.jsp</result> <result name="saveUI">/WEB-INF/jsp/departmentAction/saveUI.jsp</result> <result name="toList" type="redirectAction">department_list</result> </action> |
Tips:class=" departmentAction"首字母是小写, redirectAction要拼写正确,jsp要放进WEB-INFO目录下.

测试:启动服务器,访问action,观察页面是否成功跳转.
-
3,实现Action方法,并创建出所用到的新的Service接口。
在Action中注入相应Service(加上注解@Resource).
-
4,实现Service方法,并创建出所用到的新的Dao方法。
先利用Ctrl+1创建action要用到的Service接口(和其中的规范(Ctrl+1,再Alt+向左键 返回原来的类)),等写完了action中的具体方法,再创建具体的ServiceImpl类,实现其中具体的功能.
在ServiceImpl类上加上注解@Service@Transactional,在ServiceImpl中注入相应Dao(加上注解@Resource).
-
5,实现Dao方法。
记得在实现类上加注解@Repository.
-
6,完成JSP页面。
先完成基本功能:把数据显示出来,不用管样式.完成基本功能的时候,要参照静态页面来完成,比如页面列表上有添加和修改选项,所以就得完成这些功能.等到测试运行没问题之后再套用静态页面:即将美工给的静态页面源码和相关的资源文件(如
等)拷过来.再仔细修改静态页面.如: (部门管理有关上级部门的功能暂不实现(涉及树状结构))
列表页面:

添加/修改页面(区别是修改页面有回显数据):

原始代码:
List.jsp:
|
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <%-- 显示数据 --%> <html> <body>
<s:iterator value="departmentList"> <s:property value="id"/>, <s:property value="name"/>, <s:property value="description"/>
<%-- 使用s:a标签,可以帮我们自动的加上前面的工程名称和后面的扩展名 --%> <s:a action="department_delete?id=%{id}" onclick="return confirm('确定要删除吗?')">删除</s:a> <s:a action="department_editUI?id=%{id}">修改</s:a> <br/> </s:iterator>
<s:a action="department_addUI">添加</s:a>
</body> </html> |
迭代器的这种写法是被允许的,不过departmentList要事先被put进集合域中.相应action中的代码:
|
/** * 列表 */ public String list() throws Exception { List<Department> departmentList = departmentService.findAll(); ActionContext.getContext().put("departmentList", departmentList); return "list"; } |
SaveUI.jsp:
|
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <body>
<s:form action="department_%{id == null ? 'save' : 'edit'}"> <s:hidden name="id"></s:hidden> 名称:<s:textfield name="name"></s:textfield><br/> 说明:<s:textarea name="description"></s:textarea><br/> <s:submit value="提交"></s:submit> </s:form>
</body> </html> |
若id有值(id是从List.jsp传过来的),则这个表单会提交到DepartmentAction中的edit()方法,这个页面就成了修改页面.
而此时这个修改页面回显数据的功能就成了关键(用Struts2标签回显数据很方便,缺点是要自己修改样式):
<s:textfield name="name"></s:textfield>隐藏了value="name"(不写也会有,所以用Struts2标签回显数据很方便).
他会先从值栈的栈顶开始找对象的name属性,若找不到就会从map域的key值开始找.所以如果想要更好地回显数据,最好就要先把数据push进值栈栈顶.
对应DepartmentAction中的代码:
|
/** * 修改页面 */ public String editUI() throws Exception { //准备回显的数据 Department department = departmentService.getById(model.getId()); ActionContext.getContext().getValueStack().push(department); return "saveUI"; } |
- TIPS:一定要熟练掌握这种写法.要想使用Struts2标签,就要引入Struts2标签库<%@ taglib prefix="s" uri="/struts-tags" %>.这里使用的是OGNL表达式,语法格式是:%{},而TL表达式的语法格式是:#{}.
套用静态页面,即将页面源码复制过来后,修改页面代码.
在此要先将..替换成${pageContext.request.contextPath},然后再将
<script language="javascript" src="../script/DemoData.js" charset="utf-8"></script>
<script language="javascript" src="../script/DataShowManager.js" charset="utf-8"></script>
删掉(这些是测试数据),将class改成cssClass(Struts2标签中,会将cssClass翻译成class)最后再慢慢修改...
list.jsp:
|
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <html> <head> <title>部门列表</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script language="javascript" src="${pageContext.request.contextPath}/script/jquery.js"></script> <script language="javascript" src="${pageContext.request.contextPath}/script/pageCommon.js" charset="utf-8"></script> <script language="javascript" src="${pageContext.request.contextPath}/script/PageUtils.js" charset="utf-8"></script> <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/style/blue/pageCommon.css" /> <script type="text/javascript"> </script> </head> <body>
<div id="Title_bar"> <div id="Title_bar_Head"> <div id="Title_Head"></div> <div id="Title"><!--页面标题--> <img border="0" width="13" height="13" src="${pageContext.request.contextPath}/style/images/title_arrow.gif"/>部门管理 </div> <div id="Title_End"></div> </div> </div>
<div id="MainArea"> <table cellspacing="0" cellpadding="0" class="TableStyle">
<!-- 表头--> <thead> <tr align=center valign=middle id=TableTitle> <td width="150px">部门名称</td> <td width="150px">上级部门名称</td> <td width="200px">职能说明</td> <td>相关操作</td> </tr> </thead>
<!--显示数据列表--> <s:iterator value="departmentList"> <tbody id="TableData" class="dataContainer" datakey="departmentList"> <tr class="TableDetail1 template"> <td><s:property value="name"/> </td> <td> </td> <td><s:property value="description"/> </td> <td><s:a action="department_delete?id=%{id}" onclick="return confirm('确定要删除么?')">删除</s:a> <s:a action="department_editUI?id=%{id}">修改</s:a><br/> </td> </tr> </tbody> </s:iterator> </table>
<!-- 其他功能超链接 --> <div id="TableTail"> <div id="TableTail_inside"> <s:a action="department_addUI"><img src="${pageContext.request.contextPath}/style/images/createNew.png" /></s:a> </div> </div> </div> <!--说明--> <div id="Description"> 说明:<br /> 1,列表页面只显示一层的(同级的)部门数据,默认显示最顶级的部门列表。<br /> 2,点击部门名称,可以查看此部门相应的下级部门列表。<br /> 3,删除部门时,同时删除此部门的所有下级部门。 </div> </body> </html> |
saveUI.jsp:
|
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <head> <title>部门设置</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script language="javascript" src="${pageContext.request.contextPath}/script/jquery.js"></script> <script language="javascript" src="${pageContext.request.contextPath}/script/pageCommon.js" charset="utf-8"></script> <script language="javascript" src="${pageContext.request.contextPath}/script/PageUtils.js" charset="utf-8"></script> <link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/style/blue/pageCommon.css" /> </head> <body>
<!-- 标题显示 --> <div id="Title_bar"> <div id="Title_bar_Head"> <div id="Title_Head"></div> <div id="Title"><!--页面标题--> <img border="0" width="13" height="13" src="${pageContext.request.contextPath}/style/images/title_arrow.gif"/>部门信息 </div> <div id="Title_End"></div> </div> </div>
<!--显示表单内容--> <div id=MainArea> <s:form action="department_%{id == null ? 'save' : 'edit'}"> <s:hidden name="id"></s:hidden> <div class="ItemBlock_Title1"><!-- 信息说明<DIV CLASS="ItemBlock_Title1"> <IMG BORDER="0" WIDTH="4" HEIGHT="7" SRC="${pageContext.request.contextPath}/style/blue/images/item_point.gif" /> 部门信息 </DIV> --> </div>
<!-- 表单内容显示 --> <div class="ItemBlockBorder"> <div class="ItemBlock"> <table cellpadding="0" cellspacing="0" class="mainForm"> <tr><td width="100">上级部门</td> <td><select name="parentId" class="SelectStyle"> <option value="0" selected="selected">请选择部门</option> <option value="7">┠总经理室</option> <option value="1">┠市场部</option> <option value="2"> ┠咨询部</option> <option value="3"> ┠招生部</option> <option value="4">┠教学部</option> <option value="5">┠后勤部</option> </select> </td> </tr> <tr><td>部门名称</td> <td><s:textfield name="name" cssClass="InputStyle"/> *</td> </tr> <tr><td>职能说明</td> <td><s:textarea name="description" cssClass="TextareaStyle"/></td> </tr> </table> </div> </div>
<!-- 表单操作 --> <div id="InputDetailBar"> <input type="image" src="${pageContext.request.contextPath}/style/images/save.png"/> <a href="javascript:history.go(-1);"><img src="${pageContext.request.contextPath}/style/images/goBack.png"/></a> </div> </s:form> </div> <div class="Description"> 说明:<br /> 1,上级部门的列表是有层次结构的(树形)。<br/> 2,如果是修改:上级部门列表中不能显示当前修改的部门及其子孙部门。因为不能选择自已或自已的子部门作为上级部门。<br /> </div> </body> </html> |
DepartmentAction:
|
package cn.itcast.oa.view.action; import java.util.List; import javax.annotation.Resource; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import cn.itcast.oa.domain.Department; import cn.itcast.oa.service.DepartmentService; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven;
@Controller @Scope("prototype") public class DepartmentAction extends ActionSupport implements ModelDriven<Department>{
private Department model = new Department(); public Department getModel() { return model; }
@Resource private DepartmentService departmentService;
/** * 列表 */ public String list() throws Exception { List<Department> departmentList = departmentService.findAll(); ActionContext.getContext().put("departmentList", departmentList); return "list"; } /** * 删除 */ public String delete() throws Exception { departmentService.delete(model.getId()); return "toList"; } /** * 添加页面 */ public String addUI() throws Exception { return "saveUI"; } /** * 添加 */ public String save() throws Exception { departmentService.save(model); return "toList"; } /** * 修改页面 */ public String editUI() throws Exception { //准备回显的数据 Department department = departmentService.getById(model.getId()); ActionContext.getContext().getValueStack().push(department); return "saveUI"; } /** * 修改 */ public String edit() throws Exception { //获取要修改的数据库中的原始数据 Department department = departmentService.getById(model.getId()); //修改 department.setName(model.getName()); department.setDescription(model.getDescription()); //修改数据库中的数据 departmentService.update(department); return "toList"; } } |
- 5,测试、运行
常用快捷键:
Alt + 方向键向左键 跳回刚刚打开的类
Alt + Shift + A 集体编辑?
Ctr + o 按一次,显示当前类包含的的所有字段,方法等, 再按一次会附加显示继承过来的所有字段,方法等.
Ctrl + Shift +x 转成大写(先选中)
Alt + / 代码提示
Shift + Enter 相当于先按End在按回车,即在当前行下面另起一个新行。
Ctrl + Shift + F 格式化代码
Ctrl + Shift + O 自动导入包
Ctrl + / 注释/取消注释
Ctrl + Shift + T 打开类或接口的文件
Ctrl + D 删除整行
Ctrl + 1 快速修复错误
Alt + ↑ 当前行的代码移动到上面去
Alt + ↓ 当前行的代码移动到下面去
Ctrl + Alt + ↓ 复制当前行到下面
Ctrl + F11 直接运行
F11 Debug模式运行
Ctrl + Shift + X 转为大写
Ctrl + Shift + Y 转为小写

浙公网安备 33010602011771号