Struts2

struts2介绍

概括
    struts2是J2EE的比较流行的框架,对JSP/servlet进行了封装,应用于面向WEB开发的项目。
    struts是MVC设计模式的一种解决方案
    Struts2是基于MVC的Web应用框架
    Struts2=Struts1的知名度和市场+WebWork的技术
        实现MVC模式,结构清晰
        丰富的标签(tag)
        通过配置文件页面导航,便于后期维护
        与Servlet API松耦合,便于测试
下载
    http://struts.apache.org   
        Projects -- > struts
    http://archive.apache.org/dist/struts/binaries/
功能介绍
    数据输入校验。
    Struts标签用于页面开发。
    可扩展性编程。
    采用拦截器实现AOP功能。
    国际化和本地化。
    文件上传下载。
    表单重复提交校验
struts2和struts1的区别
    1)Action实现:struts1继承抽象的父类,struts2不需要。
    2)Action实例化:struts1中Action是单例模式,Struts2为每一个请求创建一个Action实例。
    3)与jsp/Servlet耦合:struts1在调用传统的jsp/servletAPI,但struts2可以调用jsp/servlet的API(不推荐),但重新封装了其他的API(与jsp/servlet无关),实现解耦。
    4)测试方面:因为Struts1仍然调用servlet的API,因此测试必须依赖于web服务器,但Struts2克通过实例化,方法调用的方式测试。
    5)表达式语言:struts1整合了JSTL,struts2则整合了 更为强大的OGNL表达式。
    6)struts2与struts1除了命名之外,其实没有多大关系。
目录结构
    apps:基于Struts2的示例应用
    docs:Struts2开发的各类帮助文档
    lib:核心类库及第三方插件类库
    requied-lib:Struts 2开发常用的jar文件
    src:Struts2框架的源代码

使用

1.导入jar包
    struts2-core-2.3.4.1.jar    Struts2的核心包
    xwork-core-2.3.4.1.jar  xwork的核心包
    commons-io-2.0.1.jar    支持IO读写操作
    commons-fileupload-1.2.2.jar    支持文件的上传和下载
    ognl-3.0.5.jar  支持OGNL表达式
    freemarker-2.3.19.jar   基于模板生成文本输出的通用工具/标签库模板包
    javassist-3.11.0.GA.jar 支持JAVA字节码操作
    commons-lang3-3.1.jar 对java.lang包扩展
2.配置struts2的核心过滤器
    在web.xml中配置
    <filter>
        <filter-name>struts2</filter-name>
        <!-- 核心控制器,负责拦截用户的请求,根据请求的不同,分发给相应的Action处理 -->
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <!-- 将全部请求定位到指定的Struts 2过滤器中 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
3.truts2的配置文件
    在src目录下
    默认struts.xml
4.编写Action
5.在struts配置文件中配置action

Action

作用
    处理请求
    实现业务逻辑
    返回result决定结果视图
实现方式
    1.普通的Java类
    2.实现Action接口
    3.继承ActionSupport类
普通的Java类
    public class OneAction{
        public String execute() throws Exception {
            System.out.println("访问到了");
            //返回的字符串  对应 result的name属性
            return "success";
        }
    }
实现Action接口
    public class OneAction implements Action{
        @Override
        public String execute() throws Exception {
            System.out.println("访问到了");
            //返回的字符串  对应 result的name属性
            return "success";
        }
    }
继承ActionSupport类
    public class OneAction extends ActionSupport{
        private static final long serialVersionUID = 2245233853322624873L;
        //action中默认调用的方法就是execute方法
        @Override
        public String execute() throws Exception {
            System.out.println("访问到了");
            //返回的字符串  对应 result的name属性
            return "success";
        }
    }
配置
    <action name="one" class="com.shuai.test.OneAction" method="execute">
        <result name="success">/info.jsp</result>
    </action>

Struts配置文件

基础配置
    这个配置文件需要到struts的源码中去搜索,随便一个就可以。
    <?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>
内容
    <package name="shuai" extends="struts-default" namespace="/shuai">
        <action name="" class="" method="">
            <result name=""></result>
        </action>
    </package>
