zoukankan      html  css  js  c++  java
  • ASP.NET MVC 4 小项目开发总结

    ASP.NET MVC 4 小项目开发总结

    项目很小,就是一个企业站的前后台,主要包括新闻模块、产品模块、视频模块、留言。没有什么技术上的难点,大部分就是CRUD操作。开始之前评估开发时间为4天,实际coding时间为3天,debug时间为2天,关于debug时间较长的问题,后面有较为详细的分析。

    所用技术和工具

    • Visual Studio 2012
    • ASP.NET MVC 4
    • Entify Framework 5
    • Sqlite
    • Uploadify

    关于ASP.NET MVC 4

    相比MVC 3,个人感觉并没有太大的变化,也许是一些新特性没有用到。

    debug花费时间分析

    除开没有后台页面等其他因素,自身原因分析如下:

    拿到需求后没有进行较为详细的确认

    虽然项目需求简单,但有些地方开始时疏于沟通,最终所省掉的时间还是用在了debug上,甚至更多。

    浏览器兼容性问题

    仅在开发阶段使用chrome浏览器,ie系也仅测试ie10,其余未考虑,后续在浏览器兼容性方面的调试花费了较多的时间。

    例如如下的问题:

    • ie7下jquery.validate报错

      this.attr("novalidate", "novalidate"); 修改为:if (typeof (Worker) !== "undefined") { this.attr('novalidate', 'novalidate'); }

    • ie7下ckeditor的dialog加载iframe窗口高度不正常问题

      尝试了很多网上的解决方案,均不管用,后来使用了一个非常规手段,就是给浏览器加上强制使用ie8模式的meta信息

    • ie8下jquery.validate不起作用

      版本匹配问题:经测试:jquery-1.8.2 with jquery.validate-1.9正常

    uploadify控件使用不是很熟练

    很多api需要现查官方文档,而且官方站点还需FQ。同时在集成uploadify到ckeditor里面的时候,也花费了较多的时间,主要是用在查官方文档上面。这块写了较多的js代码,在后续浏览器兼容性方面调试也比较麻烦。

    • firefox下上传文件出现http error 302

      网上大部分的情况是firefox和chrome同时出现此问题,基本都是说session的原因,但我的环境chrome却没有出问题。我的解决方案比较简单,就是对上传文件的后台action取消授权检查。应该还是跟session有关,更好的解决方案可查询谷歌。

    Entity Framework sqlite数据源适配问题

    主要是开始无法新建sqlite数据源,ef的设计器总是报错,无法通过数据库更新实体等。另外sqlite中文模糊查询问题。

      • 设计器报错问题

        需要到sqlite官网下载合适的数据源驱动程序http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki

      • sqlite中文字符串模糊查询问题

        原来使用的方式:dbcontext.Post.Where(t=>t.Name.Contains(s)),对应的sql语句为charindex,改为:list = context.Database.SqlQuery(string.Format("select * from product where name like '%{0}%'",arcTitle)).AsQueryable();

    版权声明

     
    分类: MVC

    WebService深入剖析

    最近做WebService,最开始用weblogic自带的集成IDE---Eclipse做,,死活出不来,很惨很惨,然后换了个myeclipse8.6来整,使用Tom猫部署。

    基于JAX-WS做,然后使用SOAP消息调用WebService。整了1个多小时,坑。。。

    虽然关于HelloWorld的例子满天飞,但是今天还是从该出起,完整的记录点点滴滴。

    整体工程:

    步骤:

    一:首先加入JAX-WS核心包:

    Book类为实体类,包含基本的ID,名称之类的。

    以其中的UpdateBook作为例子:

    二:创建BookService接口:

    @WebService
    @SOAPBinding(style=SOAPBinding.Style.RPC)
    public interface UpdateBook {
        public String update(int id1, int id2, String name);
    }

     三:创建BookService接口实现类:

    复制代码
    @WebService(endpointInterface = "com.bfchuan.server.UpdateBook")
    public class UpdateBookImpl implements UpdateBook{
    
        @Override
        public String update(int id1, int id2, String name) {
            if(id1==1&id2==2&name.equals("bfc")){
                return "SUCC";
            }else{
                return "Fail";
            }
        }
    
    }
    复制代码
    WebService为注解,该注解能设置很多选项:
    - namewsdl:portType 的名称。缺省值为 Java 类或接口的非限定名称。(字符串)
    - targetNamespace指定从 Web Service 生成的 WSDL 和 XML 元素的 XML 名称空间。缺省值为从包含该 Web Service 的包名映射的名称空间。(字符串)
    - serviceName指定 Web Service 的服务名称:wsdl:service。缺省值为 Java 类的简单名称 + Service。(字符串)
    - endpointInterface指定用于定义服务的抽象 Web Service 约定的服务端点接口的限定名。如果指定了此限定名,那么会使用该服务端点接口来确定抽象 WSDL 约定。(字符串)
    - portNamewsdl:portName。缺省值为 WebService.name+Port。(字符串)
    - wsdlLocation指定用于定义 Web Service 的 WSDL 文档的 Web 地址。Web 地址可以是相对路径或绝对路径。(字符串)


    这些属性如果不设置,在WSDL里面会有默认值。当你每将一个类发布成服务的时候,就会有一个WSDL描述文件。

    第四:增加WSDL文件,在该项目中,该文件如下:
    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3-hudson-390-. -->
    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://server.bfchuan.com/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="UpdateBookImplService" targetNamespace="http://server.bfchuan.com/">
      <types/>
      <message name="update">
        <part name="arg0" type="xsd:int"/>
        <part name="arg1" type="xsd:int"/>
        <part name="arg2" type="xsd:string"/>
      </message>
      <message name="updateResponse">
        <part name="return" type="xsd:string"/>
      </message>
      <portType name="UpdateBook">
        <operation name="update" parameterOrder="arg0 arg1 arg2">
          <input message="tns:update"/>
          <output message="tns:updateResponse"/>
        </operation>
      </portType>
      <binding name="UpdateBookImplPortBinding" type="tns:UpdateBook">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="update">
          <soap:operation soapAction=""/>
          <input>
            <soap:body namespace="http://server.bfchuan.com/" use="literal"/>
          </input>
          <output>
            <soap:body namespace="http://server.bfchuan.com/" use="literal"/>
          </output>
        </operation>
      </binding>
      <service name="UpdateBookImplService">
        <port binding="tns:UpdateBookImplPortBinding" name="UpdateBookImplPort">
          <soap:address location="http://localhost:8080/WebService/UpdateBookImplPort"/>
        </port>
      </service>
    </definitions>
    复制代码

    现在为WSDL做一一的解析:

    1.Type:

    其中Type为空,为什么呢?

    因为Type是用来导入和局部定义web服务交换信息要使用的XML Schema中的简单类型定义-------所有的Web服务将能够随时使用它们,因此,在这个项目中没有必要在这此处放入任何东西。通常来说,WSDL将Type定义成指向外部的schema。

    举个例子,一个需要使用Type的格式如下所示:

    <type>
    <xsd:Schema>
            <xsd:import namespace=http://soacookbook.com/
                SchemaLocation-"http://localhost:7777/Test/HelloWSService?sxd=1"/>
    </xsd:Schema>
    </type>

    2.Message

    WSDL的Message部分包含请求和响应定义,与服务器通信时,要使用的这些请求和响应,你可能会注意到,请求和响应都是各自对应一条信息。请求信息与方法调用名称相同,因此此处采用的是RPC样式。响应名称是按照在操作后附加“Response”的方式给出的,这是JAX-WS的规范的默认方式。

    对于请求:

    <message name="update">
        <part name="arg0" type="xsd:int"/>
        <part name="arg1" type="xsd:int"/>
        <part name="arg2" type="xsd:string"/>
     </message>

    每一个消息,都包含一个part子元素,消息part与方法中的参数类似,具有名称和类型。

    第一个part的名称是arg0,后面的以此类推,这个名字也是客户端调用的时候需要传递参数时候使用的名称(针对SOAP消息调用服务,后面会说到)

    当然这些名称是系统默认的,你可以对它进行定制。

    对于响应:

    <message name="updateResponse">
        <part name="return" type="xsd:string"/>
     </message>

    由于默认参数的样式纸是:wraped,Web服务返回值将封装在单个元素中,名称为return,你可以通过它提取剩余的载荷。

    3.Binding

    WSDL的Binding部分指定于服务器之间的消息传递方式。默认是SOAP,其他高级的选项包括HTTP,JSM,SMTP和TCP。由于通过对UpdateBook接口使用了这个注释:

    @SOAPBinding(style=SOAPBinding.Style.RPC)

    指定希望将服务绑定带SOAP,因此会获得SOAP绑定作为消息传输方式

    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

    这里指定了一个地址,这意味着服务将使用SOAP1.1作为消息的发送和接受的协议。

    还有个属性:style=“rpc”这个,该WSDL编写它是因为这个接口存在以上的那个注解。

    4.Service

    WSDL的Service部分指定服务名称将是UpdateBookImplService 。该名称是在定义服务器的类名称后面加上Service的,这是JAX-WS在没有自定义名字的时候采用的默认命名。

    这儿还指定使用SOAP绑定UpdateBookImplPort端口,端口命名也是默认,规则你懂的。

    该部分带有SOAP的前缀,说明他们来自:"http://schemas.xmlsoap.org/wsdl/soap/"命名空间。

    此处的Location属性指定可以在什么位置调用该服务,以及将使用哪些客户端来调用。

    第五:创建sun-jaxws.xml文件,该文件如下所示:

    复制代码
    <?xml version = "1.0"?>
    <endpoints version="2.0"
        xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime">
        <endpoint name="UpdateBookImplPort"
            implementation="com.bfchuan.server.impl.UpdateBookImpl"
            url-pattern="/UpdateBookImplPort">
        </endpoint>
    </endpoints>
    复制代码

    该文件中,定义了该实现类的访问端口UpdateBookImplPort,即当访问该端口的时候,去找com.bfchuan.server.impl.UpdateBookImpl这儿。

    第七:配置Web.xml文件

    相信这个文件,都不陌生。该文件如下所示:

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" 
        xmlns="http://java.sun.com/xml/ns/javaee" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <servlet>
          <description>JAX-WS endpoint - HelloImplService</description>
          <display-name>HelloImplService</display-name>
          <servlet-name>HelloImplService</servlet-name>
        <!--配置监听--->
    <servlet-class> com.sun.xml.ws.transport.http.servlet.WSServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet>
      <!--这儿的UpdateBookImplPort就是对应sun-jaxws.xml中的UpdateBookImplPort,当访问这个UpdateBookImplPort的时候由
        这儿转向sun-jaxws.xmlUpdateBookImplPort,再由UpdateBookImplPort去找实现类-->
    <servlet-mapping> <servlet-name>HelloImplService</servlet-name> <url-pattern>/UpdateBookImplPort</url-pattern> </servlet-mapping>
    <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <listener> <listener-class> com.sun.xml.ws.transport.http.servlet.WSServletContextListener </listener-class> </listener></web-app>
    复制代码

    于是整个WebService的文件解析完了。

    流程为:

    首先web.xml接收到请求port的请求------然后在sun-jaxws.xml中找对应的port-----找到对应的实现类

    为什么他能找到?WSDL在这儿起了管理作用,定义了相关信息,将某个port和某个service绑定在一起。

    然后就是客户端。客户端我采用SOAP消息调用service的服务。

    现在对SOAP的消息做一个介绍:

    SOAP基于HTTP协议传输,(通常是这样,当然也可一使用JSM和其他机制)。合并防火墙通常允许交换已有HTTP流量,并使用适当机制来处理流量,包括防火墙规则,分支网络等。

    SOAP被创建用来特定满足基于SOAP的WEB服务开发新手的需要,他可以手动操纵SOAP信封。关于SOAP信封的消息,度娘很多了。

    下面基于该例子做一个基于SOAP消息调用服务:

    一:首先创建一个java工程:

    第二:创建一个文件,名字为:book.msg

    内容为:

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soap:Body>
    <ns1:update xmlns:ns1="http://server.bfchuan.com/">
    <arg0>3</arg0>
    <arg1>3</arg1>
    <arg2>bfc</arg2>
    </ns1:update>
    </soap:Body>
    </soap:HelloImpl>
    复制代码

    这儿的arg0分别对于WSDL里的那个参数,还记得吧。

    这里的update对应WSDL里的操作数。

    其他的为SOAP的消息体。

    SOAP的消息载体写好了,现在我们需要发送消息。

    第三:编写java类发送SOAP消息:

    复制代码
    public class UpdateBook {
    
        public static void main(String[] args) {
            doSoapPost();
        }
        
        
        public static void doSoapPost()
        {
            try 
            {
                 //First create the connection
                 SOAPConnectionFactory soapConnFactory = 
                                    SOAPConnectionFactory.newInstance();
                 SOAPConnection connection = 
                                     soapConnFactory.createConnection();
                 
                 //Next, create the actual message
                 MessageFactory messageFactory = MessageFactory.newInstance();
                 SOAPMessage message = messageFactory.createMessage();
                 
                 //Create objects for the message parts            
                 SOAPPart soapPart = message.getSOAPPart();
                 SOAPEnvelope envelope = soapPart.getEnvelope();
                 SOAPBody body = envelope.getBody();       
                 
                //Populate the Message
                StreamSource preppedMsgSrc = new StreamSource( 
                         new FileInputStream("msg/updatebook.msg"));
                soapPart.setContent(preppedMsgSrc);
                 //Save the message
                 message.saveChanges();
                 //Check the input
                 System.out.println("/nREQUEST:/n");
                 message.writeTo(System.out);
                 System.out.println();
                //Send the message and get a reply   
                    
                //Set the destination
                String destination = 
                      "http://localhost:8080/WebService/UpdateBookImplPort";
                //Send the message
                SOAPMessage reply = connection.call(message, destination);
                
    //          Check the output
                System.out.println("/nRESPONSE:/n");
                //Create the transformer
                TransformerFactory transformerFactory = 
                                   TransformerFactory.newInstance();
                Transformer transformer = 
                                transformerFactory.newTransformer();
                //Extract the content of the reply
                Source sourceContent = reply.getSOAPPart().getContent();
                //Set the output for the transformation
                StreamResult result = new StreamResult(System.out);
                transformer.transform(sourceContent, result);
                 //Close the connection            
                 connection.close();
            } 
            catch(Exception e) 
            {
                    System.out.println(e.getMessage());
            }   
        }
    
    
    }
    复制代码

    对于该代码不做过多的说明,当该程序运行后,结果如下所示:

    复制代码
    /nREQUEST:/n
    <?xml version="1.0" encoding="UTF-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soap:Body>
    <ns1:update xmlns:ns1="http://server.bfchuan.com/">
    <arg0>2</arg0>
    <arg1>2</arg1>
    <arg2>"bfc"</arg2>
    </ns1:update>
    </soap:Body>
    </soap:HelloImpl>
    
    
    /nRESPONSE:/n
    
    <?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <
    S:Body><ns2:updateResponse xmlns:ns2="http://server.bfchuan.com/">
      <
    return>Fail</return>
      </
    ns2:updateResponse>
    </
    S:Body>
    </
    S:Envelope>
    复制代码

    前面是发送的SOAP消息

    后面是服务器返回的SOAP消息

    如果说你返回的的是个对象,比如查询某个Book,那么返回的服务的SOAP是如下所示:

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>

    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
      <
    S:Body>
        <
    ns2:byBookResponse xmlns:ns2="http://server.bfchuan.com/">
            <
    return><desc>BBB</desc>
            <
    id>2</id>
            <
    name>AAA</name>
            </
    return>
        </
    ns2:byBookResponse>
      </
    S:Body>
    </
    S:Envelope>
    复制代码

    该SOAP返回的是一个对象。

    最后题外话:

    对于WebService的架构方式,有JAX-WS还有Xfire。对此做个比较:

    1)   用基于jax-wsClient端调用基于XFirejax-wsWebService都没有问题;

    而用基于XFireClient端调用基于XFireWebService存在问题(什么原因目前还不明);

    2)   基于Jax-wsClient端只能通过解析WSDL文档的方式来调用WebService,不可以使用将WebService的接口抓到本地进行掉用的方式;

    基于XFireClient端则能够通过两种方式来调用WebService:(但目前这两种方式只针对XFire发布的WebService

    (1)       WebServiceInterface抓到本地,进行调用;

    (2)       通过得到WebServiceWSDLFile或是WSDLURL,解析WSDL来调用WebService

    3)   基于jax-wsWebServiceClient端可以建立在任何Project中;

    基于XFireWebServiceClient端则必须建立在WebServiceProject中;

    对于非WebServiceProjectProject要想调用基于XFireWebService必须将其Interface抓到本地进行调用;

    4)   基于Jax-ws发布的WebService只发布WSDL文档,

    基于XFireWebService则会发布WSDl+服务接口;

    5)   基于Jax-ws发布的WebService会显示的产生WSDL文档;

    基于XFire发布的WebService则只是在调用时由服务器产生临时的;

       6)Jax-ws设计了监听器机制,在WEB.xml中已经能看到监听类的配置了XFire没有;

     
     
    分类: 程序员
  • 相关阅读:
    Android 之流媒体播放器,广播侧下方这么简单。
    POJ 1146:ID Codes
    NYOJ 47 河问题
    浏览器 HTTP 协议缓存机制详解--网络缓存决策机制流程图
    写给后端程序员的HTTP缓存原理介绍--怎样决定一个资源的Cache-Control策略呢
    浅谈Web缓存-缓存的实现过程详解
    国内各大互联网公司相关技术博客3.0版 (集合腾讯、阿里、百度、搜狐、新浪、网易、360等共29个)
    知名技术团队博客
    【Web缓存机制系列】2 – Web浏览器的缓存机制-(新鲜度 校验值)
    学习是一件艰苦的事情
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3137868.html
Copyright © 2011-2022 走看看