Spring3+mybatis快速开发RESTful web应用

SpringMVC3.0之后的注解配置及RESTful架构可见之前的另一篇帖:springmvc

这里的spring web mvc层的配置采用的就是上篇的配置,所以这里说下spring同mybatis的整合以及其他一些东西。

spring同ibatis的整合是spring提供的,由于mybatis是在spring3.0之后更新的,所以其整合就由mybatis的mybatis-spring.jar自己完成,通过org.mybatis.spring.SqlSessionFactoryBean,配置如下:

<!-- MyBatis配置 -->
<bean id="sqlSessionFactory" class="com.minyond.core.common.mybatis.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <!-- 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
  <property name="typeAliasesPackage" value="com.minyond.modules.*.entity"/>
  <!-- 显式指定Mapper文件位置 -->
  <property name="mapperLocations" value="classpath:/mybatis/com/minyond/modules/**/mapper/*Mapper.xml"/>
</bean>
<!-- 扫描basePackage下所有以@MyBatisRepository标识的 接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="com.minyond.modules" />
  <property name="annotationClass" value="com.minyond.core.common.mybatis.MyBatisRepository"/>
</bean>

给Dao接口添加自定义注解@MyBatisRepository,*Mapper.xml配置的namespace指定对应接口。

Controller的注解,类上的@Controller@RequestMapping,方法上的@RequestMapping,注入service的@AutoWired;

Service的注解,类上有@Component、@Tranditional,查询方法上有@Traditional(readOnly=true),以及注入dao的@AutoWired;

Dao的注解,类上自定义标识@MyBatisRepository。

spring-mvc.xml的配置见上面说的那帖,下面贴出其他配置

applicationContext.xml

<!-- 使用annotation 自动注册bean,并检查@Required,@Autowired的属性已被注入 -->
  <context:component-scan base-package="com.minyond.modules">
    <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>
  
  <!-- MyBatis配置 -->
  <bean id="sqlSessionFactory" class="com.minyond.core.common.mybatis.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <!-- 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
    <property name="typeAliasesPackage" value="com.minyond.modules.*.entity"/>
    <!-- 显式指定Mapper文件位置 -->
    <property name="mapperLocations" value="classpath:/mybatis/com/minyond/modules/**/mapper/*Mapper.xml"/>
  </bean>
  <!-- 扫描basePackage下所有以@MyBatisRepository标识的 接口-->
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.minyond.modules" />
    <property name="annotationClass" value="com.minyond.core.common.mybatis.MyBatisRepository"/>
  </bean>
  
  <!-- 事务管理器配置 -->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>

  <!-- 使用annotation定义事务 -->
  <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> 

  <!-- produce环境 -->
  <beans profile="produce">
    <context:property-placeholder ignore-resource-not-found="true"
      location="classpath*:/jdbc.properties" />  

    <!-- 数据源配置,使用应用内的DBCP数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <!-- Connection Info -->
      <property name="driverClassName" value="${jdbc.driver}" />
      <property name="url" value="${jdbc.url}" />
      <property name="username" value="${jdbc.username}" />
      <property name="password" value="${jdbc.password}" />
      <property name="defaultAutoCommit" value="false" />      
    </bean>
  </beans>
  
  <!-- production环境 -->
  <beans profile="production">
    <context:property-placeholder ignore-resource-not-found="true"
      location="classpath*:/jdbc.properties" />  

    <!-- 数据源配置,使用应用内的Tomcat JDBC连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">      
       <property name="driverClass" value="${jdbc.driver}"></property>
       <property name="jdbcUrl" value="${jdbc.url}"></property>
       <property name="user" value="${jdbc.username}"></property>
       <property name="password" value="${jdbc.password}"></property>
      
       <!-- 详细参数说明参见database-config.properties -->
       <property name="initialPoolSize" value="${c3p0.initialPoolSize}"></property>
       <property name="minPoolSize" value="${c3p0.minPoolSize}"></property>
       <property name="maxPoolSize" value="${c3p0.maxPoolSize}"></property>
       <property name="maxIdleTime" value="${c3p0.maxIdleTime}"></property>
       <property name="acquireIncrement" value="${c3p0.acquireIncrement}"></property>
       <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}"></property>
       <property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}"></property>
       <property name="breakAfterAcquireFailure" value="${c3p0.breakAfterAcquireFailure}"></property>
       <property name="maxStatements" value="${c3p0.maxStatements}"></property>
       <property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}"></property>

    </bean>
  </beans>

