★★JSP+Struts+Mysql构建的MVC三层框架对一张数据表的CURD

  1. 项目实现流程

    大体流程:搭建环境
    à
    开发后台
    à
    开发前台

    1. 建立工程(struts2CURD),拷贝jar包,建立struts.xml文件,搭建环境
    2. 建立数据库和数据源配置:dbcpconfig.properties
    3. 建立db.sql:里面全是数据库操作的一些语句
    4. 建立操作数据库的工具:*.util:DBCPUtil.java,用于加载数据源。getDataSource();
    5. *.Domain:User.java 继承ActionSupport,实现Serializable接口。

    ????写好字段;生成get和set方法;建立toString方法(方便调试)

    1. 建立Dao层(先接口后实现):*.Dao:UserDao.java(这个要按需求来做,优先考虑返回值)

    实现功能


    界面


    方法原型


    查询所有用户


    显示


    public List<User> findAllUsers()
    {}


    根据查询条件查询客户


    查询


    public List<User> findUsersByCondition(String condition)
    {}


    添加用户到数据库


    添加


    public
    void addUser(User user)
    {}


    根据Id组件获取用户信息


    查看


    public User findUserById(String userId)
    {}


    修改客户信息


    编辑


    public
    void updateUser(User user)
    {}


    根据用户的ID删除记录


    删除


    public
    void deleteUser(String userId)
    {}

    1. 实现Dao接口:*.dao.impl:UserDaoMysqlImpl.java
    2. 建立"异常库":*.Exception:DaoException.java
    3. 写加密工具类:*.util:MD5Util.java
    4. *.test:单元测试

    开发后台

    1. 显示信息界面:listUsers.jsp和默认主页index.jsp
    2. 建立UserService.java接口
    3. 建立UserServiceImpl.java实现UserService类
    4. 在User.java中补充相应方法
    5. 在listUsers.jsp页面中添加"添加"用户的按钮链接。在User.java中添加addUser()方法。建立addUser.jsp页面,实现添加功能。

      注意:在最初开始写addUser()方法时应该通过System.out.println(this);来检验是否在控制台可以得到前台输入的数据。

      添加验证规则

    6. 在domain下建立验证规则(用户输入数据的规则)的xml文档:User-user_addUser-validation.xml。
    7. 实现综合模糊查询功能:在listUsers.jsp中添加相应项。在User.java中添加queryCondition()方法。

    8. 实现删除功能……
    9. 实现编辑功能……
    10. ★★★Date转换功能,系统体现的功能不适合。建立xwork-conversion.properties文件(java.util.Date=cn.hw.convertor.

      DateConvertor)

      建立DateConvertor.java类,继承:DefaulttypeConvert类,覆盖convertValue()方法

    11. 实现查看功能…… showUser.jsp
    12. 实现下载功能……
    13. 用拦截器实现的必须登陆才能进行操作。

      *.interceptor:PermissionInterceptor.java 实现Interceptor接口(注意是opensymphony的不是sun的)

      在顺

    14. 写login.jsp
  2. 总结

  • 我们自己写的动作类继承com.opensymphony.xwork2.ActionSupport的理由

    先了解Action接口有:

    ????public static final java.lang.String SUCCESS = "success";

    ????public static final java.lang.String NONE = "none";

    ????public static final java.lang.String ERROR = "error";

    ????public static final java.lang.String INPUT = "input";

    ????public static final java.lang.String LOGIN = "login";

    ????public abstract java.lang.String execute() throws java.lang.Exception;

  1. ActionSupport实现了Action类,这样利用该类中定义的这些常量来完成页面与动作类之间的交互。
  2. ActionSupport实现了很多的实用接口,大大的简化我们自己书写动作类的开发。

    1. 开发中常利用该类中的validate()方法:会自动执行在execute()之前,如校验失败,会转入input处,必须在配置该Action时配置input属性
    2. 重载该类中的execute()方法:
    3. ActionSupport还提供了一个getText(String key)方法还实现国际化,该方法从资源文件上获取国际化信息,这样在自定义标签时可以定义一个变量为new actionsupport对象实现国际化
  • 为什么要实现Serializable接口

    一个类只有实现了Serializable接口,它的对象才是可序列化的。因此如果要序列化某些类的对象,这些类就必须实现Serializable接口。而实际上,Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。一般以下三种情况都需要实现Serializable接口

  1. 当你想把的内存中的对象写入到硬盘的时候。比如说你的内存不够用了,那计算机就要将内存里面的一部分对象暂时的保存到硬盘中,等到要用的时候再读入到内存中,硬盘的那部分存储空间就是所谓的虚拟内存。在比如过你要将某个特定的对象保存到文件中,我隔几天在把它拿出来用,那么这时候就要实现Serializable接口;
  2. 当你想用套接字在网络上传送对象的时候。在进行java的Socket编程的时候,你有时候可能要传输某一类的对象,那么也就要实现Serializable接口;最常见的你传输一个字符串,它是JDK里面的类,也实现了Serializable接口,所以可以在网络上传输。
  3. 当你想通过RMI传输对象的时候。如果要通过远程的方法调用(RMI)去调用一个远程对象的方法,如在计算机A中调用另一台计算机B的对象的方法,那么你需要通过JNDI服务获取计算机B目标对象的引用,将对象从B传送到A,就需要实现序列化接口。
  • serialVersionUID的作用 ?

    serialVersionUID:字面意思上是序列化的版本号。warning的功能,在你实现序列化的类上会有这个警告,点击会出现增加这个版本号。这个版本号就是确保了不同版本之间的兼容性,不仅能够向前兼容,还能够向后兼容,即在版本升级时反序列化仍保持对象的唯一性。
    它有两种生成方式:一个是默认的1L,比如:private static final long serialVersionUID = 1L;一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:private static final long serialVersionUID = xxxxL;

