`

SpringMVC整合Freemaker

阅读更多

更多信息:http://baike.baidu.com/view/1278430.htm http://freemarker.org 

[color=green]
<!-- Freemarker Maven  dependency-->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.20</version>
</dependency>
<!-- ui.freemarker -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>3.2.4.RELEASE</version>
</dependency>
[/color]

step2.在src/main/resources/conf目錄下新建Freemarker屬性文件freemarker.properties,此屬性文件定義了Freemarker常用的編碼轉換,代碼如下::

tag_syntax=auto_detect
template_update_delay=2
default_encoding=UTF-8
output_encoding=UTF-8
locale=zh_CN
date_format=yyyy-MM-dd
time_format=HH:mm:ss
datetime_format=yyyy-MM-dd HH:mm:ss


step3.在DispatcherServlet上下文配置文件spring-servlet.xml中添加Freemarker所需的配置,代碼如下:


<!-- 配置Freemarker属性文件路径 -->
<bean id="freemarkerConfiguration"        class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="location" value="classpath:conf/freemarker.properties" />
</bean>
<!-- 配置freeMarker模板加载地址 -->
<bean id="freemarkerConfig"        class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
    <!-- 视图解析器会在/WEB-INF/ftl/路径下扫描视图文件-->
    <property name="templateLoaderPath" value="/WEB-INF/ftl/" />
    <property name="freemarkerVariables">
        <map>
            <entry key="xml_escape" value-ref="fmXmlEscape" />
        </map>
    </property>
</bean>
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" />
<!-- 配置freeMarker视图解析器 -->
<bean id="freemakerViewResolver"        class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <property name="viewClass"        value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
    <!-- 所描路径内所有的ftl結尾的文件 -->
<property name="viewNames">
        <array>
            <value>*.ftl</value>
        </array>
</property>
<property name="contentType" value="text/html; charset=UTF-8" />
<property name="exposeRequestAttributes" value="true" />
<property name="exposeSessionAttributes" value="true" />
<property name="exposeSpringMacroHelpers" value="true" />
<property name="requestContextAttribute" value="request" />
<!-- 配置视图解析器优先级 -->
<property name="order" value="1" />
</bean>



step3.1在DispatcherServlet上下文配置文件spring-servlet.xml中添加FreeMaker自定义标签需要的配置 代碼如下:


      <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">  
         <!-- 假设你需要使用freemarker的自定义标签,这里还需要增加这一段 -->  
       <property name="freemarkerVariables" />  
             <!-- 这里配置的是自定义标签,建议命名为XXDirective,有多个就一起在这里配置 
	            <map>  
	            <entry key="courselist" value-ref="courselist"/> 
	            <entry key="channellist" value-ref="channellist"/> 
	            <entry key="upper" value ref="upper"/>          
	            </map>  
       </property>   
    </bean>
 <bean id="courselist" class="com.keweisoft.ecmp.web.label.CourseListDirecitve"/> 
 <bean id="channellist" class="com.keweisoft.ecmp.web.label.TopChannelDirt"/> 
 <bean id="childchanlist" class="com.keweisoft.ecmp.web.label.TopChannelDirt"/> 
 <bean id="upper" class="com.keweisoft.ecmp.web.label.PaymentDirecitive"/> 


import java.io.IOException;
import java.io.Writer;
import java.util.Map;

import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
//把小写的字符转换为大写的字符
public class PaymentDirecitive implements TemplateDirectiveModel {

	
	public void execute(Environment env, Map params, TemplateModel[] loopVars,
			TemplateDirectiveBody body) throws TemplateException, IOException {
		// 检查参数是否传入
		if (!params.isEmpty()) {
			throw new TemplateModelException(
					"This directive doesn't allow parameters.");
		}
		if (loopVars.length != 0) {
			throw new TemplateModelException(
					"This directive doesn't allow loop variables.");
		}
		// 是否有非空的嵌入内容
                //2015、6、11修改下面被注释的内用 如果以共享变量存储           
                //还是以环境变量存储在显示的时候都出出现BUG
                //前者是一个模板中同一个标签不能用两次并且不能支持当前页面的
                //再次请求;后置不支持一个模板多次使用也会报错
                //去过是一些复杂的业务就是用循环变量这样就可以多次使用多次访问
                //demo我会在本章的最下面带上
		/*env.getConfiguration().setSharedVariable("upper", new PaymentDirecitive());
		env.setVariable("upper", new PaymentDirecitive());*/
		if (body != null) {
			// 执行嵌入体部分,和 FTL 中的<#nested>一样,除了
			// 我们使用我们自己的 writer 来代替当前的 output writer.
			body.render(new UpperCaseFilterWriter(env.getOut()));
		} else {
			throw new RuntimeException("missing body");
		}
	}
	private  class UpperCaseFilterWriter extends Writer {
		private final Writer out;
		public UpperCaseFilterWriter(){out=null;};
		public UpperCaseFilterWriter(Writer out) {
			this.out = out;
		}

		public void write(char[] cbuf, int off, int len) throws IOException {
			char[] transformedCbuf = new char[len];
			for (int i = 0; i < len; i++) {
				transformedCbuf[i] = Character.toUpperCase(cbuf[i + off]);
			}
			out.write(transformedCbuf);
		}

		public void flush() throws IOException {
			out.flush();
		}

		public void close() throws IOException {
			out.close();
		}
	}
}

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
	<head>
	 <title>
	  </title>
	    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
	<body>
        <#-- upper 《entry key="upper" value ref="upper"》这个一个标签  -->
	  <@upper>
	     bar
	     <#-- 这里允许使用所有的 FTL -->
	     <#list ["red", "green", "blue"] as color>
	     ${color}
	     </#list>
	     baaz
	  </@upper>
	</body>
</html>


注意:freemarker里面获取HttpServletRequest没有办法获取,最后还是通过spring的一个listener解决的
在web.xml里面添加下面的配置:

   <listener>  
        <listener-class>  
            org.springframework.web.context.request.RequestContextListener  
        </listener-class>  
    </listener>

     ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();  
      HttpServletRequest request = attr.getRequest();


纠正指令存在的BUG



public class PaymentDirecitive implements TemplateDirectiveModel {
 
	@Resource
	private IPaymentService paymentService;
	@Resource
	private IStationService stationService;
	@Resource(name="freemarkerConfig")
	private FreeMarkerConfigurer freemarkerConfig;
	private static Queue<PaymentDirecitiveModel> queuePayment=new LinkedList<PaymentDirecitive.PaymentDirecitiveModel>();
	private static String PAYMENT_CACHE="stationPayment" ;
	private static BeansWrapper beansWrapper;
	static{
		queuePayment.add(new PaymentDirecitive().new PaymentDirecitiveModel());
		beansWrapper = 
	            new BeansWrapperBuilder(Configuration.VERSION_2_3_22).build();
	}
	String name = null;

	public PaymentDirecitive(String name) {
		this.name = name;
	}

	public PaymentDirecitive() {

	}

	public void execute(Environment env, Map params, TemplateModel[] loopVars,
			TemplateDirectiveBody body) throws TemplateException, IOException {
		// 检查参数是否传入
		/*if (!params.isEmpty()) {
			throw new TemplateModelException("This directive doesn't allow parameters.");
		}
		if (loopVars.length != 0) {
			throw new TemplateModelException("This directivedoesn't allow loop variables.");
		}*/
		Writer out=env.getOut();
		// 是否有非空的嵌入内容
		if (body != null) {
		    ServletRequestAttributes requestAttr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();    
		     HttpServletRequest request = requestAttr.getRequest();  //TODO 模拟数据
		     
		     request.getSession().setAttribute("station",3);
		     
		     HttpSession session=request.getSession();
		     Integer station=(Integer)session.getAttribute("station");
		     Map<String,String> para=new HashMap<String, String>();
		     para.put("stationId",station.toString());//TODO 模拟缓存
		     PaymentDirecitiveModel result=(PaymentDirecitiveModel)session.getAttribute(PAYMENT_CACHE+station);
		     if(null!=result)
		     {
		    	 loopVars[0]=new DefaultObjectWrapper(Configuration.VERSION_2_3_22).wrap(result.getDataView());
		     }else
		     {
		    	 PaymentDirecitiveModel pdm=null;
		    	 List<Map<String,Object>> list=this.paymentService.getPaymentDirectiveByStationId(para);
		    	 for (int i = 0; i < list.size(); i++) {
		    		pdm=queuePayment.peek();
		    		Map<String,Object> tmp=list.get(i);
		    		String stationId=tmp.get("station_id").toString();
					String payId=tmp.get("pay_id").toString();
					String payAccount=tmp.get("pay_account").toString();
					String payStatus=tmp.get("pay_status").toString();
					String platId=tmp.get("plat_id").toString();
					String paymentId=tmp.get("payment_id").toString();
					String partner=tmp.get("partner").toString();
					String privateKey=tmp.get("private_key").toString();
					String logPath=tmp.get("log_path").toString();
					String platName=tmp.get("plat_name").toString();
					String platDesc=tmp.get("plat_desc").toString();
					String logoPath=tmp.get("logo_path").toString();
					String paymentType= tmp.get("payment_type").toString();
					String paymentDesc= tmp.get("payment_desc").toString();
					String attrNameP=tmp.get("attr_name_p").toString();
					String attrValueP=tmp.get("attr_value_p").toString();
					String attrNameI=tmp.get("attr_name_i").toString();
					String attrValueI=tmp.get("attr_value_i").toString();
		    		if(i==0)
		    		{	    	
		    			pdm.setStationId(stationId);
		    			
		    			pdm.setLogoPath(logoPath);
						pdm.setPlatName(platName);
						pdm.setPlatDesc(platDesc);
						
						pdm.setPayAccount(payAccount);
						pdm.setPayStatus(payStatus);
						pdm.setPartner(partner);
						pdm.setLogPath(logPath);
						pdm.setPrivateKey(privateKey);
						
						pdm.setPaymentType(paymentType);
						pdm.setPaymentDesc(paymentDesc);
		    		}
		    		else
		    		{
						pdm.setStationId(stationId);
						
						
					    
						if(pdm.setPlatId(platId))
						{
								pdm.setLogoPath(logoPath);
								pdm.setPlatName(platName);
								pdm.setPlatDesc(platDesc);
							
						}
					/*	else
						{
							queuePayment.add(new PaymentDirecitiveModel());
							i-=1;
							continue ;
						}
						*/
						if(!pdm.setPayId(payId))
						{
							pdm.setPayAccount(payAccount);
							pdm.setPayStatus(payStatus);
							pdm.setPartner(partner);
							pdm.setLogPath(logPath);
							pdm.setPrivateKey(privateKey);
						}
						if(!pdm.setPaymentId(paymentId))
						{
							pdm.setPaymentType(paymentType);
							pdm.setPaymentDesc(paymentDesc);
							
						}
						pdm.setPaymentAttrs(paymentId,attrNameI, attrValueI);
						pdm.setPlatAttrs(platId,attrNameP, attrValueP);
		    		}
				}
		    	session.setAttribute(PAYMENT_CACHE+station,pdm);//TODO 模拟缓存 
		        loopVars[0]=new DefaultObjectWrapper(Configuration.VERSION_2_3_22).wrap(pdm.getDataView());
		     }
		     
			body.render(env.getOut());
		} else {
			throw new RuntimeException("missing body");
		}
	}

	
	private  class PaymentDirecitiveModel
	{
        @SuppressWarnings("unused")
		public String getStationId() {
			return stationId;
		}
		public void setStationId(String stationId) {
			this.stationId = stationId;
		}
		@SuppressWarnings("unused")
		public List<String> getPayId() {
			return payId;
		}
		public Boolean setPayId(String payId) {
			if(!this.payId.contains(payId))
			{
				this.payId.add(payId);
				return false;
			}
			else
		    return true;
			
		}
		@SuppressWarnings("unused")
		public List<String> getPlatId() {
			return platId;
		}
		public Boolean setPlatId(String platId) {
			if(!this.platId.contains(platId))
			{
				this.platId.add(platId);
				return true;
			}
			else
			return false;
		}
		@SuppressWarnings("unused")
		public List<String> getPaymentId() {
			return paymentId;
		}
		public Boolean setPaymentId(String paymentId) {
			if(!this.paymentId.contains(paymentId))
			{
				this.paymentId.add(paymentId);
				return false;
			}
			else
				return true;
		}
		@SuppressWarnings("unused")
		public Map<String, String> getPlatAttrs(String key) {
			return platAttrs.get(key);
		}
		public void setPlatAttrs(String key,String name ,String value) {
			Map<String,String> attr=new HashMap<String, String>();
			attr.put(name, value);
			this.platAttrs.put(key,attr);
		}
		@SuppressWarnings("unused")
		public Map<String, String> getPaymentAttrs(String key) {
			return paymentAttrs.get(key);
		}
		public void setPaymentAttrs(String key,String name ,String value) {
			Map<String,String> attr=new HashMap<String, String>();
			attr.put(name, value);
			this.paymentAttrs.put(key,attr);
		}
		
		private String stationId;
		private List<String> payId=new ArrayList<String>();
		private List<String> payStatus=new ArrayList<String>();
		@SuppressWarnings("unused")
		public List<String> getPayStatus() {
			return payStatus;
		}
		public void setPayStatus(String payStatus) {
			if(!this.payStatus.contains(payStatus))
			this.payStatus.add(payStatus);
		}

        private List<String> logoPath=new ArrayList<String>();
		@SuppressWarnings("unused")
		public List<String> getLogoPath() {
			
			return logoPath;
		}
		public void setLogoPath(String logoPath) {
			if(!this.logoPath.contains(logoPath))
			{
				this.logoPath.add(logoPath);	
			}
			
		}
        @SuppressWarnings("unused")
		public List<String> getPartner() {
			return partner;
		}
		public void setPartner(String partner) {
			if(!this.partner.contains(partner))
			this.partner.add(partner);
		}

		private List<String> platName =new ArrayList<String>();
		@SuppressWarnings("unused")
		public List<String> getPlatName() {
			return platName;
		}
		public void setPlatName(String platName) {
			if(!this.platName.contains(platName))
			this.platName.add(platName);
		}
		private List<String> privateKey=new ArrayList<String>();
        @SuppressWarnings("unused")
		public List<String> getPrivateKey() {
			return privateKey;
		}
		public void setPrivateKey(String privateKey) {
			if(!this.privateKey.contains(privateKey))
			this.privateKey.add(privateKey);
		}
        @SuppressWarnings("unused")
		public List<String> getPlatDesc() {
			return platDesc;
		}
		public void setPlatDesc(String platDesc){
			if(!this.platDesc.contains(platDesc))
			this.platDesc.add(platDesc);
		}

		private List<String> logPath=new ArrayList<String>();
		@SuppressWarnings("unused")
		public List<String> getLogPath() {
			return logPath;
		}
		public void setLogPath(String logPath) {
			if(!this.logoPath.contains(logPath))
			this.logPath.add(logPath);
		}
		private List<String> paymentType=new ArrayList<String>();
        @SuppressWarnings("unused")
		public List<String> getPaymentType() {
			return paymentType;
		}
		public void setPaymentType(String paymentType) {
			if(!this.paymentType.contains(paymentType));
			this.paymentType.add(paymentType);
		}
        private List<String>paymentDesc=new ArrayList<String>();
		@SuppressWarnings("unused")
		public List<String> getPaymentDesc() {
			return paymentDesc;
		}
		public void setPaymentDesc(String paymentDesc) {
			if(!this.paymentDesc.contains(paymentDesc))
			this.paymentDesc.add(paymentDesc);
		}
        private List<String> payAccount=new ArrayList<String>();
		@SuppressWarnings("unused")
		public List<String> getPayAccount() {
			return payAccount;
		}
		public void setPayAccount(String payAccount) {
			if(!this.payAccount.contains(payAccount))
			this.payAccount.add(payAccount);
		}
        private List<HashMap<String, String>> dataView=new ArrayList<HashMap<String, String>>();

		public List<HashMap<String, String>> getDataView() {
			if(this.dataView.size()>0)
			return dataView;
			else
			{
				for(int i=0,len=platId.size();i<len;i++)
				{
					HashMap<String, String> subDataView=new HashMap<String, String>();
					subDataView.put("platId",this.platId.get(i));
					subDataView.put("paymentId",this.paymentId.get(i));
					subDataView.put("payId",this.payId.get(i));
					subDataView.put("src",this.logoPath.get(i));
					this.dataView.add(subDataView);
				}
				return dataView;
			}
		}
		public void setDataView(List<HashMap<String, String>> dataView) {
			if(null==dataView)
			{
				this.dataView.clear();
			}
			else
			this.dataView = dataView;
		}

		private List<String>platDesc=new ArrayList<String>();
		private List<String> partner=new ArrayList<String>();
		private List<String> platId=new ArrayList<String>();
        private List<String> paymentId=new ArrayList<String>();
        private Map<String,Map<String,String>> platAttrs=new HashMap<String,Map<String,String>>();
        private Map<String,Map<String,String>> paymentAttrs=new HashMap<String,Map<String,String>>();
		public PaymentDirecitiveModel() {
			
		}  
		
	}
	
}


<#assign uriPrefix="/ecmp-web">
	  <@payment ;dataView >
	    <#list dataView as items>
	        <#list items?keys as item>
	          
	          <#if item=='src'>
	            <img src="${uriPrefix}${items[item]}"/>
	          
	          <#elseif item=="payId">
	              <input type="radio" name="${item}" value="${items[item]}"/>
              <#else>
                  <input type="hidden" name="${item}" value="${items[item]}"/>	          
	          </#if>
	        </#list>
	     </#list>
	  </@payment>
	  <@payment ;dataView >
	    <#list dataView as items>
	        <#list items?keys as item>
	          
	          <#if item=='src'>
	            <img src="${uriPrefix}${items[item]}"/>
	          
	          <#elseif item=="payId">
	              <input type="radio" name="${item}" value="${items[item]}"/>
              <#else>
                  <input type="hidden" name="${item}" value="${items[item]}"/>	          
	          </#if>
	        </#list>
	     </#list>
	  </@payment>
分享到:
评论

相关推荐

    SpringMVC+Freemaker Demo

    通过这个"SpringMVC+Freemaker Demo",你可以深入了解这两种技术的结合使用,以及它们如何协同工作来构建一个完整的Web应用。实际操作过程中,可以进一步学习异常处理、国际化、缓存等高级话题,提升自己的开发能力...

    ext + spring Json view + springMVC + Freemaker

    "ext + spring Json view + springMVC + Freemaker"的组合提供了一种强大的解决方案,它整合了多种技术,以实现丰富的用户界面、灵活的数据处理和高效的视图渲染。下面我们将深入探讨这些技术及其相互作用。 1. **...

    基于注解的springmvc 整合freemarker的入门例子

    这是一个基于eclipse+springmvc+freemarker+注解的入门例子,是一个war包,import到eclipse就应该可以直接运行,但是确保maven环境到存在;我做为一个入门者,是参照了...

    freemarker与springmvc整合的例子

    **FreeMarker与SpringMVC整合基础** FreeMarker是一个强大的模板引擎,它被广泛应用于Web开发中,用于生成动态HTML或其他格式的文档。SpringMVC是Spring框架的一部分,它是一个轻量级的MVC(Model-View-Controller...

    IDEA+MAVEN+springMVC+mybatis+mySQL+freemaker

    【描述】"IDEA+MAVEN+springMVC+mybatis+mySQL+freemaker整合的框架" 提到的整合意味着这些组件被协同配置,以实现高效且可维护的Web应用开发。这种整合通常涉及以下步骤: 1. **IDEA配置**:在IntelliJ IDEA中,...

    spring mvc整合thymeleaf示例

    thymeleaf,我个人认为是个比较好的模板,性能也比一般的,比如freemaker的要高,而且把将美工和程序员能够结合起来,美工能够在浏览器中查看静态效果,程序员可以在应用服务器查看带数据的效果。 thymeleaf是一个...

    SpringMVC+JPA+Freeemarker

    **整合SpringMVC、JPA和FreeMarker** 在本项目中,SpringMVC作为Web层的控制器,负责接收HTTP请求,调用业务逻辑,并返回结果。JPA则作为数据访问层,处理与数据库的交互,通过Spring的Data JPA模块,可以方便地创建...

    Spring4.0.2Hibernate4.3Freemarker2.3.20 bootstrap整合例子

    Spring4 SpringMVC4 Hibernate4 Freemarker Bootstrap3 整合的小DEMO,主要就是一个登录页面,加一个主页面,然后实现增删改查,还有分页的功能 说明:在项目的doc下有数据库文件,新建数据库名为 db_shf,编码设为...

    mvc_action:项目中的功能技术点,整合到SpringMVC的示例

    业余时间,整合以前项目技术,创建springMVC示例,目前升级到4.3.13版本,您的宝贵意见,是我们进步的动力。 项目说明 项目基于maven的多profile环境配置,打包时需要选择(test/pro/dev)打包运行的环境。 **项目特点*...

    api-master:api-master是springMVC项目,基于maven多模块和dubbo的rpc方式整合使用

    api-master是springMVC项目,基于maven多模块依赖,采用dubbo远程调用,目前spring升级到4.3.13版本,欢迎大家提出意见,您的宝贵意见,是我们进步的动力。 项目说明 项目基于maven的多profile环境配置,打包时需要...

    SpringMVC+Spring+Mybatis三大框架综合练习[MySQL/AJAX/IDEA]

    springmvc框架---&gt;ssm三大框架整合---&gt;maven---&gt;SVN/GIT---&gt;hibernate框架---&gt;struts2框架---&gt;linux---&gt;SSM项目综合小练习---&gt;SpringBoot---&gt;SpringCloud---&gt;Redis---&gt;MongoDB---&...

    基于SpringBoot+LayUI+Freemarker+Mybatis的通用后台管理系统源码.zip

    基于SpringBoot+LayUI+Freemarker+Mybatis的通用后台管理系统源码.zip 完整代码,可运行 。...SpringMVC+Spring+SpringBoot+LayUI+freemarker 运行环境 IDEA【或者Eclipse】 + Tomcat6以上 + Redis + MySQL5

    Spring MVC and FreeMarker Sample

    在提供的压缩包`Freemarker_SpringMVC_example`中,包含了完整的示例代码。通过阅读和运行这些代码,你可以更深入地理解Spring MVC与FreeMarker的整合过程,以及它们在实际项目中的应用。 总结来说,Spring MVC和...

    FreeMarker开发指南

    - **与WebWork整合**: FreeMarker可以与其他MVC框架如WebWork、SpringMVC等整合。 5. **高级方法** - **自定义方法**: 可以创建自定义的FreeMarker函数以扩展其功能。 - **自定义Transforms**: 自定义转换器...

    生产实习报告_李响1151

    1. **SSM框架整合**:SSM是Java Web开发中常用的三大框架组合,Spring提供了依赖注入和事务管理,SpringMVC负责处理HTTP请求和响应,Mybatis则用于数据库操作。通过整合这三大框架,可以实现高效、灵活的业务逻辑...

    beetl-core

    - 易于整合:Beetl可以很方便地与多种Web框架整合,如SpringMVC、JFinal、Struts、Nutz、Jodd、Servlet等。 - 支持模板单独开发和测试:即使在没有M(Model)和C(Controller)的情况下,也能够开发和测试模板。 - ...

    JAVA面试题[秒杀/Redis/MongoDB/SpringBoot/SpringCloud]

    ssm三大框架整合---&gt;maven---&gt;SVN/GIT---&gt;hibernate框架---&gt;struts2框架---&gt;linux---&gt;SSM项目综合小练习---&gt;SpringBoot---&gt;SpringCloud---&gt;Redis---&gt;MongoDB---&gt;FreeMaker---&gt;...

    SVN和GIT详讲视频

    springmvc框架---&gt;ssm三大框架整合---&gt;maven---&gt;SVN/GIT---&gt;hibernate框架---&gt;struts2框架---&gt;linux---&gt;SpringBoot---&gt;SpringCloud---&gt;Redis---&gt;MongoDB---&gt;Freemaker---&gt;Nginx...

    EasyUI框架详讲[jQuery]

    springmvc框架---&gt;ssm三大框架整合---&gt;maven---&gt;SVN/GIT---&gt;hibernate框架---&gt;struts2框架---&gt;linux---&gt;SSM项目综合小练习---&gt;SpringBoot---&gt;SpringCloud---&gt;Redis---&gt;MongoDB---&...

    正则表达式详讲

    springmvc框架---&gt;ssm三大框架整合---&gt;maven---&gt;SVN/GIT---&gt;hibernate框架---&gt;struts2框架---&gt;linux---&gt;SSM项目综合小练习---&gt;SpringBoot---&gt;SpringCloud---&gt;Redis---&gt;MongoDB---&...

Global site tag (gtag.js) - Google Analytics