说明
    package
        说明
            包,管理action的路径
        name
            包名
            作用:给其它包去继承
            注意:包名必须要唯一,否则启动会报错
        namespace 
            命名空间
            可以对路径进行管理
            是url的一部分 
            默认是/
            如果是 /test 访问路径 = /test/actionName
        extends
            继承
            自定义的包,必须要继承 struts-default
            struts-default.xml
                文件目录 struts2-core-xxx.jar/struts-default.xml
                result-types : 返回值类型
                interceptors : 拦截器
        abstract
            默认是false,如果是true表示是一个抽象包,即里面不能有action的定义。
    action
        说明
            是一个控制器
            作用:配置访问路径与处理action的映射关系
        name
            访问路径
            控制器的名称,是url的一部分
        class
            控制器实际路径
            访问路径对应action类的全名 可以不写 默认是ActionSupport
            默认的class写法用来做页面跳转
                WebContent目录下是 /hello.jsp
                WEB-INF目录下是 /WEB-INF/hello.jsp
                默认的class在 struts-default.xml中配置了 <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
            修改默认执行的Action类   一般不会做修改
                <default-class-ref class="com.shuai.struts2.action.six.MyDefaultAction"></default-class-ref>
        method
            执行的方法,默认是execute
            可以省略不写
    result
        说明
            是结果集
            配置action中处理请求的方法,返回的结果视图标记对应的跳转资源
        name
            是结果的名称,通过action动作的返回值来指定。
            action处理方法的返回值
        文本值
            是结果视图
        type
            设置结果视图的类型和跳转方式
            转发 : dispatcher  默认
            重定向 : redirect
            这两个值都在struts-default.xml 中result-types中有定义

struts2访问过程

http://localhost:8080/struts2/test/six1
    1.先找struts.xml配置文件
    2.在配置文件中找命名空间/test 注意:这个地方会按照层级去找 
        /a/b/c/six 查找机制 
            首先在/a/b/c/中找six
            然后在/a/b/中找six
            然后再/a/中找six
            然后再/中找six
            如果没有就报错
    3.在命名空间中找action的six1
    4.执行action中的方法
    5.在配置文件中找result返回值
    6.找到页面进行返回

Action细节

struts2的加载顺序
    default.properties --> struts-default.xml --> struts.xml ---> *.xml
其它注意
    每次访问action的内存地址都是会改变的
    action是多例的
    servlet,filter,listener是单例的
    struts1中的action是单例的

请求参数封装

<form action="one" method="post">
    <!-- 普通属性方式 -->
    <input type="text" name="name"/>
    <!-- 对象属性方式 -->
    <input type="text" name="student.username">
    <!-- ModelDriven方式 -->
    <input type="text" name="username">
    <input type="submit" />