4. 在写代码时应该从后台开始往前台,还是从前台往后台开始写?

如果对业务不是很熟,则应该从页面的需求开始逐步从action层向service层写。Dao层可以分开,提供一些常用的数据库操作方法,当写到service层,如果dao层提供的方法不能满足条件,然后再在dao层补充相关的方法以供service层使用。但切记不要写完dao层直接写service层,除非对业务非常的熟悉。所以一般情况下,采取从两头向中间写代码比较稳妥。

  • ★★页面转向的方式有下面几种
  1. 当转向的是一个纯粹的页面时,即没有动作请求,不要从后台请求数据,则通过<a href=""/>可以直接转到相应的前台页面,前台页面之间的跳转。如主页面上点击添加用户按钮,页面转向用户添加数据的页面。
  2. 当页面向后台请求一个动作并且传输数据(如:查询或删除)时。要将相关数据提交给后台,然后后台依据该数据形成的条件今进行后台操作,最后返回相应数据至前台页面显示。这种要将数据提交给后台的动作请求,需要用表单进行操作,一般有下面三种方式可以选择。

    <form
    action="${pageContext.request.conextPath}/queryUser?operation=…"
    method="post">

    ... <input
    type="submit" value="添加"/>

    </form>

    <s:form
    action="user_queryCondition"
    namespace="/user">

    ... <s:submit
    value="查询"></s:submit>

    </s:form><!--查询结果数据在本页面显示-->

    <s:url
    action="user_delUser"
    namespace="/user"
    var="url">


    <s:param
    name="userId"
    value="#user.id"></s:param>

    </s:url>

    <a
    href="<s:property value=‘url‘/>">删除</a><!--删除、编辑、修改都可用这种方式-->

  • 利用JSP+Struts2+Mysql技术构建MVC三层框架实现一张数据表的CURD难点
  1. 上传(结合struts2框架)+ 数组形式字段的处理

    【UserAction.java】相关字段见下面(2)-(a)

    【addUser.jsp】

    <s:form
    action="user_addUser"
    namespace="/user"
    enctype="multipart/form-data">


    <s:file
    name="image"
    label="照片"></s:file>

    </s:form>

????????【UserAction:addUser()】

