@Validated怎么在非restcontroller使用层使用

博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Jfinal在非controller层中的声明式事务控制
你好,想跟你请教个问题:
你好,波总,我又来了。。。。
我在网上搜了下,jfinal的声明式事务,大多是在controller里做的。我觉得这样设计,不太合理吧
目前我这边的架构是这样的,controller只做请求转发,外带一些简单的数据封装,和struts2的action层差不多
controller接到请求后,转发给service,这个层是专门做事务用的,每个方法都是一个事务,确保原子性
那现在问题就来了,我怎么在service中,使用声明式事务来进行事务的管理和控制。就类似spring的声明式事务一样,加一个@Transactional就行了。
麻烦多指教
事务为啥不直接看JFinal的文档 要在网上搜呢
--- 共有 1 条评论 ---
文档上只写了对action的事务控制。那如果一个action中所有的操作,在我的业务中,被划分为了2个事务,怎么做。其实也就是说,不想声明式事务依赖于action。
& & &如果想在非 controller 上使用声明式事务,需要在其之上引入 &AOP,通常需要引入一个 IOC,再通过 xml或者 annotation 将 AOP 与需要被代理类进行装配,这势必增大了配置量、代码量,严重拖慢开发效率。当然还可以在字节码层面动态生成 AOP 切面代码,这种方式不利于程序调试。jfinal 用 Interceptor实现的 AOP 就是为了消除大量的xml与annotation而生的,在易用性、灵活性上都有过仔细考量。建议直接使用jfinal 拦截器做事务,或者用 Db.tx(...) 来做。
& & AOP 本来就是独立出来的,业务层不需要知道 AOP 在哪里,AOP紧靠service或controller在本质上并无差别,如果要找差别的话:紧靠service层做事务 AOP会让事务开启的时间稍晚一些,带来略微的性能提升,其实controller中的代码是简单的控制代码所耗性能对于业务层来说可以忽略不计,所以在 controller 上做声明式事务是jfinal权衡后最佳的选择。
& & &AOP&希望贴近 service 来做是理论化、学术化的诉求,通常软件开发是工程性的活动,理论化与学术化不经济也不实用。
--- 共有 2 条评论 ---
: 必然可以,你可以让需要成功的事务这样做:Db.getConfig().getThreadLocalConnection().commit(); 可以在中途就先提交一个事务,不过这种需求从来没有碰到过,将这个 action 拆分成两个更好
那如果,用户点击一个按钮,到了controller层。但是根据我的业务需求,这不是一个事务,而是2个事务,允许其中的一个失败,另一个成功。那如果是这样的场景,是不是就不行了?
如果一定要集成spring 的事务,请参考我这个
代码:http://git.oschina.net/319licheng/jfinal_spring_demo
http://my.oschina.net/u/811979/blog/358819
--- 共有 1 条评论 ---
我不想集成spring啊,我就安安静静的在service加上一行简单的代码,实现声明式事务。随便再做一个美男子
引用来自“无争”的评论 如果一定要集成spring 的事务,请参考我这个
代码:http://git.oschina.net/319licheng/jfinal_spring_demo
http://my.oschina.net/u/811979/blog/358819
那你只能自己去实现了1533人阅读
spring(42)
http://www.cnblogs.com/wangtale/p/3688205.html
1.新增文件
package com.library.
import org.springframework.beans.BeansE
import org.springframework.context.ApplicationC
import org.springframework.context.ApplicationContextA
public class ApplicationContextHelper implements ApplicationContextAware {
private static ApplicationContext appCtx;
public void setApplicationContext( ApplicationContext applicationContext ) throws BeansException {
appCtx = applicationC
public static Object getBean( String beanName ) {
return appCtx.getBean( beanName );
public static &T& T getBean(Class&T&
return (T)appCtx.getBean(clz);
2.在spring.xml中的最后加入
&bean id="SpringApplicationContext" class="com.library.common.ApplicationContextHelper"&&/bean&
3.调用代码
UserService us=ApplicationContextHelper.getBean(UserService.class);SpringMVC中参数校验使用教程
我的图书馆
SpringMVC中参数校验使用教程
一、环境准备在项目中添加以下依赖gradleorg.hibernate:hibernate-validator:5.3.5.Final1maven&dependency&
&groupId&org.hibernate&/groupId&
&artifactId&hibernate-validator&/artifactId&
&version&5.3.5.Final&/version&
&/dependency&12345如果是SpringBoot项目,只需要引入web的starter即可,里面包含了所需依赖二、常用的校验注解及示例
//该参数必须为空
@Null(message = "无需ID")
//根据正则校验手机号是否是由数字组成
@Pattern(regexp = "^\\d{11}$", message = "手机格式不正确,不是11位")
//校验该对象是否为null
//对于String来说,空字符串可通过校验,所以String应该使用@NotBlank进行校验,此处仅做示例而已。
@NotNull(message = "联系人不能为空")
private String friendN
//校验对象是否是空对象,可用于Array,Collection,Map,String
@NotEmpty(message = "家庭成员不能为空")
//校验长度,可以用于Array,Collection,Map,String
@Size(min = 4, max = 8, message = "用户名长度错误 by size")
//校验长度,只能用于String
@Length(min = 4, max = 8, message = "用户名长度错误 by length")
//javax校验
@Max(value = 200, message = "年龄一般不会超过200 by max")
@Min(value = 1, message = "年龄一般不能小于1 by min")
//hibernate校验,效果等同
@Range(min = 0, max = 200, message = "年龄范围在0-200之间 by range")
//校验参数是否是False, 相反的是@AssertTrue
@AssertFalse(message = "用户初始化无需冻结")
//String专用
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 12, message = "密码长度不对")
//使用自定义校验注解-&校验时间
@Past(message = "生日只能为以前的时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
//校验Email
@Email(message = "邮件地址不正确")
private S1234567891011121314151617181920212223242526272829303132333435363738394041424344454647三、校验类方法中的普通参数在类上加@Validated注解在参数上加上校验注解以controller层作示例如下:@Validated
@RestController
@RequestMapping(value = "/user")
public class UserController {
* 校验请求参数
@GetMapping
public String getUser(@Size(min = 5, max = 8, message = "用户名长度超出限制") String username) {
}12345678910111213四、校验类方法中的自定义对象在类上加@Validated注解(同普通参数一样都需要加)在参数上加@Valid,(或者加@Validated也是可以的)@Validated
@RestController
@RequestMapping(value = "/user")
public class UserController {
* 校验请求中的自定义对象
@PostMapping
public UserDTO saveUserOuter(@RequestBody @Valid UserDTO userDTO) {
return userDTO;
}12345678910111213143.在自定义对象中的属性上加上校验注解public class UserDTO {
//该参数必须为空
@Null(message = "无需ID")
//根据正则校验手机号是否是由数字组成
@Pattern(regexp = "^\\d{11}$", message = "手机格式不正确,不是11位")
//校验该对象是否为null
//对于String来说,空字符串可通过校验,所以String应该使用@NotBlank进行校验,此处仅做示例而已。
@NotNull(message = "联系人不能为空")
private String friendN
//校验对象是否是空对象,可用于Array,Collection,Map,String
@NotEmpty(message = "家庭成员不能为空")
//校验长度,可以用于Array,Collection,Map,String
@Size(min = 4, max = 8, message = "用户名长度错误 by size")
//校验长度,只能用于String
@Length(min = 4, max = 8, message = "用户名长度错误 by length")
//javax校验
@Max(value = 200, message = "年龄一般不会超过200 by max")
@Min(value = 1, message = "年龄一般不能小于1 by min")
//hibernate校验,效果等同
@Range(min = 0, max = 200, message = "年龄范围在0-200之间 by range")
//校验参数是否是False, 相反的是@AssertTrue
@AssertFalse(message = "用户初始化无需冻结")
//String专用
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 12, message = "密码长度不对")
//使用自定义校验注解-&校验时间
@Past(message = "生日只能为以前的时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
//校验Email
@Email(message = "邮件地址不正确")
getter ....
}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152五、关于@Valid和@Validated的区别联系一直对@Valid和@Validated这两个注解非常疑惑,不知道怎么区分和使用。1.包位置&- @Valid: javax.validation, 是javax,也是就是jsr303中定义的规范注解&- @Validated: org.springframework.validation.annotation, 是spring自己封装的注解。2.功能&@Valid就不用说了,是jsr303的规范。我们打开@Validated的源码,可以看到以下注释,Variant of JSR-303's {@link javax.validation.Valid}, supporting the
specification of validation groups. Designed for convenient use with
Spring's JSR-303 support but not JSR-303 specific.123大致意思就是说@Validated是@Valid的一个变种,扩展了@Valid的功能,支持group分组校验的写法。&那么我们对于@Valid和@Validated就可以这么理解:&1. 能用@Valid的地方通常可以用@Validated替代。&2. 需要使用分组校验的时候使用@Validated注解。六、分组校验我们有一个用户DTO,其中有id,username两个属性。当保存时,id不需要有值,由数据库自动生成,我们使用@Null注解校验。当更新时,id需要有值,根据ID去更新用户名,我们使用@NotNull注解校验。无论是保存用户还是更新用户,都需要校验用户名,我们使用@NotBlank注解校验。UserGroupValidDTOpublic class UserGroupValidDTO {
public interface SaveGroup extends Default {}
public interface UpdateGroup extends Default {}
@Null(groups = {SaveGroup.class}, message = "不需要传入用户ID")
@NotNull(groups = {UpdateGroup.class}, message = "用户ID不能为空")
@NotBlank(message = "用户名不能为空")
//Setter Getter ...
}123456789101112131415定义相应类型的公开接口(SaveGroup,UpdateGroup),给每个校验注解指定groups属性,如果不指定则默认为javax.validation.groups.Default.class。我们让SaveGroup和UpdateGroup继承了Default, 那么三个接口之间的关系类似如下:save --& SaveGroup |--&id
|--&Default --& username @NotBlank
update--& UpdateGroup |--&id @NotNull
|--&Default --& username @NotBlank12345UserController@Validated
@RestController
@RequestMapping(value = "/user")
public class UserController {
* 分组校验:保存用户,不能传ID
@PostMapping("/save")
public void validSaveUser(@RequestBody @Validated(value = UserGroupValidDTO.SaveGroup.class) UserGroupValidDTO userDTO) {
//save user
* 分组校验:更新用户信息,需要传ID
@PostMapping("/update")
public void validUpdateUser(@RequestBody @Validated(value = UserGroupValidDTO.UpdateGroup.class) UserGroupValidDTO userDTO) {
//update user
}123456789101112131415161718192021在方法参数的对象上加@Validated属性,填写Value为对应的接口的class即可,这时候访问不同的接口就会进行不同的校验了。七、自定义校验注解有时候默认提供的校验注解无法满足我们的需要,我们需要自定义。例如现有校验注解不支持java8中的LocalDateTime。那么接下来我们自定义一个校验LocalDateTime的注解。该注解判断传入的时间是否是一个过去的时间。1.创建校验注解/**
* @author kingboy--
* @desc ${DESCRIPTION}.
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PastTimeValidate.class)
public @interface PastDate {
String message();
Class&?&[] groups() default { };
Class&? extends Payload&[] payload() default { };
}12345678910111213141516172.编写校验规则&校验规则也就是枚举PastDate中指定的validateBy属性/**
* @author kingboy--
@CommonsLog
public class PastTimeValidate implements ConstraintValidator&PastDate, LocalDateTime& {
public void initialize(PastDate constraintAnnotation) {
log.info("init enum PastDate");
public boolean isValid(LocalDateTime localDateTime, ConstraintValidatorContext context) {
return localDateTime.isBefore(LocalDateTime.now()) ? true : false;
}123456789101112131415161718写完这些,我们就可以像@Past对Date校验一样使用@PastDate对LocalDateTime进行校验了。可以参考我的查看完整示例,示例中额外包含了校验异常的捕捉方式。版权声明:本文为博主原创文章,转载请注明来源,顺便点个赞呗 https://blog.csdn.net/KingBoyWorld/article/details/
TA的最新馆藏
喜欢该文的人也喜欢在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
如题,这是自定义标签 这里获取不到biz
public class FormatTimeTaglib extends BodyTagSupport {
@Autowired
private UserBiz uB
// serialVersionUID:{描述属性}
private static final long serialVersionUID = -6930958L;
public int doStartTag() throws JspException {
if(NullUtils.stringIsNull(time)){
return SKIP_BODY;
System.out.println("############uBiz : "+(uBiz==null));
return EVAL_BODY_INCLUDE;
public interface UserBiz extends GenericDao&User&{
public boolean user_exists(final String email,final String pwd);
UserBizImpl
@Transactional
public class UserBizImpl extends GenericDaoImpl&User& implements UserBiz {
@Resource UserTimelineBiz utlB
@Resource UserMedalBiz umB
@Resource MedalBiz medalB
public boolean user_exists(String email, String pwd) {
GenericDao
public interface GenericDao&T& {
private void save();
GenericDaoImpl
@Transactional
public abstract class GenericDaoImpl&T& implements GenericDao&T&{
protected Class&T& entityClass = GenericsUtils.getSuperClassGenricType(this.getClass());
@PersistenceContext protected EntityM
public void save(){
&?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:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.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-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"&
&context:component-scan base-package="com.kk" /&
&!-- 必须要加 --&
&mvc:annotation-driven /&
&mvc:default-servlet-handler /&
&mvc:resources location="/resources/" mapping="/resources/**" /&
&context:annotation-config /&
&bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close"&
&!-- 驱动名称 --&
&property name="DriverClassName" value="com.mysql.jdbc.Driver" /&
&!-- 基本属性 url、user、password --&
&property name="url"
value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8" /&
&property name="username" value="root" /&
&property name="password" value="root" /&
&!-- 配置初始化大小、最小、最大 --&
&property name="initialSize" value="1" /&
&property name="minIdle" value="1" /&
&property name="maxActive" value="20" /&
&!-- 配置获取连接等待超时的时间 --&
&property name="maxWait" value="60000" /&
&!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --&
&property name="timeBetweenEvictionRunsMillis" value="60000" /&
&!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --&
&property name="minEvictableIdleTimeMillis" value="300000" /&
&property name="validationQuery" value="SELECT 'x'" /&
&property name="testWhileIdle" value="true" /&
&property name="testOnBorrow" value="false" /&
&property name="testOnReturn" value="false" /&
&!-- 打开PSCache,并且指定每个连接上PSCache的大小 --&
&property name="poolPreparedStatements" value="true" /&
&property name="maxPoolPreparedStatementPerConnectionSize"
value="20" /&
&!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计 --&
&property name="filters" value="stat" /&
&!-- JPA实体工厂配置 --&
&bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&
&property name="dataSource" ref="dataSource" /&
&!-- 扫描实体路径 --&
&property name="packagesToScan" value="com.kk.entity" /&
&property name="jpaVendorAdapter"&
&bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"&
&property name="showSql" value="true" /&
&/property&
&property name="jpaProperties"&
&!--设置外连接抓取树的最大深度 --&
&prop key="hibernate.max_fetch_depth"&3&/prop&
&prop key="hibernate.jdbc.fetch_size"&18&/prop&
&prop key="hibernate.jdbc.batch_size"&10&/prop&
&!-- 自动建表类型 validate|create|create-drop|update --&
&prop key="hibernate.hbm2ddl.auto"&update&/prop&
&!-- 是否显示SQL --&
&prop key="hibernate.show_sql"&true&/prop&
&!-- 显示SQL是否格式化 --&
&prop key="hibernate.format_sql"&false&/prop&
&!-- 关闭二级缓存 --&
&prop key="hibernate.cache.provider_class"&org.hibernate.cache.NoCacheProvider&/prop&
&/property&
&!-- 配置 jdbcTemplate --&
&bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate"&
&property name="dataSource"&
&ref bean="dataSource" /&
&/property&
&!-- 事务 --&
&bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
lazy-init="true"&
&property name="entityManagerFactory" ref="entityManagerFactory" /&
&tx:annotation-driven transaction-manager="transactionManager" /&
&!-- 对模型视图名称的解析,即在模型视图名称添加前后缀,在requestmapping输入的地址后自动调用该类进行视图解析 --&
&bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"&
&property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" /&
&property name="prefix" value="/WEB-INF/" /&
&property name="suffix" value=".jsp"&&/property&
&!-- annotation默认的方法映射适配器 --&
&bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /&
&bean id="handlerAdapter"
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /&
&bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/&
&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_2_5.xsd"
id="WebApp_ID" version="2.5"&
&display-name&question&/display-name&
&!-- logback
&context-param&
&param-name&logbackConfigLocation&/param-name&
&param-value&classpath:logback.xml&/param-value&
&/context-param& --&
&!-- encoding --&
&filter-name&CharacterEncodingFilter&/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-mapping&
&filter-name&CharacterEncodingFilter&/filter-name&
&url-pattern&/*&/url-pattern&
&/filter-mapping&
&!-- &listener&
&listener-class&ch.qos.logback.ext.spring.web.LogbackConfigListener&/listener-class&
&/listener&
&!-- Spring view分发器 --&
&servlet-name&dispatcher&/servlet-name&
&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&
&init-param&
&param-name&contextConfigLocation&/param-name&
&param-value&classpath:beans.xml&/param-value&
&/init-param&
&load-on-startup&1&/load-on-startup&
&/servlet&
&servlet-mapping&
&servlet-name&dispatcher&/servlet-name&
&url-pattern&/&/url-pattern&
&/servlet-mapping&
&/web-app&
求高手帮忙啊
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
&context:component-scan base-package="com.kk" /&
这个代表只扫这个目录下的Bean,加上你其它的包就好了,例如:
&context:component-scan base-package="com.kk" /&
&context:component-scan base-package="com.kk.service" /&
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
上面说的不对吧
&context:component-scan base-package="com.kk" /&
这个use-default-filters默认是true,会扫描该包和子包的所有类的
建议你用@Resource,不要用Autowired
你在spring配置文件中,已经用了&context:component-scan /&这个标签了,也就是隐式地在内部注册了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor这两个bean了,所以就不再需要&context:annotation-config /&了,引用下spring的原文:
The use of &context:component-scan& implicitly enables the
functionality of &context:annotation-config&. There is usually no
need to include the &context:annotation-config& element when using
&context:component-scan&.
用@Service的时候,最好标明名称,如@Service("userBiz")
说的有不对的,指出来哈,虽然没解决你问题
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
@Resource, 会按名字来寻找合适的Bean.
@Autowired, 会先按名字来找, 如果找不到就按类型来找
在你的Code中, @Service里没有名字, 所以Spring 会自己去生成bean的名字
Spring 的 javadoc里又说:
p&If the annotation's value doesn't indicate a bean name, an appropriate
* name will be built based on the short name of the class (with the first
* letter lower-cased). For example:
com.xyz.FooServiceImpl -& fooServiceImpl
也就是说如果你的class的名字是 UserTimelineBizImpl, 那么spring 会生成一个名叫userTimelineBizImpl的bean;
但你用@Resource UserTimelineBiz utlBiz 来标记的时候, @Resource是找不到叫utlBiz的bean的
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
在标签中如果使用spring注入,需要继承org.springframework.web.servlet.tags.RequestContextAwareTag这个类在类中使用 this.getRequestContext().getWebApplicationContext().getBean(YourBean.class);获取Bean
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
@Transactional
该答案已被忽略,原因:
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。

我要回帖

更多关于 nsviewcontroller使用 的文章

 

随机推荐