spring-springmvc-mybatis-shiro项目介绍

spring-springmvc-mybatis-shiro项目介绍

在之前的mybatis整合项目之后,新增日志、简单集成shiro,之前的代码不予展示与介绍,想了解的请参考mybatis整合项目
项目代码获取:https://github.com/pysasuke/s…

项目结构

java:代码

  • controller:控制层,ShiroUserController,主要包含登录及几个页面跳转

    @RequestMapping("/login")
    public String login(ShiroUser shiroUser, HttpServletRequest request) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(shiroUser.getUsername(), shiroUser.getPassword());
        try {
            subject.login(token);//会跳到我们自定义的realm中
            request.getSession().setAttribute("user", shiroUser);
            log.info(shiroUser.getUsername() + "登录");
            return "success";
        } catch (UnknownAccountException e) {
            request.getSession().setAttribute("user", shiroUser);
            return "login";
        } catch (IncorrectCredentialsException e) {
            request.getSession().setAttribute("user", shiroUser);
            request.setAttribute("error", "用户名或密码错误!");
            return "login";
        }
    }
  • service:业务处理层,包含一个impl包,Service以接口类型存在,impl包下存放Service接口的实现类,ShiroUserServiceImpl包含用户、角色、权限相关操作

@Service("shiroUserService")
public class ShiroUserServiceImpl implements ShiroUserService {
    @Resource
    private ShiroUserMapper shiroUserMapper;

    public ShiroUser getByUsername(String username) {
        return shiroUserMapper.getByUsername(username);
    }

    public Set<String> getRoles(String username) {
        return shiroUserMapper.getRoles(username);
    }

    public Set<String> getPermissions(String username) {
        return shiroUserMapper.getPermissions(username);
    }
}
  • dao:数据库交互层

  • model:实体对象层

  • realm: 自定义Realm(shiro相关)

public class MyRealm extends AuthorizingRealm {

    @Resource
    private ShiroUserService shiroUserService;

    // 为当前登陆成功的用户授予权限和角色,已经登陆成功了
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {

        String username = (String) principals.getPrimaryPrincipal(); //获取用户名
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(shiroUserService.getRoles(username));
        authorizationInfo.setStringPermissions(shiroUserService.getPermissions(username));
        return authorizationInfo;
    }

    // 验证当前登录的用户,获取认证信息
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal(); // 获取用户名
        ShiroUser shiroUser = shiroUserService.getByUsername(username);
        if (shiroUser != null) {
            AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(shiroUser.getUsername(), shiroUser.getPassword(), "myRealm");
            return authcInfo;
        } else {
            return null;
        }
    }
}

resources:配置文件

  • application.xml:spring配置文件入口,加载spring-config.xml

  • spring-mvc.xml:springmvc配置相关文件

  • spring-config.xml:加载其他集成的配置文件,这里加载spring-mybatis.xml、spring-shiro.xml和db.properties

  • spring-mybatis.xml:mybatis相关配置文件

  • spring-shiro.xml:shiro配置相关文件

   <!-- 自定义Realm -->
    <bean id="myRealm" class="com.py.realm.MyRealm"/>

    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="myRealm"/>
    </bean>

    <!--自定义退出路径-->
    <bean id="logout1" class="org.apache.shiro.web.filter.authc.LogoutFilter">
        <property name="redirectUrl" value="/shiro/user/index"/>
    </bean>

    <!-- Shiro过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,这个属性是必须的 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 身份认证失败,则跳转到登录页面的配置 -->
        <property name="loginUrl" value="/shiro/user/login"/>
        <!-- 权限认证失败,则跳转到指定页面 -->
        <property name="unauthorizedUrl" value="/shiro/user/unauthorized"/>
        <!-- Shiro连接约束配置,即过滤链的定义 -->
        <property name="filterChainDefinitions">
            <value>
                /shiro/user/logout = logout <!--与操作指令key(logout)对应-->
                /shiro/user/login=anon  <!--登录不拦截-->
                /shiro/user/person*=authc  <!--表示需认证才能使用-->
                <!--注意URL Pattern里用到的是两颗星,这样才能实现任意层次的全匹配-->
                /shiro/user/student*/**=roles[student]  <!--访问需要student角色-->
                <!--多参时必须加上引号,且参数之间用逗号分割-->
                /shiro/user/teacher*/**=perms["user:create"] <!--访问需要user:create权限-->
            </value>
        </property>
        <property name="filters">
            <map>
                <entry key="logout" value-ref="logout1"/> <!--操作指令(logout)与过滤器(LogoutFilter拦截器id)对应-->
            </map>
        </property>
    </bean>

    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- 开启Shiro注解 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>
  • db.properties:数据库相关参数

  • log4j.properties:日志相关配置

###Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG
log4j.rootLogger=info, console, log, error

###Console ###
#输出到控制台
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %d %p[%C:%L]- %m%n

### log ###
#输出到文件
log4j.appender.log = org.apache.log4j.DailyRollingFileAppender
#日志编码设置
log4j.appender.log.Encoding=UTF-8
#文件路径(绝对路径)
log4j.appender.log.File = E:/my_project/spring-springmvc-mybatis/logs/log.log
#true为追加,false为覆盖,默认为true
log4j.appender.log.Append = true

#针对DEBUG级别以上的日志,低于DEBUG级别的日志不显示,这里设置为DEBUG没有意义
log4j.appender.log.Threshold = DEBUG
log4j.appender.log.DatePattern='.'yyyy-MM-dd

#指定布局模式
log4j.appender.log.layout = org.apache.log4j.PatternLayout
log4j.appender.log.layout.ConversionPattern = %d %p[%c:%L] - %m%n


### Error ###
log4j.appender.error = org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.File = E:/my_project/spring-springmvc-mybatis/logs/error.log
log4j.appender.error.Append = true
log4j.appender.error.Threshold = ERROR 
log4j.appender.error.DatePattern='.'yyyy-MM-dd
log4j.appender.error.layout = org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern =%d %p[%c:%L] - %m%n

###控制台打印sql配置
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
  • mapping:存放mybatis映射文件,以UserMapper.xml为例

<!--与dao中的接口类对应-->
<mapper namespace="com.py.dao.UserMapper">

    <select id="getById" resultType="com.py.model.User">
        select id,username,password,email from user where id=#{id,jdbcType=BIGINT}
    </select>

</mapper>

webapp:web相关

  • web.xml

 <!-- shiro过滤器定义 -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
            <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>

 其他文件

logs:日志存放

  • error.log:记录error级别日志

  • log.log:记录其他日志

deploy:部署文件,sql

  • update.sql

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `t_permission`
-- ----------------------------
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission` (
  `id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  `permissionname` varchar(100) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES ('1', '1', 'user:create');
INSERT INTO `t_permission` VALUES ('2', '2', 'user:update');

-- ----------------------------
-- Table structure for `t_role`
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `rolename` varchar(20) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ('1', 'teacher');
INSERT INTO `t_role` VALUES ('2', 'student');

-- ----------------------------
-- Table structure for `t_user`
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) COLLATE utf8mb4_bin NOT NULL,
  `password` varchar(20) COLLATE utf8mb4_bin NOT NULL,
  `role_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES ('1', 'admin', 'admin', '1');
INSERT INTO `t_user` VALUES ('2', 'test', '123456', '2');

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) COLLATE utf8mb4_bin NOT NULL,
  `password` varchar(32) COLLATE utf8mb4_bin NOT NULL,
  `email` varchar(32) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', '张三', '123456', '835852265@qq.com');

pom.xml:maven相关

        <!-- 日志相关 begin-->
        <!--不加会报异常:应该是某包的依赖
               Property 'filters' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/log4j/Priority-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <!--不加会报异常:应该是springframework.web的依赖
            严重: Exception sending context destroyed event to listener instance of class org.springframework.web.context.ContextLoaderListener
            java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <!--slf4j-log4j12:链接slf4j-api和log4j中间的适配器-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!-- 日志格式化end -->

        <!--shiro相关-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-all</artifactId>
            <version>${shiro-version}</version>
        </dependency>

        <!--lombok插件相关-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.8</version>
        </dependency>
    原文作者:pysasuke
    原文地址: https://segmentfault.com/a/1190000011001391
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