public String addUser(){

//System.out.println(this);//★打印到控制台上,验证jsp页面的数据能不能获得

//1.★★单独处理hobby

if(hobbies!=null&&hobbies.length>0){

StringBuffer sb =
new StringBuffer();

for(int i=0;i<hobbies.length;i++){

if(i>0)

sb.append(",");

sb.append(hobbies[i]);

}

hobby = sb.toString();

}

//单独处理:filename、storePath、path

/*2.1★★单独处理filename,上传到文件存储时必须以不同的文件名存储,防止多名用户上传相同文件名文件*/

filename = UUID.randomUUID().toString()+"_"+imageFileName;

//2.2得到存放文件根目录files的真实路径

String storePath = ServletActionContext.getServletContext().getRealPath("/files");

//2.3计算存放的子路径:自动随机生成两级目录

path = WebUtil.makeDirs(storePath,filename);

//3.★★文件上传

try
{

//common.io包中的:FileUtils.copyFile():拷贝文件到新的文件中并且保存最近修改时间

FileUtils.copyFile(image,
new File(storePath+"\\"+path+"\\"+filename));

}
catch
(IOException e)
{

e.printStackTrace();

}

s.addUser(this); //4.★将user放进去

ActionContext.getContext().put("message",
"保存成功!");

return
"saveOK";

}

【WebUtil.java】

public
class WebUtil{

public
static String makeDirs(String storePath, String filename)
{

int hashCode = filename.hashCode();

int dir1 = hashCode&0xf;//最低四位

int dir2 =(hashCode&0xf0)>>4;//其余四位

String newPath = dir1+"\\"+dir2;

File file =
new File(storePath,newPath);

if(!file.exists())

file.mkdirs();

return newPath;

}

}

  1. 下载(结合struts2框架)

    下面的方法中利用EL表达式和struts中OGNL表达式进行传值+简单权限拦截

    下面与下载相关的参数说明:

    contentType
    :内容类型,和互联网MIME标准中的规定类型一致,例如text/plain代表纯文本text/xml表示XML,image/gif代表GIF图片,image/jpeg代表JPG图片

    inputName:下载文件的来源流,对应着action类中某个类型为Inputstream的属性名,例如取值为inputStream的属性需要编写getInputStream()方法

    contentDisposition
    :文件下载的处理方式,包括内联(inline)和附件(attachment)两种方式,而附件方式会弹出文件保存对话框,否则浏览器会尝试直接显示文件。取值为:attachment;filename="struts2.txt",表示文件下载的时候保存的名字应为struts2.txt。如果直接写filename="struts2.txt",那么默认情况是代表inline,浏览器会尝试自动打开它,等价于这样的写法:inline; filename="struts2.txt"

    bufferSize:下载缓冲区的大小

    1. 【UserAction.java】

    public
    class User extends ActionSupport implements Serializable {


    //...
    其它字段和相应的setter和getter 方法

    private String path;//文件保存的路径

    private String filename;//存的文件名 UUID_老文件名

    //文件上传的相关字段

    private File image;

    private String imageFileName;

    private String imageContentType;

    private InputStream inputStream;//★文件下载的相关字段:文件下载需要的流

    private UserService s =
    new UserServiceImpl();

    public String download(){

    path = ServletActionContext.getRequest().getParameter("path");

    filename = ServletActionContext.getRequest().getParameter("filename");

    String storePath = ServletActionContext.getServletContext().getRealPath("/files");

    try
    {

    inputStream =
    new FileInputStream(storePath+"\\"+path+"\\"+filename);//★组织路径:构建传输流

    }
    catch
    (FileNotFoundException e)
    {

    e.printStackTrace();

    }

    return SUCCESS;

    }

    }

    1. 【download.jsp】

    <c:url
    value="/user/download"
    var="url">


    <c:param
    name="path"
    value="${user.path}"></c:param>


    <c:param
    name="filename"
    value="${user.filename}"></c:param>

    </c:url>

    <a
    href="${url}">下载</a>

    1. 【struts.xml】

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


    <action
    name="download"
    class="cn.hw.domain.User"
    method="download">


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


    <!-- 拦截器,登录以后才可以进行下载-->


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


    <param
    name="contentType">application/octet-stream</param>


    <!-- octet-stream表示二进制流? -->


    <param
    name="inputStream">inputStream</param>


    <!-- ★
    输入是对应的动作类中的那个字段,指定输入流是哪个 -->


    <param
    name="contentDisposition">attachment;filename=${filename}</param>


    <!-- 要下载的文件名,主要加头attachment,否则会吐到浏览器上面 -->


    </result>


    <result
    name="login">/login.jsp</result>


    </action>

    </package>

    1. 【PermissionInterceptor.java】定义拦截器,并在struts.xml中进行配置

    public
    class PermissionInterceptor implements Interceptor {

    public String intercept(ActionInvocation invocation)
    throws Exception {

    HttpSession session = ServletActionContext.getRequest().getSession();

    Object obj = session.getAttribute("user");

    if(obj==null){

    return
    "login";

    }else{

    return invocation.invoke();

    }

    }

    ///其它方法省略

    }

    1. 登录的相关代码和页面等省略
