• spring mvc 总结


    依赖包

    <!-- spring依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.2.9.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>4.2.9.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>4.2.9.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.2.9.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.2.9.RELEASE</version>
        </dependency>
        
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.9.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.2.9.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.2.9.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.9.RELEASE</version>
        </dependency>
        
        <!-- 结束 -->
        
        <!-- slf4j日志依赖,不用log4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.5.8</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.5.8</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.5.8</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>
        
        <!-- servlet运行依赖 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
        
        <!-- jstl标签依赖 -->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        
        <!-- springmvc返回json依赖 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.8.8</version>
        </dependency>
        
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.8.8</version>
        </dependency>
        
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.8</version>
        </dependency>
        
        
        <!-- springmvc文件上传依赖 -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
      
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
      
      <build>
        <plugin> 
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.7</source> 
                <target>1.7</target> 
                <encoding>UTF-8</encoding> 
            </configuration>
        </plugin>
    </build>

    springmvc初始化的方式

    1.web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    
    
        <!-- spring mvc -->
        <servlet>
            <servlet-name>springMvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-mvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>springMvc</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
    
        
    </web-app>

    2.类初始化需要servlet 3.0以上

    public class MyWebApplicationInitializer implements WebApplicationInitializer {
    
        @Override
        public void onStartup(ServletContext container) {
            ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
            registration.setLoadOnStartup(1);
            registration.setInitParameter("contextConfigLocation", "classpath:spring-mvc.xml");
            registration.addMapping("/");
        }
    
    }

    springmvc 配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
    
        
       
        
    
       
         
        <!-- 不用默认的扫描  用自定义的扫描 -->
        <context:component-scan base-package="com.controller" use-default-filters="false">
          <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
          <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
        </context:component-scan>
        
        <!-- 对应的整合spring的配置配置文件不扫描springmvc的注解,为了避免重复扫描创建两个对象 -->
        <!-- <context:component-scan base-package="com.controller">
          <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
          <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
        </context:component-scan> -->
        
        
        <!-- <context:component-scan base-package="com.handler"></context:component-scan> -->
    
        <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
        
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/view/"></property>
            <property name="suffix" value=".jsp"></property>
        </bean>
        
        <!-- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/view/" p:suffix=".jsp" /> -->

    <!--自定义视图-->
        <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
           <property name="order" value="100"></property>
        </bean>

    <!--自定义视图--> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"> <property name="order" value="100"></property> </bean> <!-- <mvc:view-controller path="/success" view-name="/success"/> -->
    <!--静态文件的控制访问交由servlet去处理 比如当访问 /aaa/a.html时直接访问页面 配置后需添加mvc:annotation-driven--> <mvc:default-servlet-handler />

    <!--配置后一些springmvc会初始化一些默认的配置比如异常,返回 json的处理等-->
    <mvc:annotation-driven />

    <mvc:interceptors>
    <!--全局拦截器--> <bean class="com.interceptor.FirstInterceptor"></bean> <mvc:interceptor>
    <!--拦截指定路径--> <mvc:mapping path="/aaaa/"/> <bean class="com.interceptor.SecondInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> <!--SimpleMappingExceptionResolver 自定义异常解析--> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionAttribute" value="myexception"></property> <property name="exceptionMappings"> <props> <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop> </props> </property> </bean> <!-- springmvc上传文件 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"></property> <property name="maxUploadSize" value="5242880"></property> </bean> </beans>
    <context:component-scan base-package="com.jit" resource-pattern="/**/services/**/*.class"></context:component-scan>

     springmvc 不拦截静态资源

    方案一:拦截器中增加针对静态资源不进行过滤(涉及spring-mvc.xml)
    注意:需引入mvc命名空间
    1.  <!-- 添加注解驱动 -->
    2.  <mvc:annotation-driven/>
    3.  <!--
    4.  通过mvc:resources设置静态资源,这样servlet就会处理这些静态资源,而不通过控制器
    5.  设置不过滤内容,比如:css,js,img 等资源文件
    6.  location指的是本地的真是路径,mapping指的是映射到的虚拟路径。
    7.  -->
    8.  <mvc:resources mapping="/css/**" location="/css/"/>

    方案二:使用默认的servlet处理静态资源(涉及spring-mvc.xml,web.xml)

    在spring-mvc.xml中添加:

    1.  <!--启用默认Servlet-->
    2.  <mvc:default-servlet-handler/>

      <mvc:default-servlet-handler/>

     在web.xml中添加:

    1.  <!--增加对静态资源的处理,当前的设置必须在Spring的Dispatcher的前面-->
    2.  <servlet-mapping>
    3.  <servlet-name>default</servlet-name>
    4.  <url-pattern>*.css</url-pattern>
    5.  <url-pattern>/css/*</url-pattern>
    6.  </servlet-mapping>

    方案三:修改spring的全局拦截设置为*.do的拦截(涉及web.xml)

    1.  <!-- 拦截所有请求 -->
    2.  <servlet-mapping>
    3.  <servlet-name>dispatcher</servlet-name>
    4.  <!--<url-pattern>/</url-pattern>-->
    5.  <url-pattern>*.do</url-pattern>
    6.  </servlet-mapping>

    spring获取注解类

     ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);

    拦截器,配置多个拦截器的执行顺序   会先执行第一个拦截器的preHandle 第二个拦截器的preHandle   之后反序

    public class FirstInterceptor implements HandlerInterceptor{
    
        /**
         * 控制器访问后,渲染视图后,通常释放资源
         */
        @Override
        public void afterCompletion(HttpServletRequest arg0,
                HttpServletResponse arg1, Object arg2, Exception arg3)
                throws Exception {
            System.out.println("FirstInterceptor:afterCompletion");
        }
    
        /**
         * 控制器访问后,渲染视图前调用,通常改变请求值
         */
        @Override
        public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
                Object arg2, ModelAndView view) throws Exception {
            //System.out.println(view==null);
            view.addObject("openid", "12121212");
            //arg3.addObject("openid", "123456");
            System.out.println("FirstInterceptor:postHandle");
            
        }
    
        /**
         * 请求控制类之间被调用,通常被用为权限,日志,事物等
         */
        @Override
        public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
                Object arg2) throws Exception {
            System.out.println("FirstInterceptor:preHandle");
            return true;
        }
    
    }

    springmvc  控制类全局异常处理

    /**
     * 全局处理异常
     * @author Administrator
     *
     */
    @ControllerAdvice
    public class HandlerException {
        
        
        @ExceptionHandler({Exception.class})
        public ModelAndView handlerException(Exception e){
            e.printStackTrace();
            ModelAndView view = new ModelAndView("error");
            view.addObject("error",e);
            return view;
        }
    
    }

    自定义异常

    @ResponseStatus(value=HttpStatus.FORBIDDEN,reason="页面没找到")
    public class MyException extends RuntimeException{
    
        private static final long serialVersionUID = 1L;
    
    }

    控制类

    @RequestMapping("/testMyException")
        public String testMyException(){
            int i = 9;
            if(i==9){
                throw new MyException();
            }
            return "hello"; 
            
        }

    自定义视图,比如返回pdf  excel

    @Component
    public class MyView implements View{
    
        @Override
        public String getContentType() {
            return "text/html";
        }
    
        @Override
        public void render(Map<String, ?> model, HttpServletRequest request,
                HttpServletResponse response) throws Exception {
            response.getWriter().write("111111111111111");
            
        }
    
    }

    控制类

    @RequestMapping("/testMyView")
        public MyView testMyView(HttpServletRequest request,HttpServletResponse response,
                HttpSession session,Principal principal,Locale Locale,Writer writer,Reader reader){
            System.out.println("121212");
            //@CookieValue("j")
            return new MyView();
        }

    consumes、produces 示例

    Content-Type   MediaType,即是Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。

     常见的媒体格式类型如下:

    •     text/html : HTML格式
    •     text/plain :纯文本格式      
    •     text/xml :  XML格式
    •     image/gif :gif图片格式    
    •     image/jpeg :jpg图片格式 
    •     image/png:png图片格式

       以application开头的媒体格式类型:

    •    application/xhtml+xml :XHTML格式
    •    application/xml     : XML数据格式
    •    application/atom+xml  :Atom XML聚合格式    
    •    application/json    : JSON数据格式
    •    application/pdf       :pdf格式  
    •    application/msword  : Word文档格式
    •    application/octet-stream : 二进制流数据(如常见的文件下载)
    •    application/x-www-form-urlencoded : <form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

       另外一种常见的媒体格式是上传文件之时使用的:

    •     multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

    value:  指定请求的实际地址, 比如 /action/info之类。
    method:  指定请求的method类型, GET、POST、PUT、DELETE等
    consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;
    produces:    指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回
    params: 指定request中必须包含某些参数值是,才让该方法处理
    headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求

    cousumes的样例:

     
    1. @Controller  
    2. @RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json")  
    3. public void addPet(@RequestBody Pet pet, Model model) {      
    4.     // implementation omitted  
    5. }  

    方法仅处理request Content-Type为“application/json”类型的请求。

    produces的样例:

    1. @Controller  
    2. @RequestMapping(value = "/pets/{petId}", method = RequestMethod.GET, produces="application/json")  
    3. @ResponseBody  
    4. public Pet getPet(@PathVariable String petId, Model model) {      
    5.     // implementation omitted  
    6. }  

    方法仅处理request请求中Accept头中包含了"application/json"的请求,同时暗示了返回的内容类型为application/json;

    springmvc 控制类文件下载

        /**
         * 文件下载
         * @return
         */
        public ResponseEntity<byte[]> down(){
            ResponseEntity<byte[]> responseEntity = null;// = new ResponseEntity<byte[]>(body, headers, statusCode)
            return responseEntity;
        }

    springmvc 控制类数据绑定,可用于表单提交html转义编码放置xss攻击等

    @InitBinder
        public void initBinder(WebDataBinder binder) {
            // String类型转换,将所有传递进来的String进行HTML编码,防止XSS攻击
            binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
                @Override
                public void setAsText(String text) {
                    setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
                }
                @Override
                public String getAsText() {
                    Object value = getValue();
                    return value != null ? value.toString() : "";
                }
            });
            
            // Date 类型转换
            binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
                @Override
                public void setAsText(String text) {
                    setValue(DateUtils.parseDate(text));
                }
            });
            
            // Timestamp 类型转换
            binder.registerCustomEditor(Timestamp.class, new PropertyEditorSupport() {
                @Override
                public void setAsText(String text) {
                    Date date = DateUtils.parseDate(text);
                    setValue(date==null?null:new Timestamp(date.getTime()));
                }
            });
        }

    springmvc    @ModelAttribute

        /**
         * 访问控制类首先被调用会把myUser放到requestScope中,页面可用EL表达式获取,也可以在控制类其他方法中获取,如果表单提交会把u合并
         * @return
         */
        @ModelAttribute("myUser")  
        public User getUser(){
            User u = new User();
            return u;
        }
        
        @RequestMapping("/addUser")
        public String addUser(@ModelAttribute("myUser") User u ){
            return "success";
        }

     springmvc 获取多文件

    boolean isFileUpload = ServletFileUpload.isMultipartContent(request);

    MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) req;

    List<MultipartFile > files = multipartHttpServletRequest.getFiles("files");

    String realPath = req.getSession().getServletContext().getRealPath("/");
     String path =  realPath + "\upload\"+year+"\"+month+"\";

     File filepath = new File(path);
            if (!filepath.exists())
                filepath.mkdirs();
            // 文件保存路径  
            String savePath = path + file.getOriginalFilename();  
            // 转存文件  
            file.transferTo(new File(savePath)); 

    第一种方法:
    
         MultipartFile file = xxx; 
            CommonsMultipartFile cf= (CommonsMultipartFile)file; 
            DiskFileItem fi = (DiskFileItem)cf.getFileItem(); 
    
            File f = fi.getStoreLocation();
    
      会在项目的根目录的临时文件夹下生成一个文件;
    
    第二种方法:
    
        transferTo(File dest);
    
      会在项目中生成一个新文件;
    
    第三种方法:   
    
      File f = (File) xxx 强转即可。前提是要配置multipartResolver,要不然会报类型转换失败的异常。
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="maxUploadSize" value="104857600"/>
            <property name="maxInMemorySize" value="4096"/>
        </bean>
      没试过;
    第四种方法:
      Workbook wb = Workbook.getWorkbook(xxx .getInputStream());
      转换为输入流,直接读取;
    第五种方法:
      byte[] buffer = myfile.getBytes();
      先转换为字节数组,没试过;

    Filter Types 的5中类型:

    1 . annotation  注解           org.springframework.stereotype.Controller        注解名(类型)

    2. assignale  类名或者接口   org.example.someClass 

    3. aspectj    简单点就是就是切面表达式

    4.regex  正则表达式

    5. custom  实现了 org.springframework.core.type.TypeFilter 接口的类型

    复制代码
    <beans>
    <context:component-scan base-package="org.example">
    <context:include-filter type="regex"
    expression=".*Stub.*Repository"/>
    <context:exclude-filter type="annotation"
    expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>
    </beans>
    复制代码

    use-default-filters="false"关闭默认filter

    springmvc 自定义映射规则

    https://segmentfault.com/a/1190000021376498?utm_source=tag-newest

     //自定义消息转换器

    <mvc:annotation-driven>
          <mvc:message-converters register-defaults="true">
                <bean class="com.javazhan.controller.UTF8StringHttpMessageConverter"/>
          </mvc:message-converters>
    </mvc:annotation-driven>

    package com.javazhan.controller;
    
    import org.springframework.http.HttpInputMessage;
    import org.springframework.http.HttpOutputMessage;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.AbstractHttpMessageConverter;
    import org.springframework.http.converter.HttpMessageNotReadableException;
    import org.springframework.http.converter.HttpMessageNotWritableException;
    import org.springframework.util.StreamUtils;
    
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.nio.charset.Charset;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @Author: yandq
     * @Description:
     * @Date: Create in 11:50 2018/4/3
     * @Modified By:
     */
    public class UTF8StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
        public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    
        private volatile List<Charset> availableCharsets;
        private boolean writeAcceptCharset;
    
        public UTF8StringHttpMessageConverter() {
            this(DEFAULT_CHARSET);
        }
    
        public UTF8StringHttpMessageConverter(Charset defaultCharset) {
            super(defaultCharset, new MediaType[]{MediaType.TEXT_PLAIN, MediaType.ALL});
            this.writeAcceptCharset = true;
        }
    
        public void setWriteAcceptCharset(boolean writeAcceptCharset) {
            this.writeAcceptCharset = writeAcceptCharset;
        }
    
        @Override
        public boolean supports(Class<?> clazz) {
            return String.class == clazz;
        }
    
        @Override
        protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
            Charset charset = this.getContentTypeCharset(inputMessage.getHeaders().getContentType());
            return StreamUtils.copyToString(inputMessage.getBody(), charset);
        }
    
        @Override
        protected Long getContentLength(String str, MediaType contentType) {
            Charset charset = this.getContentTypeCharset(contentType);
    
            try {
                return (long)str.getBytes(charset.name()).length;
            } catch (UnsupportedEncodingException var5) {
                throw new IllegalStateException(var5);
            }
        }
    
        @Override
        protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
            if (this.writeAcceptCharset) {
                outputMessage.getHeaders().setAcceptCharset(this.getAcceptedCharsets());
            }
    
            Charset charset = this.getContentTypeCharset(outputMessage.getHeaders().getContentType());
            StreamUtils.copy(str, charset, outputMessage.getBody());
        }
    
        protected List<Charset> getAcceptedCharsets() {
            if (this.availableCharsets == null) {
                this.availableCharsets = new ArrayList(Charset.availableCharsets().values());
            }
    
            return this.availableCharsets;
        }
    
        private Charset getContentTypeCharset(MediaType contentType) {
            return contentType != null && contentType.getCharset() != null ? contentType.getCharset() : this.getDefaultCharset();
        }
    }



  • 相关阅读:
    美国首位女计算机博士荣获今年图灵奖
    此人需要关注一下
    Microsoft的壮大与IBM对Sun的收购
    文章介绍:Sexy Lexing with Python
    程序员的门道
    闲谈:敏捷与否的区分方法、对组织内部人员的现实作用与长远利益
    聊聊最俗的工厂相关话题
    人之患在好为人师
    TIOBE的头头儿和“反Java”的教授
    敏捷的核心究竟是什么
  • 原文地址:https://www.cnblogs.com/jentary/p/6832899.html
Copyright © 2020-2023  润新知