• Struts2学习(四)


    struts-defualt.xml指定的result的类型

    1、struts-defualt.xml 文件的 181 行 开始定义了:

    <result-types>
        <result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
        <result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
        <result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
        <result-type name="httpheader" class="org.apache.struts2.result.HttpHeaderResult"/>
        <result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
        <result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
        <result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
        <result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>
        <result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
        <result-type name="plainText" class="org.apache.struts2.result.PlainTextResult" />
        <result-type name="postback" class="org.apache.struts2.result.PostbackResult" />
    </result-types>

    2、所有的 <result> 默认的名称 ( name ) 都是 success ,默认的 类型 ( type ) 都是 dispatcher
    3、dispatcher 等同于 RequestDispatcher 中的 forward 操作 ,redirect 等同于 HttpServletResponse 中的 sendRedirect 操作

    4、当 type = "redirect" 时,可以指定任意的位置

     <result type="redirect">http://www.google.com</result>

     redirectAction 类似于 redirect , 与 redirect 不同的是它专门重定向到 <action>

    <result name="success" type="redirectAction">
      <param name="namespace">/customer</param>
      <param name="actionName">page/success/register</param>
    </result>
    全局的 result
    1、<global-results>在这里所写的 result 属于当前包 的全局 result,当前包 的所有<action>可以访问
    2、action标签呢的result属于局部的result,仅仅当前的 <action> 可以访问
    控制异常
    1、<global-exception-mappings>全局的异常映射,里面的result只能引用全局的result
    2、测试案例
    index.jsp
    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Apache Struts</title> <style type="text/css"> .container { width: 90% ; margin: 10px auto ; box-shadow: 0px 0px 5px 4px #dedede ; padding: 5px 5px ; } ul .required { color : blue ; } ul li { font-size: 16px ; padding: 5px 5px ; } </style> </head> <body>      <div class="container"> <h4> &lt;global-results&gt; 和 &lt;global-exception-mappings&gt; :</h4> <a href="${ pageContext.request.contextPath }/throw/hello?throw=true" >发生异常</a> <a href="${ pageContext.request.contextPath }/throw/hello?throw=false" >不发生异常</a> </div> </body> </html>

    struts.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    
    <struts>
      <package name="throw" namespace="/throw" extends="struts-default">
    
            <global-results>
                <!-- 在这里所写的 result 属于当前包 的全局 result -->
                <result name="index" type="redirect">/results/index.jsp</result>
                <result name="exception" type="dispatcher">/results/catch.jsp</result>
            </global-results>
            <!-- 全局的exception只能引用全局的result -->
            <global-exception-mappings>
                <exception-mapping exception="java.lang.RuntimeException"
                    result="exception" />
            </global-exception-mappings>
    
            <action name="hello" class="ecut.results.action.HelloAction">
                <!-- 仅仅当前的 <action> 可以访问,属于局部的 result -->
                <result name="success" type="dispatcher">/results/hello.jsp</result>
            </action>
    
        </package>
    </struts>

    Action类

    package ecut.results.action;
    
    import com.opensymphony.xwork2.Action;
    
    public class HelloAction implements Action {
        
        private boolean t ;
    
        @Override
        public String execute() throws Exception {
            System.out.println(t);
            if( t ) {
                throw new RuntimeException( "出错了" );
            }
            return SUCCESS;
        }
        //jsp中的属性名要和get方法保持一致
        public boolean getThrow(){
            return this.t ;
        }
        
        public void setThrow( boolean t ) {
            this.t = t ;
        }
    
    }

    jsp中的属性名只需要和getter setter 方法一致就行,必须要有setter方法,getter方法可以省略,这样才可以从jsp中的URL接收到来自页面的参数throw。不然throw默认是false。

    catch.jsp

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>catch</title> </head> <body> <h1>catch</h1> </body> </html>

    hello.jsp

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>hello</title> </head> <body> <h1>Hello</h1> </body> </html>

    struts-plugin.xml中定义的result-type

    1、struts-defualt.xml的json-default包中定义的result-type

    <result-types>
      <result-type name="json" class="org.apache.struts2.json.JSONResult"/>
      <result-type name="jsonActionRedirect" class="org.apache.struts2.json.JSONActionRedirectResult"/>
    </result-types>

     2、struts2-json-plugin测试案例

    添加需要的jar包,下载链接https://files.cnblogs.com/files/AmyZheng/jckson%E4%BE%9D%E8%B5%96%E5%8C%85.rar

    普通方法将object转换json代码如下:

    package ecut.results.action;
    
    import java.io.IOException;
    import java.util.Map;
    
    import org.codehaus.jackson.map.ObjectMapper;
    
    import ecut.results.entity.Customer;
    
    public class test {
        public static void main(String[] args) throws IOException {
            Customer c = new Customer();
            c.setPassword("123456");
            c.setConfirm("123456");
            c.setUsername("Amy");
            ObjectMapper  mapper = new ObjectMapper ();
            String json = mapper.writeValueAsString(c);
            System.out.println(json);
            Customer customer = mapper.readValue(json, Customer.class);
            System.out.println(customer.getUsername()+","+customer.getPassword());
            
            Map<?,?> map = mapper.readValue(json, Map.class);
            for(Map.Entry<?, ?> entry: map.entrySet()){
                System.out.println(entry.getKey()+":"+ entry.getValue());
            }
        }
    }

    利用Struts2插件将json进行转换,代码如下:

    index.jsp

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%>
    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Apache Struts</title> <style type="text/css"> .container { width: 90% ; margin: 10px auto ; box-shadow: 0px 0px 5px 4px #dedede ; padding: 5px 5px ; } ul .required { color : blue ; } ul li { font-size: 16px ; padding: 5px 5px ; } </style> </head> <body>   <div class="container"> <h4> 使用 json 类型 :</h4> <a href="${ pageContext.request.contextPath }/json/customer" >Java Bean</a> <a href="${ pageContext.request.contextPath }/json/map" >Map</a> </div> </body> </html>

    struts.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    
    <struts>
       <!-- JSON : JavaScript Object Notation -->
        <!-- json-default继承了struts-default并扩展了他 -->
        <package name="json" namespace="/json" extends="json-default">
    
            <default-class-ref class="ecut.results.action.JsonAction" />
    
            <action name="customer" method="bean">
                <result name="success" type="json">
                    <!-- 指定 root 参数,可以确定 只将哪个属性 转换为 JSON 格式 -->
                    <param name="root">customer</param>
                </result>
            </action>
    
            <action name="map" method="map">
                <result name="success" type="json">
                    <param name="root">map</param>
                </result>
            </action>
    
        </package>
    </struts>

     指定 root 参数,可以确定 只将哪个属性 转换为 JSON 格式 

    Action类

    package ecut.results.action;
    
    import java.util.HashMap;
    import java.util.Map;
    import com.opensymphony.xwork2.Action;
    import ecut.results.entity.Customer;
    
    public class JsonAction implements Action {
    
        private Customer customer;
    
        private Map<String, Integer> map;
    
        @Override
        public String execute() throws Exception {
            return SUCCESS;
        }
    
        public String map() throws Exception {
    
            map = new HashMap<>();
    
            map.put("各种粉", 4);
            map.put("藜蒿炒腊肉", 5);
            map.put("瓦罐汤", 3);
            return SUCCESS;
        }
    
        public String bean() throws Exception {
    
            customer = new Customer();
    
            customer.setUsername("张三丰");
            customer.setPassword("hello2017");
    
            return SUCCESS;
        }
    
        public Customer getCustomer() {
            return customer;
        }
    
        public void setCustomer(Customer customer) {
            this.customer = customer;
        }
    
        public Map<String, Integer> getMap() {
            return map;
        }
    
        public void setMap(Map<String, Integer> map) {
            this.map = map;
        }
    
    }

    添加json注解,使密码和确认密码不要进行序列化

     result-type为stream

    1、通过result的type=“stream”来处理。
    2、参数说明:
    • contentType:指定文件类型,默认为text/plain即纯文本.(更多类型可查询tomcat安装目录下的conf目录的web.xml文件,例如application/vnd.ms-excel:Excel下载;application/octet-stream:文件下载),此处用image/jpeg。
    • inputName:指定action中inputStream类型的属性名称,需要getter方法。
    • contentDisposition:指定文件下载的处理方式,包括内联(inline)和附件(attachment)两种方式,而附件方式会弹出文件保存对话框。
    • 否则浏览器会尝试直接显示文件。取值为:attachment;filename="${fileName}",表示文件下载的时候取名为通过EL表达式进行获取。
    • filename="${fileName}"如同inline;filename="${fileName}",浏览器会尝试在线打开它;如果未指定filename属性则以浏览器的页面名作为文件名。
    • bufferSize:输出时缓冲区的大小设置为 attachment 将会告诉浏览器下载该文件,filename 指定下载文件保有存时的文件名,若未指定将会是以浏览的页面名作为文件名,如以 download.action 作为文件名。这里使用的是动态文件名,${fileName}。它将通过 Action 的 getFileName() 获得文件名。也就是说Action里面要有一个getFileName ()的方法。

    3、Serlet实现上传和下载和展示图片测试案例

    下载

    package ecut.response;
    
    import java.io.IOException;
    import java.net.URLEncoder;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet( "/image/down" )
    public class DownloadImageServlet extends HttpServlet {
    
        private static final long serialVersionUID = 448136179136896451L;
    
        @Override
        protected void service(HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            
            request.setCharacterEncoding( "UTF-8" );
            
            response.setCharacterEncoding( "UTF-8" );
            
            //下载文件名称
            String filename = "Koala.jpg" ;
            
            //保存文件名称
            String name = "考拉.jpg" ;
    
            Path source = Paths.get( "D:/" ,  filename );
            
            response.setHeader( "content-type" , "image/jpeg" );
            
            // 响应报头 content-disposition 用来设置 响应正文中的二进制数据是 在浏览器显示 还是 由浏览器下载
            name = URLEncoder.encode( name , "UTF-8" ); // 如果文件名中含有汉字,则需要对汉字进行编码
            
            System.out.println( "编码后:" + name  );
            
            response.setHeader( "content-disposition" , "attachment;filename='" + name + "'" );
            
            // 获得可以向客户端发送二进制数据的字节输出流
            ServletOutputStream out = response.getOutputStream();
            // 将 source 中的内容 "复制" 到 out 对应的输出流,实际上就完成了输出操作
            Files.copy( source, out ) ;
            
        }
        
        
    
    }

    展示

    package ecut.response;
    
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet( "/image/show" )
    public class ShowImageServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1376233444161496825L;
    
        @Override
        protected void service(HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" );
            
            response.setHeader( "content-type" , "image/jpeg" );
            
            // 响应报头 content-disposition 用来设置 响应正文中的二进制数据是 在浏览器显示 还是 由浏览器下载
            response.setHeader( "content-disposition" , "inline" );
            //Path接口表示一个目录或一个文件对应的路径(它可以定位本地系统中的一个文件或目录)
            //Paths类是一个工具类,其中定义了两个静态方法,专门用来返回Path对象:        
            //static Path     get(String first, String... more)转换的路径字符串,或一个字符串序列,当加入形成一个路径字符串, Path。 
            Path source = Paths.get( "D:/Koala.jpg" );
            //FileInputStream in = new FileInputStream( "D:/Koala.jpg" );
            
            // 获得可以向客户端发送二进制数据的字节输出流
            ServletOutputStream out = response.getOutputStream();
            // nio将 source 中的内容 "复制" 到 out 对应的输出流,实际上就完成了输出操作
            Files.copy( source, out ) ;
            
            /*
            byte[] bytes = new byte[32] ;
            int n ;
            while( ( n = in.read( bytes ) ) != -1 ){
                out.write( bytes ,  0 ,  n );
            }
            */
            
        }
        
        
    
    }

    4、Struts2利用 result-type为stream实现下载和展示图片测试案例

    index.jsp

    <%@ page language = "java" pageEncoding = "UTF-8" %>
    <%@ page contentType = "text/html; charset= UTF-8"%>
    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Apache Struts</title> <style type="text/css"> .container { width: 90% ; margin: 10px auto ; box-shadow: 0px 0px 5px 4px #dedede ; padding: 5px 5px ; } ul .required { color : blue ; } ul li { font-size: 16px ; padding: 5px 5px ; } </style> </head> <body> <div class="container"> <h4> 使用 stream 类型 :</h4> <a href="${ pageContext.request.contextPath }/stream/show" >显示</a> <a href="${ pageContext.request.contextPath }/stream/down" >下载</a> <!-- 可以在 URL 中传递被下载的文件名,Action 中的 name 属性负责接收 --> <a href="${ pageContext.request.contextPath }/stream/down?name=考拉.jpg" >下载</a> </div> </body> </html>

    struts.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    
    <struts>
    <package name="stream" namespace="/stream" extends="struts-default">
    
            <default-class-ref class="ecut.results.action.ImageAction" />
    
            <action name="show">
                <param name="storePath">D:/</param>
                <result name="success" type="stream">
                    <!-- inputName 属性用来指定 从哪个输入流中读取 文件 , 默认名称是 inputStream ( InputStream 
                        类型 ) -->
                    <param name="inputName">inputStream</param>
                    <param name="contentType">image/jpeg</param>
                    <param name="contentDisposition">inline</param>
                </result>
            </action>
    
            <action name="down">
                <param name="storePath">D:/</param>
                <result name="success" type="stream">
                    <param name="inputName">inputStream</param>
                    <param name="contentType">image/jpeg</param>
                    <param name="contentDisposition">attachment;filename="${ name }"</param>
                </result>
            </action>
        </package>
    </struts>

    JSP中可以通过${requestScope.name}获取到值,也可以直接${name}按照page-request-session-application 的顺序去查找,因此JSP中的name和Action中一致。在URL中没有指定name的时候Action中的name会给jsp中的name进行赋值,则name必须有getter。如果指定了,要从jsp中的URL接收到来自页面的参数name,则name必须要有setter方法。

    Action类

    package ecut.results.action;
    
    import java.io.InputStream;
    import java.net.URLEncoder;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    import com.opensymphony.xwork2.Action;
    
    public class ImageAction implements Action {
    
        private String storePath; // 文件的存储目录
    
        private String filename; // 被下载的文件的名称
    
        private String name; // 保存文件的名称
    
        private InputStream inputStream;
    
        @Override
        public String execute() throws Exception {
    
            filename = "Koala.jpg";
    
            // inputStream = new FileInputStream( "D:/"" + name ) ;
    
            Path path = Paths.get(storePath, filename);
            inputStream = Files.newInputStream(path);
            if (name != null) {
                name = URLEncoder.encode(name, "UTF-8");
            }else{
                name = filename;
            }
            
            return SUCCESS;
        }
    
        public String getStorePath() {
            return storePath;
        }
    
        public void setStorePath(String storePath) {
            this.storePath = storePath;
        }
    
        public String getFilename() {
            return filename;
        }
    
        public void setFilename(String filename) {
            this.filename = filename;
        }
    
        public InputStream getInputStream() {
            return inputStream;
        }
    
        public void setInputStream(InputStream inputStream) {
            this.inputStream = inputStream;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

    整个过程是通过StreamResult类来实现显示和下载的

    转载请于明显处标明出处

    https://www.cnblogs.com/AmyZheng/p/9207275.html

  • 相关阅读:
    记录Spark 笛卡尔积问题
    接口和继承的区别
    SpringMVC使用可以访问静态资源,但是导致Controller访问失败
    Redis获取缓存异常:java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to XXX
    Spring MVC RedirectAttributes取值方法
    Resource interpreted as Stylesheet but transferred with MIME || DevTools failed to parse SourceMap:
    web.xml中filter加载顺序出现的问题
    kafka 与 rocketmq
    从小到大的部署架构
    SSH框架的简单实现
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9207275.html
Copyright © 2020-2023  润新知