</form>
属性方式
    public class OneAction{
        //普通属性方式
        private String name;
        //对象属性方式
        private Student student;
        public String execute() throws Exception {
            return "success";
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Student getStudent() {
            return student;
        }
        public void setStudent(Student student) {
            this.student = student;
        }
    }
对象方式
    public class UserAction{
        private Student student;
        public String execute() throws Exception {
            System.out.println("user-action");
            System.out.println(student);
            return "success";
        }
        public void setStudent(Student student){
            this.student = student;
        }
        public Student getStudent(){
            return this.student;
        }
    }
ModelDriven方式
    public class UserAction implements ModelDriven<Student>{
        private Student student = new Student();
        public String execute() throws Exception {
            System.out.println("user-action");
            System.out.println(student);
            return "success";
        }
        @Override
        public Student getModel() {
            return student;
        }
    }

通配符

与后边的{1}是对应关系
    eight_* 中 {1}代表这个*
    eight_*_* 中{2}代表第二个*
<action name="eight_*" class="com.shuai.struts2.action.EightAction" method="{1}">
    <!-- 指代跟方法名相同的jsp页面 -->
    <result>/{1}.jsp</result>
</action>

按模块拆分struts.xml

struts-article.xml
    <package name="article" namespace="/article" extends="struts-default">
        <action name="one" class="com.shuai.test.ArticleAction" method="execute">
             <result name="success">/article.jsp</result>
        </action>
    </package>
struts-user.xml
    <package name="user" namespace="/user" extends="struts-default">
        <action name="one" class="com.shuai.test.UserAction" method="execute">
             <result name="success">/user.jsp</result>
        </action>
    </package>
struts.xml
    <struts>
        <constant name="struts.i18n.encoding" value="UTF-8"></constant>
        <include file="struts-user.xml"></include>
        <include file="struts-article.xml"></include>
    </struts>

访问Servlet API(Request/Session/Application)的方式

第一种方式
    ActionContext context = ActionContext.getContext();
    //保存到request域
    Map<String,Object> request = (Map<String,Object>)context.get("request");
    request.put("request_data", "request_data_message");
    //保存到session域
    Map<String,Object> session = (Map<String,Object>)context.get("session");
    session.put("session_data", "session_data_message");
    //保存到application域
    Map<String,Object> application = (Map<String,Object>)context.get("application");
    application.put("application_data", "application_data_message");
第二种方式-有耦合
    //保存到request域
    HttpServletRequest request = ServletActionContext.getRequest();
    request.setAttribute("request_data", "request_data_message");
    //保存到session域
    HttpSession session = request.getSession();
    session.setAttribute("session_data", "session_data_message");
    //保存到application域
    ServletContext context = ServletActionContext.getServletContext();
    context.setAttribute("application_data", "application_data_message");
第三种方式
    public class ElevenAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{
        private Map<String, Object> application;
        private Map<String, Object> session;
        private Map<String, Object> request;
        @Override
        public void setRequest(Map<String, Object> request) {
            this.request = request;
        }
        @Override
        public void setSession(Map<String, Object> session) {
            this.session = session;
        }
        @Override
        public void setApplication(Map<String, Object> application) {
            this.application = application;
        }
    }

乱码问题

POST方式GBK编码
    项目统一编码GBK
    <constant name="struts.i18n.encoding" value="GBK"></constant>
POST方式UTF-8编码
    项目统一编码UTF-8
    <constant name="struts.i18n.encoding" value="UTF-8"></constant>
POST方式其它
    项目统一编码GBK
    <constant name="struts.i18n.encoding" value="UTF-8"></constant>
GET方法UTF-8编码
    项目统一编码UTF-8
    <constant name="struts.i18n.encoding" value="UTF-8"></constant>
    tomcat/conf/server.xml配置<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

常量修改

概述
    在struts2-core 里面 的 org.apache.struts2包下来 default.properties 这里面有常量配置
修改
    <constant name="struts.action.extension" value="action,do,go,,"></constant>
名称
    struts.i18n.encoding=UTF-8 
        请求数据的中文处理 请求数据的编码 POST请求
    struts.action.extension=action,, 
        访问后缀
    struts.enable.DynamicMethodInvocation = true 
        是否开启动态方法调用,就是是否可以通过*号的方式来指代占位
        http://localhost:8080/struts2/twelve1!insert 这种访问方式是否可以
    struts.multipart.maxSize=2097152 
        文件上传大小的限制
        默认是2M
    struts.devMode = false 
        开发者模式,会显示更多的日志信息
    struts.i18n.reload=false 
        就是改了配置文件是否需要重启服务
    struts.ui.theme=xhtml 
        修改struts主题 ,一般都改为simple,就是jsp页面使用struts标签的时候,
        页面展示的时候,生成是html页面是否有额外的东西。

result结果集的type类型11个类型

转发
    <result name="success" type="dispatcher">/user.jsp</result>
重定向 - 外部资源
    <result name="success" type="redirect">/one.jsp</result>
    <result name="success" type="redirect">/user/one</result>

配置错误页面

某个Action下的错误页面
    <action name="one" class="com.shuai.test.OneAction">
         <result name="error">/error.jsp</result>
    </action>
全局错误页面
    <global-results>
        <result name="error">error.jsp</result>
    </global-results>
全局未抓取的异常配置
    <global-exception-mappings>
        <exception-mapping result="error" exception="java.lang.Exception"/>
    </global-exception-mappings>

struts-tags 标签

需要导入taglib指令:
    <%@taglib uri="/struts-tags" prefix="s"%>
标签分类
    通用标签
        数据标签
        控制标签(默认前缀s)
    UI标签
    Ajax标签(默认前缀sx)
数据标签
    提供对各种数据访的相关功能
    <s:property>
        输出值栈及Stack Context 中所有能访问的值
        访问对象的属性
        //value 是Action中的userName属性
        <s:property value="userName"/>
        //value 是Action中的user属性对象中的userName属性
        <s:property value="user.userName"/>
        Action的成员变量存储在值栈中
            <s:property value="user.id"/>
        访问List集合的一个元素
            <s:property value="streetsList[0]"/>
        访问List集合的第一个元素的属性
            <s:property value="streetsList[0].streetName"/> 
        获取List集合的大小
            <s:property value="streetsList.size()"/> 
        获取List集合是否为空
            <s:property value="streetsList.isEmpty()"/> 
    <s:debug>
        在页面上生成一个链接,单击这个链接可以
        查看值栈及Stack Context 中所有能访问的值
    <s:date>    
        格式化输出一个日期
    <s:set> 
        对设置的表达式求值,并将结果赋给特定作用域的某个变量
    <s:url> 
        生成一个URL 地址
    <s:a>   
        生成HTML 的<a>标签
    <s:param>   
        为其他标签添加参数化设置
    <s:include> 
        把其他页面包含到当前的页面上
控制标签
    用来完成流程控制,如分支流程、循环流程等
    <s: if>/<s: elseif>/<s: else>   
        实现分支流程控制,它们的语意和Java中的if、else if、else相似
    <s:iterator>    
        主要用于对集合实现循环访问功能
UI标签
    用来生成UI界面及元素
    <s:form>    
        对应HTML 中的<form>,用于向服务器端提交数据
    <s:textfield>   
        对应HTML 中的<input type="text">,即单行文本框
    <s:textarea>    
        对应HTML 中的<textarea>,即多行文本域
    <s:submit>  
        对应HTML 中的<input type="submit">,即提交表单按钮
    <s:select>  
        生成一个下拉框
    <s:doubleselect >   
        生成两个联动的下拉框
    <s:datetimepicker>  
        生成一个日历控件

interceptor拦截器(提供32个,默认执行18个)

概述
    struts2是通过拦截器来完成功能的。
    在struts-default.xml中定义了struts的所有拦截器  interceptors
    使用拦截器  有一个拦截器栈  interceptor-stack
        默认的栈是 <interceptor-stack name="defaultStack">
    struts执行哪个拦截器栈
        <default-interceptor-ref name="defaultStack"/>
拦截器与过滤器区别
    过滤器
        Filter 是servlet的概念
        拦截所有的请求,jsp/servlet/html/css/js/image....
    拦截器
        interceptor 是struts2的概念
        只拦截action请求
        如果访问的是jsp就不会拦截。
自定义拦截器
    步骤
    1.创建类OneInterceptor implements Interceptor
    2.实现 init/intercept/destroy方法
    3.在package中配置
    代码
        public class OneInterceptor implements Interceptor {
            private static final long serialVersionUID = 353192690805863911L;
            @Override
            public void destroy() {
                System.out.println("拦截器销毁 destroy");
            }
            @Override
            public void init() {
                System.out.println("拦截器初始化");
            }
            @Override
            public String intercept(ActionInvocation invocation) throws Exception {
                System.out.println("拦截开始");
                //放行,去到下一个拦截器,如果没有下一个拦截器  就执行action的方法
                //一旦执行了invoke方法,就说明已经发生了资源跳转,再更改方法的返回值无效
                String result = invocation.invoke();
                System.out.println("拦截结束--invoke="+result);
                return result;
            }
        }
    配置
        <package name="thirteen" extends="struts-default" >
            <interceptors>
                <!-- 自定义的拦截器 -->
                <interceptor name="OneInterceptor" class="com.shuai.struts2.OneInterceptor"></interceptor>
                <!-- 自定义拦截器栈 -->
                <interceptor-stack name="mystatck">
                    <!-- 引入默认的拦截器栈 -->
                    <interceptor-ref name="defaultStack"></interceptor-ref>
                    <!-- 加入自己的拦截器 -->
                    <interceptor-ref name="OneInterceptor"></interceptor-ref>
                </interceptor-stack>
            </interceptors>
            <!-- 使用自己的拦截器栈 -->
            <default-interceptor-ref name="mystatck"></default-interceptor-ref>
        </package>

文件上传

单文件上传
    public class OneAction extends ActionSupport {
        private static final long serialVersionUID = -5407112650267208013L;
        //单文件上传
        private File file;
        private String fileFileName;
        private String fileContentType;
        @Override
        public String execute() throws Exception {
            //自己打开输入流输出流把file写出到某个位置即可。
            System.out.println("file="+file);
            System.out.println("fileFileName="+fileFileName);
            System.out.println("fileContentType="+fileContentType);
            return SUCCESS;
        }
    }
多文件上传
    public class OneAction extends ActionSupport {
        private static final long serialVersionUID = -5407112650267208013L;
        private File[] file;
        private String[] fileFileName;
        private String[] fileContentType;
        @Override
        public String execute() throws Exception {
            for (int i = 0; i < file.length; i++) {
                System.out.println("file[]=" + file[i]);
            }
            for (int i = 0; i < fileFileName.length; i++) {
                System.out.println("fileFileName[]=" + fileFileName[i]);
            }
            for (int i = 0; i < fileContentType.length; i++) {
                System.out.println("fileContentType[]=" + fileContentType[i]);
            }
            return SUCCESS;
        }
    }
配置文件
    <action name="one" class="com.shuai.struts2.action.OneAction">
        <interceptor-ref name="defaultStack">
             <param name="fileUpload.allowedExtensions">txt,png,docx</param>
        </interceptor-ref>
        <result>/hello.jsp</result>
    </action>
    说明
        限制允许上传的文件类型   只能上传这些中类型 
            <param name="fileUpload.allowedTypes">text/plain,image/png</param>
        限制允许上传的文件扩展名(注意:如果与上面一起用取交集!)
            <param name="fileUpload.allowedExtensions">txt,png,docx</param>
界面
    <form action="one" method="post" enctype="multipart/form-data">
        file:<input type="file" name="file"/><br/>
        <input type="submit"/><br/>
    </form>

文件下载

代码
    public class OneAction extends ActionSupport {
        private static final long serialVersionUID = -5407112650267208013L;
        //2.需要下载的文件名
        private String fileName;
        public String getFileName() {
            return fileName;
        }
        public void setFileName(String fileName) {
            try {
                fileName = new String(fileName.getBytes("ISO8859-1"),"UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            this.fileName = fileName;
        }
        //1.下载方法
        public String down() {
            return  "down";  // 注意:因为做下载功能,返回的结果类型是“stream”
        }
        // 4.返回流
        public InputStream getFileStream(){
            File file = new File("D:\\download",this.fileName);
            FileInputStream inputStream=null;
            try {
                inputStream = new FileInputStream(file);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            System.out.println("inputStream="+inputStream);
            return inputStream;
        }
        // 5.浏览器显示的文件名
        public String getDownFile(){
            try {
                return URLEncoder.encode(fileName, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }
    }
配置文件
    <action name="one_*" class="com.shuai.struts2.action.OneAction" method="{1}">
        <result>/hello.jsp</result>
        <!-- 3.下载操作 -->
        <result name="down" type="stream">
            <!-- 文件的类型,指定为任意二进制类型,可以标识任何文件  任何类型的文件 -->
           <param name="contentType">application/octet-stream</param>
           <!-- 对应的是Action类中返回流的属性! 注意:这个fileStream是action中的getFileStream方法 -->
           <param name="inputName">fileStream</param>
           <!-- 指定浏览器显示的文件名,对应action类中的返回文件名的属性! 需要url编码    注意:这个downFile是action中的getDownFile方法-->
           <param name="contentDisposition">attachment;filename=${downFile}</param>
           <!-- 读取缓冲区大小 -->
           <param name="bufferSize">1024</param>
        </result>
    </action>

OGNL表达式

概述
    Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。
    Struts2框架使用OGNL作为默认的表达式语言。
作用
    页面取值!必须配置struts2标签!
    页面取值方式:
        1.jsp的EL表达式
        2.Struts2的Ognl表达式
使用
    引入struts的jar包,必须引入ognl.jar
OGNL优势
    1、支持对象方法调用,如xxx.doSomeSpecial();
    2、支持类静态的方法调用和值访问,表达式的格式:
        @[类全名(包括包路径)]@[方法名|值名],例如:
        @java.lang.String@format('foo %s', 'bar')
        或@tutorial.MyConstant@APP_NAME;
    3、支持赋值操作和表达式串联,如price=100, discount=0.8,
        calculatePrice(),这个表达式会返回80; 
    4、访问OGNL上下文(OGNL context)和ActionContext;
    5、操作集合对象。
其它
    OGNL 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了 java.utils.Map 的接口。
    Ognl的核心是OgnlContext对象
代码
    OgnlContext是一个Map
        //创建对象
        OgnlContext context = new OgnlContext();
        //赋值
        context.put("china", "中国");
        //取值
        System.out.println(context.get("china"));
    往根元素设置值
        User user = new User(100);
        //创建对象
        OgnlContext context = new OgnlContext();
        //赋值
        context.setRoot(user);
        //解析
        Object ognl = Ognl.parseExpression("id");
        Object value = Ognl.getValue(ognl, context,context.getRoot());
        System.out.println(value);
    往非根元素设置值, ognl表达式取值时候,需要带#符号
        User user = new User(200);
        //创建对象
        OgnlContext context = new OgnlContext();
        //赋值
        context.put("user",user);
        //解析
        Object ognl = Ognl.parseExpression("#user.id");
        Object value = Ognl.getValue(ognl, context,context.getRoot());
        System.out.println(value);
    总结
        根元素取值
            <s:property value = "id">   
        非根元素取值
            <s:property value = "#user.name">   
         ognl表达式取值,如果是根元素取值不用带#符号, 非根元素取值要带#号!

ValueStack

概述
    ValueStack实际是一个接口
    在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类
    这个类是Struts2利用OGNL的基础。
特点
    ValueStack贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象). 
    相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象.
    Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 的request请求属性中。
        ValueStack vs1 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
存储集合
    ValueStack存储对象
        ObjectStack: Struts  把动作和相关对象压入 ObjectStack 中--List
    ContextMap: 
        Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中
        Struts 会把下面这些映射压入 ContextMap 中
            parameters: 该 Map 中包含当前请求的请求参数
            request: 该 Map 中包含当前 request 对象中的所有属性
            session: 该 Map 中包含当前 session 对象中的所有属性
            application:该 Map 中包含当前 application  对象中的所有属性
            attr: 该 Map 按如下顺序来检索某个属性: request, session, application
值栈数据存储原理
    Struts每次访问action的时候
        1. 创建一个ActionContext对象
        2. 创建值栈对象
             把域中存放的数据、以及Action对象,放到值栈中!
             这时候,值栈就有了struts运行时期的数据!
        3. 把值栈的数据,拷贝一份给ActionContext!
        4. 最后,把值栈放到request的请求中!

验证


其它

1.请求数据自动封装
2.数据处理
3.拦截器、自定义拦截器
4.文件上传下载
5.Ognl表达式与struts标签
6.数据校验
7.类型转换
8.国际化
9.模型驱动
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,814评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,124评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,814评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,924评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,815评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,562评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,944评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,582评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,859评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,881评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,700评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,493评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,943评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,115评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,413评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,978评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,182评论 2 339

推荐阅读更多精彩内容

  • 概述 什么是Struts2的框架Struts2是Struts1的下一代产品,是在 struts1和WebWork的...
    inke阅读 2,228评论 0 50
  • action中如何接受页面传过来的参数 第一种情况:(同名参数) 例如:通过页面要把id=1 name=tom a...
    清枫_小天阅读 2,917评论 1 22
  • 1、struts2工作流程 Struts 2框架本身大致可以分为3个部分: 核心控制器FilterDispatch...
    重山杨阅读 1,510评论 0 38
  • 嗯 突然听到这首歌 矫情的情绪就像海水一样都涌了出来 对的 我所有的文字都是毫无头绪 无病呻吟 我...
    孙四岁阅读 319评论 0 0
  • 高考后就没有再写过一千字以上的文章了,觉得应该鼓励下自己。 今天通过老师对马斯洛需求理论五要素的...
    李瑞英mile阅读 173评论 0 4