一个spring mvc + mybatis项目里的一些问题
程序员文章站
2022-03-27 15:37:08
...
1. mybatis sql 映射配置文件里的sql语句,如果没有把最后的;号去掉,会报错
ORA-00911: 无效字符
2. Ambiguous mapping found when using class multi level @RequestMapping urls
这个是spring mvc的url映射重复了
3. Jackson 报错:Infinite recursion (*Error)
json支持使用Jackson包,出现如上错误,有说解决方法是:
在返回对象的entity中找到有关联关系的对象,在其get方法上加入
@JsonBackReference
尝试下,无效。controller里返回值是map中还有个map,也许是这个错。后来用自定义的dto对象全部封装起来,就没这个错了。
以下两点参考文档:https://github.com/springside/springside4/wiki/SpringMVC
4. 事务
保证spring-mvc.xml的context:component-scan只扫描Controller,而 applicationContext.xml里的不包含Controller. 否则在applicationContext.xml里的事务就要失效了。方法如下:
spring-mvc.xml:
<context:component-scan base-package="com.mycompany.myproject" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
applicationContext.xml:
<context:component-scan base-package="org.springside.examples.quickstart">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
另外,定义在spring-mvc.xml里的东西,在applicationContext*.xml中是不可见的,想共享的东西最好放在applicationContext.xml那边。
而applicationContext*.xml里的一些BeanPostProccesor,也不会作用到spring-mvc.xml定义/扫描到的Bean上,如果有必要就在spring-mvc.xml里重新定义一次,像Shiro的AOP校验权限。
还有另一种方法,就是全部在spring mvc的配置文件里进行配置。关于applicationContext.xml和<spring-mvc>.xml文件内容不共享的问题稍后作详细介绍。
5. Preparable接口--表单仅包含对象领域部分属性
Struts2有一个很实用的Preparable二次绑定功能: 表单提交时,先绑定一个ID,使用这个ID从数据库里找出对象来,再把表单中的其他属性绑定到这个对象上,对于那些表单中的输入框数量比业务对象的实际属性数少的情况很实用。
其实Spring MVC也有相同的能力, 见quickstart中的UserAdminController.
先用@ModelAttribute标注如下函数。SpringMVC会在执行任何实际处理函数之前,执行该函数并将返回值存为Model Attribute "user"
@ModelAttribute("user")
public User getUser(@RequestParam(value = "id", required = false) Long id) {
if (id != null) {
return accountService.getUser(id);
}
return null;
}
再在save函数里,以@ModelAttribute标注表单处理函数的参数。SpringMVC就会按名称"user"取出前面的对象,然后才进行真正的Binding。
@RequestMapping(value = "update/{userId}", method = RequestMethod.POST)
public String update(@Valid @ModelAttribute("user") User user) {
accountService.updateUser(user);
return "redirect:/admin/user";
}
注意1, 这里有个小坑爹的地方是,这个getUser()会在controller的所有函数前都执行,因此需要进行一下判断RequestParam中是否含id属性的判断,要不你就把update()方法独立到一个Controller中。
注意2, ModelAttribute如果已经占用了"user"这个名字,那些非update()函数的参数里就要躲开这个名字。
6. cookie报错
java.lang.IllegalArgumentException: Control character in cookie value, consider BASE64 encoding your value
cookies只支持ASCII字符,而且不能有逗号,分号,空白。或者以$开头。名字在创建后不能改变。如果要存储中文的,先用URLEcode编码,在存入,取出的时候,用decode解码。
7. 在web容器里保存applicationContext
建一个listener配置到web.xml中去
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class WebAppContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent event) {}
public void contextInitialized(ServletContextEvent event) {
ApplicationContext cxt = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
Const.WEB_APP_CONTEXT = cxt;
}
}
8. 以上是applicationContext.xml文件对应的context,获取<spring-mvc>.xml文件对应的context需使用
ApplicationContext applicatinContext = RequestContextUtils.getWebApplicationContext(request);
关于这两个context的区别,这里有描述:http://starscream.iteye.com/blog/1107036
spring通过在web.xml 中配置ContextLoaderListener 来加载context配置文件,在DispatcherServlet中也可以来加载spring context配置文件,那么这两个有什么区别呢。
ContextLoaderListener中加载的context成功后,spring 将 applicationContext存放在ServletContext中key值为"org.springframework.web.context.WebApplicationContext.ROOT"的attribute中。(servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context));可以通过WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)或WebApplicationContextUtils.getWebApplicationContext(servletContext)方法来获取对应的applicationContext。
DispatcherServlet加载的context成功后,如果 publishContext属性的值设置为true的话(缺省为true) 会将applicationContext存放在org.springframework.web.servlet.FrameworkServlet.CONTEXT. + (servletName)的attribute中。
例如 web.xml中配置如下
<servlet>
<servlet-name>mvcServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring/config/applicationContextMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
则对应的applicationContext的attribute key值为org.springframework.web.servlet.FrameworkServlet.CONTEXT.mvcServlet。
在每次request请求时,DispatcherServlet会将此applicationContext存放在request中attribute值为 org.springframework.web.servlet.DispatcherServlet.CONTEXT中(request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,getWebApplicationContext());)。可以通过 RequestContextUtils.getWebApplicationContext 或 WebApplicationContextUtils.getWebApplicationContext(servletContext,attrname)方法 来获取对应的applicationContext。
从上面的分析可以看出,DispatcherServlet所加载的applicationContext可以认为是mvc私有的context,由于保存在servletContext中的key值与通过ContextLoaderListener加载进来的applicationContext使用的key值不相同,因此如果只使用DispatcherServlet加载context的话,如果程序中有地方使用WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) 来试图获取applicationContext时,就会抛出"No WebApplicationContext found: no ContextLoaderListener registered?"的exception。
9. json view的配置
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager">
<bean class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"
p:favorPathExtension="false"
p:favorParameter="true"
p:parameterName="format"
p:ignoreAcceptHeader="true"
p:defaultContentType="text/html">
<property name="mediaTypes">
<props>
<prop key="xml">application/xml</prop>
<prop key="json">application/json</prop>
</props>
<!-- <value>
xml=application/xml
json=application/json
</value>
<map>
<entry key="xml" value="application/xml"/>
<entry key="json" value="application/json"/>
</map> -->
</property>
</bean>
</property>
<property name="viewResolvers">
<list />
</property>
<property name="defaultViews">
<list>
<ref bean="marshallingView" />
<ref bean="mappingJacksonJsonView" />
</list>
</property>
</bean>
<bean id="marshallingView" class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller">
<bean class="org.springframework.oxm.xstream.XStreamMarshaller"/>
</property>
<property name="modelKey" value="model" />
</bean>
<bean id="mappingJacksonJsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
其中props那段配置跟注释掉的内容是一致的,配置方式不同而已。
还有另外的配置方式
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
或者
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="false" />
<property name="ignoreAcceptHeader" value="false" />
<property name="mediaTypes">
<value>
xml=application/xml
json=application/json
</value>
</property>
</bean>
10. Invalid bound statement (not found): com.....UserDao.getUser
出现这个错误是sql映射文件不存在,或sql映射有错误。
11. 数字验证
Double myNumber=23323.3323232323;
Double test=0.3434;
//getInstance()
//返回当前缺省语言环境的缺省数值格式。
String myString = NumberFormat.getInstance().format(myNumber);
System.out.println(myString);
//getCurrencyInstance()返回当前缺省语言环境的通用格式
myString = NumberFormat.getCurrencyInstance().format(myNumber);
System.out.println(myString);
//getNumberInstance() 返回当前缺省语言环境的通用数值格式。
myString = NumberFormat.getNumberInstance().format(myNumber);
System.out.println(myString);
//getPercentInstance() 返回当前缺省语言环境的百分比格式。
myString = NumberFormat.getPercentInstance().format(test);
System.out.println(myString);
//setMaximumFractionDigits(int) 设置数值的小数部分允许的最大位数。
//setMaximumIntegerDigits(int) 设置数值的整数部分允许的最大位数。
//setMinimumFractionDigits(int) 设置数值的小数部分允许的最小位数。
//setMinimumIntegerDigits(int) 设置数值的整数部分允许的最小位数.
NumberFormat format = NumberFormat.getInstance();
format.setMinimumFractionDigits( 3 );
format.setMaximumFractionDigits(5);
format.setMaximumIntegerDigits( 10 );
format.setMinimumIntegerDigits(0);
System.out.println(format.format(2132323213.23266666666));
12. java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String;
getContextPath()方法在servlet 2.5版本才有,因此对于servlet-api的依赖不要写成2.3,有时候有些包没有直接依赖servlet-api 2.3,比如axis,这时就需要排除axis中对于servlet-api 2.3的依赖。
阅读(4655)| 评论(3)
喜欢推荐转载
历史上的今天
- linux防火墙配置2011-12-29 13:26:01
- linux 查看cpu信息2009-12-29 14:59:05
<iframe id="lmid_iframe" style="margin: 0px; padding: 0px; border-width: 0px; border-style: initial; display: block;" src="http://g.163.com/r?site=netease&affiliate=blog&cat=article&type=column590x100&location=1" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="590" height="100"></iframe>
在LOFTER的更多文章
<iframe id="morecontent_frame" style="margin: 10px 0px 10px 5px; padding: 0px; border-width: 0px; border-style: initial; max-width: 780px; display: block;" src="http://www.lofter.com/recommendblog?email=ljhzzyx@163.com" frameborder="0" scrolling="no" width="100%" height="125"></iframe>
关闭
玩LOFTER,免费冲印20张照片,人人有奖! 我要抢>
上一篇: 中山11月份好玩的地方大全
下一篇: Linux zip小知识
推荐阅读
-
从零开始搭建spring mvc + mybatis + memcached+ dubbo\zookper的maven项目
-
从零开始搭建spring mvc + mybatis + memcached+ dubbo\zookper的maven项目
-
spring mvc + mybatis + mysql 调整的一个简单的登录例子
-
Spring 中MVC配置双数据源实现一个java项目同时连接两个数据库的方法
-
Spring 中MVC配置双数据源实现一个java项目同时连接两个数据库的方法
-
一个spring mvc + mybatis项目里的一些问题
-
spring mvc + mybatis + mysql 调整的一个简单的登录例子
评论