web.xml

<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath*:/spring/applicationContext.xml,
			classpath*:/spring/applicationContext-shiro.xml
		</param-value>
	</context-param>
	<context-param>
		<param-name>spring.profiles.default</param-name>
		<param-value>produce</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<filter>
		<filter-name>encodingFilter</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>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<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/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>    
  
  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <listener>
    <listener-class>
      org.springframework.web.context.request.RequestContextListener
    </listener-class>
  </listener>

	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>    
  
	<error-page>
		<exception-type>java.lang.Throwable</exception-type>
		<location>/WEB-INF/view/error/500.html</location>
	</error-page>
	<error-page>
		<error-code>500</error-code>
		<location>/WEB-INF/view/error/500.html</location>
	</error-page>
	<error-page>
		<error-code>404</error-code>
		<location>/WEB-INF/view/error/404.html</location>
	</error-page>

applicationContext-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<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-3.2.xsd"
	default-lazy-init="true">

	<description>Shiro安全配置</description>

	<!-- Shiro's main business-tier object for web-enabled applications -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="shiroRealm" />
	</bean>

	<!-- 項目自定义的Realm -->
	<bean id="shiroRealm" class="com.minyond.modules.base.system.realm.ShiroRealm" depends-on="userDao">
		<property name="userService" ref="userService"/>
	</bean>
	
	<!-- Shiro Filter -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="/" />
		<property name="successUrl" value="/main" />
		<property name="filterChainDefinitions">
			<value>
			  <!--静态资源直接通过-->
        /libs/** = anon
				/login = anon
				/test = anon
				/logout = logout
				/** = authc
			</value>
		</property>
	</bean>
	
	<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
	
</beans>

mybatis.com.minyond.modules.base.classroom.mapper.ClassroomMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace必须指向Dao接口 -->
<mapper namespace="com.minyond.modules.base.classroom.dao.ClassroomDao">
  <!-- 分页查询 -->
  <select id="searchClassroom" resultType="map" parameterType="map">
      select b.rownum_,a.*,c.name as school_name from bd_classroom a,
      (
        select top ${endRow} row_number() over (order by ${sort} ${direction}) as rownum_,id from bd_classroom
        <where>
          <if test="id!=null and id!=''">
            id = '${id}'
          </if>
        </where>
      )b,bd_school c where a.id = b.id and a.school_id = c.id and rownum_ >= ${startRow} order by rownum_ asc
  </select>
  <!-- 查询总数量 -->
  <select id="countClassroom" resultType="Integer" parameterType="map">
      select count(*) from bd_classroom
      <where>
        <if test="id!=null and id!=''">
          id = '${id}'
        </if>
      </where>
  </select>
  <!-- 根据Id查询 -->
  <select id="getClassroomById" resultType="Classroom" parameterType="Long">
      select id, school_id as schoolId,name,code,position,capacity,kind,enabled,remark
      from bd_classroom where id = #{id}
  </select>
  <!-- 新增 -->
  <insert id="saveClassroom"  parameterType="Classroom">
      insert into bd_classroom(
        id,school_id,name,code,position,capacity,kind,enabled,remark)
      values(
        #{id},#{schoolId},#{name},#{code},#{position},#{capacity},#{kind},#{enabled},#{remark})
  </insert>
  <!-- 修改 -->
  <update id="updateClassroom"  parameterType="Classroom">
      update bd_classroom set
        school_id = #{schoolId},
        name = #{name},
        code = #{code},
        position = #{position},
        capacity = #{capacity},
        kind = #{kind},
        remark = #{remark}
      where id = #{id}
  </update>
  <!-- 删除 -->
  <delete id="deleteClassroomById" parameterType="Long">
      delete
        bd_classroom
      where id = #{id}
  </delete>
</mapper>


关于freemarker标签的使用

<tr>
    <td>< @constant.m "workingresume_position"/>: </td>
    <td><@dictionaryDirective code="positionKindDict" name="position" value="${workingResume.po    sition}" />
    </td>
</tr>

@constant及@dictionaryDirective的原理

spring-mvc.xml中freemarker的配置如下:

<bean id="freeMarkerConfigurer"
    class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
      <property name="templateLoaderPath" value="/WEB-INF/view/" />
      <property name="freemarkerVariables">
	      <map>
	        <entry key="schoolDirective" value-ref="schoolDirective"/>
	        <entry key="dictionaryDirective" value-ref="dictionaryDirective"/>
	        <entry key="gradeDirective" value-ref="gradeDirective"/>
	        <entry key="periodDirective" value-ref="periodDirective"/>
          <entry key="subjectDirective" value-ref="subjectDirective"/>
          <entry key="sideDirective" value-ref="sideDirective"/>
	        <entry key="permissionDirective" value-ref="permissionDirective"/>
	        <entry key="commonContext" value="${commonContext}"/>
	        <entry key="personalContext" value="${personalContext}"/>
	        <entry key="exportTemplatePath" value="${exportTemplatePath}"/>
	        <entry key="courseDirective" value-ref="courseDirective"/>
	        <entry key="publisherDirective" value-ref="publisherDirective"/>
	        <entry key="schoolTermDirective" value-ref="schoolTermDirective"/>
	      </map>
      </property>
      <property name="freemarkerSettings">
        <props>
          <prop key="template_update_delay">0</prop>                                              
          <prop key="defaultEncoding">UTF-8</prop>
          <prop key="url_escaping_charset">UTF-8</prop>
          <prop key="locale">zh_CN</prop>
          <prop key="boolean_format">true,false</prop>
          <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
          <prop key="date_format">yyyy-MM-dd</prop>
          <prop key="time_format">HH:mm:ss</prop>
          <prop key="number_format">0.######</prop>
          <prop key="whitespace_stripping">true</prop>
          <prop key="template_exception_handler">ignore</prop>
          <prop key="classic_compatible">true</prop>
          <prop key="auto_import">ftl/pony/index.ftl as ui,/ftl/spring.ftl as constant</prop>
        </props>
      </property>
  </bean>
  
  <!-- 针对freemarker的视图配置 -->
  <bean id="viewResolver"
    class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
      <property name="cache" value="true" />
      <property name="prefix" value="" />
      <property name="suffix" value=".html" />
      <property name="contentType" value="text/html;charset=UTF-8"></property>
      <property name="requestContextAttribute" value="rc" />
      <property name="exposeSpringMacroHelpers" value="true" />
      <property name="exposeRequestAttributes" value="true" />
      <property name="exposeSessionAttributes" value="true" />
  </bean>

而@constant标签的使用,取决于

<prop key="auto_import">ftl/pony/index.ftl as ui,/ftl/spring.ftl as constant</prop>

的配置,文件spring.ftl及各国际化文件*.properties

   类似于@dictionaryDirective标签,实现freemarker提供的接口TemplateDirectiveModel

   当然也是使用spring提供的注解@Component完成创建该标签类实例,

     在实现方法execute内实现自己的逻辑,比如这里就是为页面提供select下单选框标签,并通过下面两行

           Dictionary dictionary = this.dictionaryService.getDictionaryByCode(code);

          List<DictionaryValue> dictionaryValueList = this.dictionaryService.select-                                                                                                                             DictionaryValue(dictionary.getId());

   查询数据库中字典dictionary表,遍历dictionaryValueList将相关kind类型值内容赋予<option>标签,最后将拼接成的html字符串输出到页面便完成了。



通过shiro完成权限控制

shiro提供的注解//@RequiresPermissions("/base/teachermanager/retired/search_retired")

    若无此权限则不能访问相应请求链接。

        @Component

        public class PermissionDirective implements TemplateDirectiveModel

     再借助freemarker提供的以上接口,根据逻辑判断权限,若无相应权限可屏蔽显示相应标签。

shiro的配置在以上的spring-mvc.xml及web.xml均有需要配置的内容。


转载于:https://my.oschina.net/zhupanxin/blog/269060

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值