概述
前面两章收集了一些java 国际化相关api用法,以及spring MVC对国际化的支持。今天打算采用spring MVC搭建一套支持国际化的demo环境(采用的Spring MVC版本为:4.3.1.RELEASE),代码已经放到github,地址请见文章结尾。
主要整合内容包括:
1、view层采用的Freemaker。
2、使用自定义的formatter,对日期、货币等进行转化。
springMVC 相关配置
web.xml 配置:主要包含三部分,“Spring 容器的配置”、“Spring mvc 配置”、“spring 字符集处理配置”。完整的内容如下:
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>locale-demo</display-name> <!-- step1 Spring 容器启动器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- spring 容器配置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-config.xml</param-value> </context-param> <!-- step2 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> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- step3 spring character encoding --> <filter> <filter-name>Character Encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
Spring容器对应的配置文件是:spring-config.xml ,SpringMVC对应的配置文件是spring-mvc.xml。spring-config.xml 可以手动配置bean、指定属性配置文件(.properties)、以及制定其他子配置文件,如:数据库配置文件、工具类配置文件、外部接口配置文件等。本次demo环境,只是整合框架,具体内容根据项目需要再添加。
spring-config.xml内容如下:
<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"> <!-- 加载属性配置文件,主要为spring bean实例化 提供配置支持--> <bean id="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:spring-locale.properties</value> </list> </property> </bean> <!--导入其他所需的配置文件 --> <!-- <import resource="spring/*.xml" /> 配置文件尽量根据模块进行拆分--> </beans>
在手动注入bean时,往往我们需要一些配置参数,比如:数据库用户名、密码等,这些参数都可以提前配置到属性配置文件spring-locale.properties中。本次demo spring-locale.properties为空,根据业务需要添加。
SpringMVC对应的配置文件spring-mvc.xml,是本次讲解的重点。整合freemaker、以及国际化支持等都在该配置文件中体现,内容如下:
<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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" default-autowire="byName"> <mvc:annotation-driven /> <mvc:default-servlet-handler /> <context:component-scan base-package="com.sky.locale.demo.controller" > <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <mvc:resources mapping="/css/**" location="/css/" /> <mvc:resources mapping="/*.html" location="/" /> <!-- Freemarker属性配置--> <bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="location" value="classpath:freemarker.properties"/> </bean> <bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape" /> <!-- Freemarker配置--> <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="freemarkerSettings" ref="freemarkerConfiguration"/> <property name="templateLoaderPath"> <value>/WEB-INF/view/</value> </property> <property name="freemarkerVariables"> <map> <entry key="xml_escape" value-ref="fmXmlEscape" /> </map> </property> </bean> <!-- 配置freeMarker视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/> <property name="contentType" value="text/html; charset=utf-8"/> <property name="cache" value="false"/> <property name = "suffix" value = ".ftl"></property> <property name="exposeRequestAttributes" value="true" /> <property name="exposeSessionAttributes" value="true" /> <property name="exposeSpringMacroHelpers" value="true" /> <property name="requestContextAttribute" value="request"/> </bean> <!-- 图片上传 处理--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="utf-8" /> <property name="maxUploadSize" value="10485760000" /> <property name="maxInMemorySize" value="40960" /> </bean> <!-- 国际化资源文件 --> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basenames" > <list> <value>/WEB-INF/resource/usermsg</value> <value>/WEB-INF/resource/userlabels</value> </list> </property> <property name="defaultEncoding" value="UTF-8"/> </bean> <!-- 本地化配置 --> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"> <property name="cookieName" value="clientlanguage"/> <property name="cookieMaxAge" value="94608000"/> <property name="defaultLocale" value="en" /> </bean> <mvc:annotation-driven conversion-service="formatService" /> <!-- formatter转换配置 --> <bean id="formatService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="formatters"> <set> <!--<bean class="org.springframework.format.number.CurrencyStyleFormatter"> </bean> <bean class="org.springframework.format.number.NumberStyleFormatter"> </bean> <bean class="org.springframework.format.number.PercentStyleFormatter"> </bean> <bean class="org.springframework.format.datetime.DateFormatter"> </bean> --> <bean class="com.sky.locale.demo.formatter.MyDateFormatter" /> <bean class="com.sky.locale.demo.formatter.MyCurrencyFormatter" /> </set> </property> </bean> </beans>
这里主要说下与Freemaker整合的配置,其他关于国际化的配置说明可以参考上一章《java国际化之---springMVC(二)》。
首先看下Freemaker基础配置:
<!-- Freemarker配置--> <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="freemarkerSettings" ref="freemarkerConfiguration"/> <property name="templateLoaderPath"> <value>/WEB-INF/view/</value> </property> <property name="freemarkerVariables"> <map> <entry key="xml_escape" value-ref="fmXmlEscape" /> </map> </property> </bean>
1、freemarkerSettings属性:设置FreeMarker启动属性配置,可以直接配置,也可以配置到属性文件,这次采用的后者。对应的属性配置为:
<!-- Freemarker属性配置--> <bean id="freemarkerConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="location" value="classpath:freemarker.properties"/> </bean>
可以看到读取了属性配置文件freemarker.properties,再来看下中的内容:
#设置标签类型:square_bracket:[] auto_detect:[]<> tag_syntax=auto_detect #模版缓存时间,单位:秒 template_update_delay=0 default_encoding=UTF-8 output_encoding=UTF-8 locale=zh_CN #设置数字格式 ,防止出现 000.00 number_format=\# #变量为空时,不会报错 classic_compatible=true #这个表示每个freemarker的视图页面都会自动引入这个ftl文件。里面定议的就是一些宏,如text文本框,各种form元素 #auto_import="/WEB-INF/templates/index.ftl" as do auto_import="/common/spring.ftl" as spring
具体根据自己的需要调整,这里特别说下auto_import="/common/spring.ftl" as spring,spring.ftl是spring MVC针对Freemaker实现的宏,可以用来读取国际化配置信息等。该文件在spring-webmvc-4.3.1.RELEASE.jar中,具体路径如下:
将该文件copy到WEB-INF/common路径下,还可以根据自己需要修改和新增宏命令。
2、templateLoaderPath属性:配置Freemaker模板文件路径前缀,这里配置的/WEB-INF/view/,注意根目录别配置错了。Spring MVC还支持,多种视图一起使用,一般使用二级目录区分,比如:/WEB-INF/vm/对应velocity,/WEB-INF/jsp/ 对应原始jsp 等等。
3、freemarkerVariables属性:配置Freemaker的自定义标签,这里是个map结构,可以配置多个。
再来看下Freemaker的视图配置:
<!-- 配置freeMarker视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/> <property name="contentType" value="text/html; charset=utf-8"/> <property name="cache" value="false"/> <property name = "suffix" value = ".ftl"></property> <property name="exposeRequestAttributes" value="true" /> <property name="exposeSessionAttributes" value="true" /> <property name="exposeSpringMacroHelpers" value="true" /> <property name="requestContextAttribute" value="request"/> </bean>
如前面所说,你还可以配置多个视图解析器:jsp文件对应的InternalResourceViewResolver解析器,以及velocity对应的VelocityLayoutViewResolver视图解析器,并且Spring MVC允许你配置多个一起使用,根据不同的业务使用不同的视图解析器。
最终配置相关的目录结构如下:
国际化配置文件、以及Freemaker模板文件目录结构如下:
Spring相关配置就说这些吧,关于Freemaker模板文件后面讲解,下面来看看Controller。
Controller控制器代码
Controller相关的代码结构如下:
controller包中对应的是本实例的控制器存放目录,首先来看下UserController,主要处理4类请求:add、save、edit、changelanguage 分别对应:添加用户、保存用户、修改用户、修改语言。具体代码如下:
@Controller public class UserController { @RequestMapping(value="add") public String addUser(Model model) { model.addAttribute(new User()); return "/user/UserForm"; } @RequestMapping(value="save") public String saveUser(@ModelAttribute User user, BindingResult bindingResult, Model model) { UserValidator userValidator = new UserValidator(); userValidator.validate(user, bindingResult); if (bindingResult.hasErrors()) { FieldError fieldError = bindingResult.getFieldError(); System.out.println("Code:" + fieldError.getCode() + ", field:" + fieldError.getField()); return "/user/UserForm"; } // save product here model.addAttribute("org.springframework.validation.BindingResult.user",new BindException(bindingResult)); return "/user/UserInfo"; } /** * * @param model * @return */ @RequestMapping(value="edit") public String editUser(Model model) { //省略从数据库中查询代码 User user = new User(); user.setName("张三"); Date now = new Date(); user.setBirthday(now); user.setMoney(new BigDecimal("12.12")); model.addAttribute("user",user); return "/user/UserForm"; } @RequestMapping(value = "/changelanguage", method = RequestMethod.POST) public void changeLanguage(@RequestParam String new_lang,HttpServletRequest request, HttpServletResponse response) { String msg = ""; try { LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request); if (localeResolver == null) { throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?"); } LocaleEditor localeEditor = new LocaleEditor(); localeEditor.setAsText(new_lang); localeResolver.setLocale(request, response, (Locale)localeEditor.getValue()); msg = "Change Language Success!"; } catch(Exception ex) { msg = "error"; ex.printStackTrace(); } response.setCharacterEncoding(CharEncoding.UTF_8); try { response.getWriter().print(msg); } catch (IOException e) { e.printStackTrace(); } } }
View视图
这里采用的是Freemaker视图,模板文件主要有两个:
首先看下UserForm.ftl(UserInfo.ftl文件内容不再累述):
<!DOCTYPE html> <html> <head> <title><@spring.message "page.user.title"/> </title> <link rel="stylesheet" href="/css/main.css"> </head> <body> <div id="global"> <@spring.message "current.locale"/> : ${request.locale} <br/> <@spring.message "select.language"/> : <span><a href="javascript:void(0)" onclick="changeLanguage('en_GB')">EN</a></span> |<span><a href="javascript:void(0)" onclick="changeLanguage('zh_CN')">CN</a></span> <form name="user" action="save" method="post"> <fieldset> <legend><@spring.message "user.form.name"/></legend> <p> <@spring.bind "user.name" /> <label for="name"><@spring.message "label.userName"/>:</label> <input id="name" type="text" name="name" value="${user.name}" cssErrorClass="error"/> <@spring.showErrors "<br/>" cssClass="error"/> </p> <p> <@spring.bind "user.birthday" /> <label for="birthday"><@spring.message "label.birthday"/>: </label> <input id="birthday" type="text" name="birthday" value="<#if (user.birthday)??> ${(user.birthday?datetime)} </#if>" cssErrorClass="error"/> <@spring.showErrors "<br/>" cssClass="error"/> </p> <p> <@spring.bind "user.money" /> <label for="money"><@spring.message "label.money"/>: </label> <input id="money" type="text" name="money" value="${(user.money?string.currency)!}" cssErrorClass="error"/> <@spring.showLastError classOrStyle="error"/> </p> <p id="buttons"> <input id="reset" type="reset" tabindex="4" value="<@spring.message "button.reset"/>"> <input id="submit" type="submit" tabindex="5" value="<@spring.message "button.submit"/>"> </p> </fieldset> </form> </div> </body> </html> <script type="text/javascript" src="//misc.360buyimg.com/jdf/lib/jquery-1.6.4.js?t=1705252218"></script> <script type="text/javascript"> function changeLanguage(language) { $.ajax({ type: "POST", url:"/changelanguage", data: "new_lang="+language, dataType:"text", async: true, error: function(data, error) {alert("change lang error!"); alert(error)}, success: function(data) { window.location.reload(); } }); } </script>
需要说明以下几点:
1、@spring.message,带有这个标记的标签,表面是本地化消息,这里会根据不同的语言选择不同的国际化配置文件,再根据不同的key选择不同的消息。
比如当前语言为cn_ZH(汉语_中国大陆),对应的配置文件为:usermsg_zh_CN.properties、userlabels_zh_CN.properties。<@spring.message "page.user.title"/>标签中,page.user.title对应的值在userlabels_zh_CN.properties中,配置为:page.user.title=新增用户,该位置的渲染结果即为:“新增用户”。配置文件中的内容,就不贴出来了,感兴趣的可以从文章结尾的github地址中下载。
2、@spring.bind、@spring.showErrors分别为绑定变量,和显示该变量的错误信息。连同1中的@spring.message 这三个标签都是在spring.ftl中定义的。
3、Freemaker国际化支持,${(user.birthday?datetime)}、${(user.money?string.currency)} 会根据不同的语言国家,做不同的格式显示。比如中国,货币显示为:¥12.12;英语英国,货币显示为:£12.12。
其他关于Freemaker的标签说明,参考其官方文档:http://freemarker.org/docs/ref_directive_local.html
日期、货币国际化处理
SpringMVC主要通过定义不同Formatter实现对日期、货币等国际化处理。 Springmvc 自带对日期、货币国际化处理Formatter实现,我们也可以根据自己业务定义自己的Formatter。
自定义的日期时间formatter,MyDateFormatter,调用其可以把String格式的日期转换为Date型,比如:可以把英文环境下的“Jun 13, 2017 9:40:57 PM”,以及中文环境下的” 2017-06-13 21:40:57” 转换为相同的Date,实现如下:
public class MyDateFormatter implements Formatter<Date> { @Override public Date parse(String s, Locale locale) throws ParseException{ DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, locale); System.out.println("parse"); try { return df.parse(s); } catch (ParseException e) { throw new IllegalArgumentException( "invalid date format."); } } @Override public String print(Date date, Locale locale) { DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, locale); System.out.println("format"); return df.format(date); } }
自定义的货币处理formatter,MyCurrencyFormatter,可以实现把不同国家带符号的价格转换为BigDecimal,实现如下:
public class MyCurrencyFormatter implements Formatter<BigDecimal> { /** * 去掉货币符号,并转换为BigDecimal * @param s * @param locale * @return * @throws ParseException */ @Override public BigDecimal parse(String s, Locale locale) throws ParseException { try { NumberFormat curF = NumberFormat.getCurrencyInstance(locale); BigDecimal bd = new BigDecimal(curF.parse(s).toString());//去掉货币符号 return bd; } catch (ParseException e) { //如果没有带单位 转换会失败,但是如果是数字可以成功转换成BigDecimal,主要是springMVC做了兼容处理 throw new IllegalArgumentException( "invalid Currency format."); } } /** * 把BigDecimal 转换为对应国家带货币单位的 字符串格式 * @param bigDecimal * @param locale * @return */ @Override public String print(BigDecimal bigDecimal, Locale locale) { NumberFormat curF = NumberFormat.getCurrencyInstance(locale); return curF.format(bigDecimal); } }
最后通过配置注入到Spring 容器中,当表单提交时就可以实现类型自动转换,配置如下:
<!-- formatter转换配置 -->
<bean id="formatService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<!-- 使用SpringMVC 自带的formatters处理 日期、数字国际化 -->
<!--<bean class="org.springframework.format.number.CurrencyStyleFormatter">
</bean>
<bean class="org.springframework.format.number.NumberStyleFormatter">
</bean>
<bean class="org.springframework.format.number.PercentStyleFormatter">
</bean>
<bean class="org.springframework.format.datetime.DateFormatter">
</bean> -->
<bean class="com.sky.locale.demo.formatter.MyDateFormatter" />
<bean class="com.sky.locale.demo.formatter.MyCurrencyFormatter" />
</set>
</property>
</bean>
示例演示
以上实例demo代码,已经放到github:https://github.com/gantianxing/locale-demo.git,方便以后继续整合使用,也欢迎感兴趣的朋友下载。下载成功后,使用idea打开,打包即可运行。
启动成功后,首先访问http://localhost/add
访问:http://localhost/edit
修改相关数据后,点添加按钮,返回:
点击add页面的‘EN’,可以切换到英文版(ps:如果切换不成功,tomcat版本请换成tomcat8以上):
关于英文版的操作,就不再演示了。感兴趣的可以自己操作下,如有问题请指正,欢迎留言。
以上代码GitHub地址https://github.com/gantianxing/locale-demo.git。
相关推荐
Springboot+Mybatis-plus+ SpringMvc+Shiro+Redis企业级报表后台管理系统Springboot+Mybatis-plus+ SpringMvc+Shiro+Redis企业级报表后台管理系统Springboot+Mybatis-plus+ SpringMvc+Shiro+Redis企业级报表后台管理...
项目描述 在上家公司自己集成的一套系统,用了两个多月的时间完成的:Springboot+Mybatis-plus+ SpringMvc+Shiro+Redis企业级开发系统 Springboot作为容器,使用mybatis作为持久层框架 使用官方推荐的thymeleaf做为...
本科毕设-课设-基于SpringMVC+MyBatis开发学生管理系统.zip本科毕设-课设-基于SpringMVC+MyBatis开发学生管理系统.zip本科毕设-课设-基于SpringMVC+MyBatis开发学生管理系统.zip本科毕设-课设-基于SpringMVC+MyBatis...
在线投票系统-jsp+springMVC+mybatis在线投票系统-jsp+springMVC+mybatis在线投票系统-jsp+springMVC+mybatis在线投票...jsp+springMVC+mybatis在线投票系统-jsp+springMVC+mybatis在线投票系统-jsp+springMVC+mybatis
毕设项目-基于Spring + SpringMvc + MyBatis搭建的学生信息管理系统源码.zip毕设项目-基于Spring + SpringMvc + MyBatis搭建的学生信息管理系统源码.zip毕设项目-基于Spring + SpringMvc + MyBatis搭建的学生信息...
【标题】"SpringMVC精品资源--SSM(spring+springmvc+mybatis)框架 Demo.zip" 提供的是一份关于使用Spring、SpringMVC和MyBatis这三大开源框架集成开发的示例项目。这个压缩包可能包含了完整的源代码、配置文件、...
Spring、SpringMVC、Mybatis、Velocity和Maven是Java Web开发中常用的一组技术栈,它们各自在软件开发的不同层面发挥着重要作用。这个压缩包文件的标题和描述表明,它提供了一个集成这些技术的演示项目,下面我们将...
在现代Java Web开发中,"Maven整合Spring+SpringMVC+Hibernate+SpringDataJPA"是一个常见的架构组合,被广泛应用于构建企业级应用程序。这个组合通常被称为"SSM",其中"M"代表Maven,"S"代表Spring,包括Spring核心...
springMVC+maven+hibernate框架,搭建的过程 可以参考 java进阶(五)------springMVC---springMVC+Hibernate+maven完整搭建运行步骤 http://blog.csdn.net/zzq900503/article/details/49892783
SSM框架,即SpringMVC、Spring和Mybatis的集成,是Java开发中常见的Web应用框架。本教程将深入探讨这三个组件如何协同工作,构建高效、灵活的企业级应用程序。 SpringMVC是Spring框架的一部分,专注于处理HTTP请求...
SSM框架,即Spring、SpringMVC和Mybatis的整合,是Java开发中常见的Web应用框架组合。这个框架集合了Spring的IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)功能,...
第一章 企业项目开发--maven+springmvc+spring+mybatis+velocity整合代码的github地址:https://github.
项目描述 在上家公司自己集成的一套系统,用了两个多月的时间完成的:Springboot+Mybatis-plus+ SpringMvc+Shiro+Redis企业级开发系统 Springboot作为容器,使用mybatis作为持久层框架 使用官方推荐的thymeleaf做为...
微信 java weixin-java-tools-springmvc-master 微信 java weixin-java-tools-springmvc-master
【SpringMVC精品资源--SSM(Spring+SpringMVC+Mybatis)新闻管理系统】是一个集成性的项目,旨在帮助开发者理解并掌握SSM框架在实际应用中的整合与运用。这个资源包可能包含了一系列的代码示例、配置文件以及教程文档...
【标题】中的“SpringMVC精品资源--基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构,提供整套公”表明这是一个关于使用Spring、SpringMVC和Mybatis框架进行分布式敏捷开发的综合资源包。这通常包括示例代码、...
这是网易云课堂里面一个简单的增删改查的项目,感觉挺适合初学者的推荐给大家,在看这个项目时学习到了很多,前端使用了bootstrap,后端使用spring+springmvc+mybatis的rest风格设计
基于java的开发源码-Java SpringMVC+HTML5飞翔的小鸟游戏微信小程序源码.zip 基于java的开发源码-Java SpringMVC+HTML5飞翔的小鸟游戏微信小程序源码.zip 基于java的开发源码-Java SpringMVC+HTML5飞翔的小鸟游戏...
Java基于Spring+SpringMVC+MyBatis实现的学生信息管理系统源码,SSM+Vue的学生管理系统。 Java基于Spring+SpringMVC+MyBatis实现的学生信息管理系统源码,SSM+Vue的学生管理系统。 Java基于Spring+SpringMVC+...