时间: 2024-10-07 07:04:22

★★JSP+Struts+Mysql构建的MVC三层框架对一张数据表的CURD的相关文章

MySQL数据库查询某个库下有几张数据表

今天想了解一下我们项目中具体用了几张数据表,使用如下SQL检索语句即可: SELECT COUNT(*) TABLES, table_schema FROM information_schema.TABLES WHERE table_schema = '数据库名' GROUP BY table_schema;

yii框架之gii创建数据表对应的model类

一.首先是在数据库中建立工程需要的表: 二.然后,配置对应文件: 在工程目录下yiiProject\protected\config\main.php.在50行定义了db应用组件,下面后一段注释掉了的mysql的链接配置项,我们将未注释的db注释掉,然后打开mysql链接代码并填写相关信息即可完成mysql链接配置项. 即,把下面代码         'db'=>array(             'connectionString' => 'sqlite:'.dirname(__FILE_

【mysql元数据库】使用information_schema.tables查询数据库和数据表信息

概述 对于mysql和Infobright等数据库,information_schema数据库中的表都是只读的,不能进行更新.删除和插入等操作,也不能加触发器,因为它们实际只是一个视图,不是基本表,没有关联的文件. information_schema.tables存储了数据表的元数据信息,下面对常用的字段进行介绍: table_schema: 记录数据库名: table_name: 记录数据表名: engine : 存储引擎: table_rows: 关于表的粗略行估计: data_lengt

mysql 如何在访问某张数据表按照某个字段分类输出

也许大家有时候会遇到需要将把数据库中的某张表的数据按照该表的某个字段分类输出,比如一张数据表area如下 我们需要将里面的area按照serialize字段进行分类输出,比如这种形式: areas          serialize 阿蓝色,艾沙云      A 重庆森林,传承家园  C 红军楼小区,海员新村 H ......... 要以这种形式放映出来,于是可以这样做,使用mysql中的group_concat() .group by实现, select serialize,group_co

MySQL之终端(Terminal)管理数据库、数据表、数据的基本操作

sudo /Applications/XAMPP/xamppfiles/bin/mysql.server start /Applications/XAMPP/xamppfiles/bin/mysql -h localhost -u root -p; http://www.cnblogs.com/GarveyCalvin/p/4297282.html#createDatabase 1. mysql> select version(); +-----------+ | version() | +--

MVC+三层框架搭建

介绍: UI   -->asp.net mvc  admintLTE BLL -->IBLL .BLL DAL -->IDAL.DAL MODEL -->Model Common -->Common Locale -->Locale Core -->Core 引用关系: 可以参考http://www.cnblogs.com/ymnets/p/3424939.html这位大神的 亮点: IOC容器的实现 最后附上效果图: 原文地址:https://www.cnblo

MYSQL—第二部分(Linux版本的安装和数据表的操作)

Linux版本的安装(过于简单了) 安装: ? 1 yum install mysql-server 服务端启动 ? 1 mysql.server start 客户端连接 ? 1 2 3 4 5 6 7 连接:     mysql -h host -u user -p     常见错误:         ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2), it

Mysql学习(慕课学习笔记7)修改数据表(下)

添加主键约束 ALTER TABLE tb1_name ADD [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,…….) ALTER TABLE user2 ADD CONSTRAINT PK_USER2_ID PRIMARY KEY(id); 添加唯一约束 ALTER TABLE user2 ADD UNIQUE(username); 添加默认约束  add , alter ALTER TABLE user2 ALT

Mysql学习(慕课学习笔记6)修改数据表(上)

添加单列 Alter table tb1_name ADD[column] col_name column_definition [first | after col_name] 列名称       列定义                  插入数据的位置 after username 表示插入到username字段之后 first 表示位于第一列 添加多列 ALTER TABLE tb1_name ADD [COLUMN] (COL_NAME COLUMN_DEFINITION,…..) 删除