<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] ## 1. 創建SpringBoot項目(整合mybatis) ### 1.1 新建springboot項目 > 1. 新建項目【File】>【New】>【Project】 ![](https://box.kancloud.cn/1def4fc75d9ef8e4ecb96d7a380fd8df_704x662.png) > 2. 選擇【Spring Initializer】> 【next】 ![](https://box.kancloud.cn/8414606ffe29fe2ae510011fd42b9dec_828x812.png) > 3. 填寫項目信息 ![](https://box.kancloud.cn/27bc173606dfd1b3758c615908565382_828x812.png) > 4. 加入web,mybatis,mysql 【NEXT】 ![](https://box.kancloud.cn/f78d7105f87218a75404887fcef3512d_826x796.png) ![](https://box.kancloud.cn/dec9ecfc7864d0a28cebbf8c372d0c5e_828x812.png) > 5. finish > 這樣intellij會自動為我們引入web、mybatis所需要的依賴 ### 1.2 根據表自動生成model,mapper(可選) 使用mybatis-generator根據數據庫表,自動生成model和mapper代碼 #### 1.2.1 修改pom.xml文件,指定生成代碼的保存位置 > 記得新建: > net.aexit.infrastructure.common.mapper > net.aexit.infrastructure.common.model > net.aexit.infrastructure.common.mapper ~~~ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <!-- MyBatis Generator --> <!-- Java接口和實體類,自動生成的存放位置 --> <targetJavaProject>${basedir}/src/main/java</targetJavaProject> <targetXmlProject>${basedir}/src/main/java</targetXmlProject> <targetMapperPackage>net.aexit.infrastructure.common.mapper</targetMapperPackage> <targetModelPackage>net.aexit.infrastructure.common.model</targetModelPackage> <targetXMLPackage>net.aexit.infrastructure.common.mapper</targetXMLPackage> </properties> ~~~ #### 1.2.2 建立文件夾generator,放入jar文件 ![](https://box.kancloud.cn/083f58076397ca5d256c55170c4ba0b8_456x113.png) jar鏈接:https://pan.baidu.com/s/1qZnlxoS 密碼:fcey #### 1.2.3 maven配置pom.xml書寫 mybatis-generator-maven-plugin ~~~ <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile> <overwrite>true</overwrite> <verbose>true</verbose> </configuration> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.40</version> </dependency> <dependency> <groupId>com.xxg</groupId> <artifactId>mybatis-generator-plugin</artifactId> <version>1.0.0</version> <scope>system</scope> <systemPath>${basedir}/src/main/resources/generator/mybatis-generator-plugin-1.0.0.jar</systemPath> </dependency> </dependencies> </plugin> </plugins> <resources> <resource> <directory>src/main/java</directory> <filtering>false</filtering> <includes> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <filtering>false</filtering> </resource> </resources> </build> ~~~ #### 1.2.4 在generator文件夾下編寫generatorConfig.xml文件,固定格式 ~~~ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!--此文件用于從數據庫表結構,自動生成model,自動生成基礎CURD的mapper代碼 mvn mybatis-generator:generate--> <!--<properties resource="./generator/generatorConfig.properties"/>--> <!-- 數據庫驅動包位置,使用maven的方法,這個就不用了 --> <context id="MYSQLTables" targetRuntime="MyBatis3" defaultModelType="flat"> <!-- 生成的Java文件的編碼 --> <property name="javaFileEncoding" value="UTF-8"/> <!-- 格式化java代碼 --> <property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/> <!-- 格式化XML代碼 --> <property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/> <plugin type="com.xxg.mybatis.plugins.MySQLLimitPlugin"></plugin> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <!-- 數據庫鏈接URL、用戶名、密碼 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://192.168.x.xx:3306/test?useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true" userId="test" password="123456"> </jdbcConnection> <javaModelGenerator targetPackage="${targetModelPackage}" targetProject="${targetJavaProject}"/> <sqlMapGenerator targetPackage="${targetXMLPackage}" targetProject="${targetXmlProject}"/> <javaClientGenerator targetPackage="${targetMapperPackage}" targetProject="${targetJavaProject}" type="XMLMAPPER" /> <!-- mvn mybatis-generator:generate --> <table tableName="sys_user"/> </context> </generatorConfiguration> ~~~ #### 1.2.5 命令行生成代碼 > 在pom.xml的同級目錄執行 ~~~ mvn mybatis-generator:generate ~~~ #### 1.2.6 查看生成結果 可以看到自動生成了四個文件 > 1. SysUserMapper.java > 2. SysUserMapper.xml > 3. SysUser的實體類 > 4. SysUserExample,單表復雜數據庫操作模板 有了以上的代碼,針對單表的操作接近100%,不用寫SQL!具體如何用好這四個類,后文詳細講解! 注意:一旦數據庫表結構發生變化,需要重新生成4個文件!請先刪除xml,如:SysUserMapper.xml ,因為追加不覆蓋導致報錯, **會根據駝峰規則生成對象 ** role_id字段對應roleId屬性; role_name對應roleName; **類依然是首字母大寫** ![](https://box.kancloud.cn/0f7609b832be1f53ebd8e994f810ae9d_1699x517.png) #### 1.2.7 如何獲取insert的自增key. 配置,自動生成的代碼是沒有useGeneratedKeys="true" keyProperty="id"這個配置的,需要加上. ~~~ <insert id="insert" parameterType="net.aexit.infrastructure.common.model.SysUser" useGeneratedKeys="true" keyProperty="id"> insert into sys_user (id, user_id, user_name, password, salt, org_id, phone, address, sex, email, remarks, create_date, head_image, status) values (#{id,jdbcType=INTEGER}, #{userId,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{salt,jdbcType=VARCHAR}, #{orgId,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, #{address,jdbcType=VARCHAR}, #{sex,jdbcType=TINYINT}, #{email,jdbcType=VARCHAR}, #{remarks,jdbcType=VARCHAR}, #{createDate,jdbcType=TIMESTAMP}, #{headImage,jdbcType=VARCHAR}, #{status,jdbcType=TINYINT}) </insert> ~~~ ? 獲取 ~~~ this.sysUserMapper.insert(sysUser); return sysUser.getId(); ~~~ 這樣就生成了model,和mapper ![](https://box.kancloud.cn/dd9e23782b9439a925e13bc7ef3cc3c6_638x333.png) ### 1.3 測試mybatis 1. 設置掃描 ~~~ @SpringBootApplication @ComponentScan(basePackages = {"com.aixin"}) public class SpringbootApplication { public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); } } ~~~ 2. 掃描mapper ~~~ package com.aixin.config; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Configuration; /** * Created by dailin on 2018/1/9. */ @Configuration @MapperScan("com.**.mapper") public class MybatisConfig { } ~~~ 3. mapper添加方法 ~~~ Userinfo findByUsername(String userName); ~~~ 4. 配置xml添加SQL ~~~ <select id="findByUsername" parameterType="string" resultMap="BaseResultMap"> SELECT * FROM UserInfo WHERE username=#{userName} </select> ~~~ 5. service 接口 ~~~ package com.tuna.service; import com.tuna.model.Userinfo; public interface UserInfoService { /**通過username查找用戶信息;*/ public Userinfo findByUsername(String username); } ~~~ 實現類 ~~~ package com.tuna.service; import javax.annotation.Resource; import com.tuna.mapper.UserinfoMapper; import com.tuna.model.Userinfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserInfoServiceImpl implements UserInfoService{ @Autowired private UserinfoMapper userinfoMapper; @Override public Userinfo findByUsername(String username) { System.out.println("UserInfoServiceImpl.findByUsername()"); return userinfoMapper.findByUsername(username); } } ~~~ 6. controller ~~~ package com.tuna.controller; import com.tuna.model.Userinfo; import com.tuna.service.UserInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.websocket.server.PathParam; /** * Created by dailin on 2018/1/9. */ @RestController public class Hello { @Autowired private UserInfoService userInfoService; @RequestMapping("/hello") public Userinfo sayHello(){ Userinfo userInfo = userInfoService.findByUsername("admin"); return userInfo; } } ~~~ 7. application.yml 配置 ~~~ server: port: 8090 address: 0.0.0.0 session: timeout: 28800 ################################################# 數據庫訪問配置 # 主數據源,默認的 spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://192.168.56.130:3306/shiro?useUnicode=true&characterEncoding=utf8&autoReconnect=true username: root password: tuna mybatis-plus: configuration: mapUnderscoreToCamelCase: true ~~~ 8. 結果 ![](https://box.kancloud.cn/7e859e48f575b306c8a7c55407ac0531_841x391.png) ## 2. 整合實例 上面創建項目時,自動完成了mybatis的整合 ### 2.1 集成druid 1.添加maven依賴 ~~~ <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.2</version> </dependency> ~~~ 2. 配置數據源application.yml 數據庫訪問配置 ~~~ # 主數據源,默認的 datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://192.168.2.21:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true username: test password: 123456 druid: initialSize: 2 minIdle: 2 maxActive: 30 WebStatFilter: exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*' StatViewServlet: loginUsername: aexit loginPassword: aexit ~~~ 3.查看監控,輸入用戶名密碼,上文 訪問:http://localhost:20001/druid/ ![](https://box.kancloud.cn/2b37d39866e2681c8fe8bafcac65b6e2_495x285.png) ### 2.2 整合beetl 1. 引入maven ~~~ <dependency> <groupId>com.ibeetl</groupId> <artifactId>beetl</artifactId> <version>2.7.21</version> </dependency> ~~~ * beetl提供了starter的方式集成springboot,但是經過試驗,和druid有沖突!因為beetl-starter不但集成了模板,還集成了beetlSQL,和druid數據庫連接池發生沖突! * 所以不引入帶starter的maven包! 2. 配置beetl基礎信息 ~~~ package com.aixin.tuna.webtest.config; import org.beetl.core.resource.ClasspathResourceLoader; import org.beetl.ext.spring.BeetlGroupUtilConfiguration; import org.beetl.ext.spring.BeetlSpringViewResolver; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Properties; @Configuration public class BeetlTplConfig extends BeetlGroupUtilConfiguration { @Bean(initMethod = "init", name = "beetlConfig") public BeetlGroupUtilConfiguration getBeetlGroupUtilConfiguration() { BeetlGroupUtilConfiguration beetlGroupUtilConfiguration = new BeetlGroupUtilConfiguration(); ClasspathResourceLoader classpathResourceLoader = new ClasspathResourceLoader(); beetlGroupUtilConfiguration.setResourceLoader(classpathResourceLoader); Properties beetlConfigProperties = new Properties(); //是否檢測文件變化,開發用true合適,但線上要改為false beetlConfigProperties.setProperty("RESOURCE.autoCheck","true"); //自定義標簽文件Root目錄和后綴 beetlConfigProperties.setProperty("RESOURCE.tagRoot","templates/tags"); beetlConfigProperties.setProperty("RESOURCE.tagSuffix","tag"); beetlGroupUtilConfiguration.setConfigProperties(beetlConfigProperties); return beetlGroupUtilConfiguration; } @Bean(name = "beetlViewResolver") public BeetlSpringViewResolver getBeetlSpringViewResolver(@Qualifier("beetlConfig") BeetlGroupUtilConfiguration beetlGroupUtilConfiguration) { BeetlSpringViewResolver beetlSpringViewResolver = new BeetlSpringViewResolver(); beetlSpringViewResolver.setPrefix("/templates/"); beetlSpringViewResolver.setSuffix(".html"); beetlSpringViewResolver.setContentType("text/html;charset=UTF-8"); beetlSpringViewResolver.setOrder(0); beetlSpringViewResolver.setConfig(beetlGroupUtilConfiguration); return beetlSpringViewResolver; } @Override public void initOther() { // groupTemplate.registerFunctionPackage("shiro", new ShiroKit()); // groupTemplate.registerFunctionPackage("tool", new ToolUtil()); } } ~~~ 例子 ~~~ 控制層 @Controller public class LoginController { @RequestMapping(value = "/", method = RequestMethod.GET) public String index(Model model) { model.addAttribute("name", "代林"); return "login"; } } ~~~ 顯示層,放在resources/templates目錄下面的login.html ~~~ <html lang="en"> <head> <title>beetl servlet</title> </head> <body> 這是${name}的第一個beetl例子 </body> </html> ~~~ 訪問 ![](https://box.kancloud.cn/3a49a56daaf18561dfdbbd9a122b1a1e_1174x187.png) ### 2.3 整合shrio #### 2.3.1 引入shrio依賴 <shiro.version>1.4.0</shiro.version> ~~~ <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>${shiro.version}</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro.version}</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>${shiro.version}</version> <exclusions> <exclusion> <artifactId>slf4j-api</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions> </dependency> ~~~ #### 2.3.2 原理講解 > ShiroConfiguration.java: > shiro啟動時候的初始化工作,比如哪些是需要認證,哪些不需要認證;緩存配置設置;shiro權限數據在頁面展示時整合需要的模板套件配置,等等。 > ShiroRealm.java: > shiro權限認證的具體實現代碼,因為shiro本身只提供攔截路由,而具體如何數據源則由用戶自己提供,不同的項目不同的要求,要不要加緩存登陸驗證次數,要不要密碼加密設置其他具體方式,這些都由用戶自己決定,而shiro只提供給用戶權限驗證的格式接口,通過用戶提供的數據源shrio判斷要不要給具體用戶授權請求路徑的判斷。 > ShiroRealm 涉及到以下點: > principal: > 主體,就是登陸的當前用戶類型的數據實體 > credentials: > 憑證,用戶的密碼,具體加密方式用戶自己實現,什么都不做就是原文 > Roles: > 用戶擁有的角色標識(角色名稱,admin,account,customer_service),字符串格式列表:用戶擁有多個角色的可能 > Permissions: > 用戶擁有的權限標識(每個權限唯一標識,比如主鍵或者權限唯一標識編碼),字符串格式列表:用戶擁有多個權限的可能 #### 2.3.3 ShrioRealm 1. 用戶登陸信息及權限配置 ~~~ @Component("aexitShrioRealm") public class AexitShrioRealm extends AuthorizingRealm { @Resource UserService userService; @Resource RoleService roleService; @Resource MenuService menuService; /** * 配置用戶權限 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { if (principals == null) { throw new AuthorizationException("PrincipalCollection method argument cannot be null."); } String userId = (String) getAvailablePrincipal(principals); List<String> roleList = roleService.getRoleIdsByUserId(userId); //用戶角色獲取用戶功能id Set<String> roleSet = new HashSet<>(); //角色集合 Set<String> menuSet = new HashSet<>(); //菜單集合 List<String> menus; for(String roleId : roleList){ roleSet.add(roleId); menus = menuService.getMenuidsByRoleId(roleId); Collections.addAll(menuSet,menus.toArray(new String[menus.size()])); } SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(roleSet); authorizationInfo.setStringPermissions(menuSet); return authorizationInfo; } /** * 配置登錄認證信息 * * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; String userId = token.getUsername(); if (userId == null) { throw new AccountException("Null usernames are not allowed by this realm."); } //查出是否有此用戶 SysUser curUser = userService.getByUserId(userId); if(curUser == null) throw new AccountException("account error:one user name must have one and only one user! "); //密碼加密 String password = ShiroKit.md5(curUser.getPassword(),curUser.getSalt()); return new SimpleAuthenticationInfo(userId, password, getName()); } } ~~~ 2. 用戶登陸驗證 ~~~ /** * 登陸驗證 * @return */ @RequestMapping(value="/login",method = RequestMethod.POST) @ResponseBody public AjaxCommonObject login(@RequestParam(value="user_id",required = false) String userId, @RequestParam(value="password",required = false) String password, @RequestParam(value="user_validate_code",required = false) String userValidateCode, HttpSession session) { AjaxCommonObject ajaxCommonObject = new AjaxCommonObject(); try { if (!userValidateCode.equals(session.getAttribute(Constants.KAPTCHA_SESSION_KEY))) { throw new BizCommonException(400,"請輸入正確的驗證碼!"); } SysUser user = userService.getByUserId(userId.trim()); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken( userId, ShiroKit.md5(password,user.getSalt())); subject.login(token); //登陸成功之后 session.setAttribute(AuthConstants.CURRENT_USER, user); session.setAttribute(AuthConstants.DICTIONRYS, sysDictionaryMapper.selectByExample(new SysDictionaryExample()));//數據字典 } catch (BizCommonException e) { return new AjaxCommonObject(new BizCommonException(400,"請輸入正確的用戶名和密碼!")); } return ajaxCommonObject; } ~~~ 3. shiro生命周期的管理配置 ~~~ /** * shiro生命周期配置項 * Created by hanxt on 2017/12/18. */ @Configuration public class ShiroConfiguration { @Resource SysMenuExtMapper sysMenuExtMapper; @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean(name = "shiroRealm") @DependsOn("lifecycleBeanPostProcessor") public AexitShrioRealm shiroRealm() { AexitShrioRealm realm = new AexitShrioRealm(); return realm; } @Bean(name = "ehCacheManager") @DependsOn("lifecycleBeanPostProcessor") public EhCacheManager ehCacheManager() { EhCacheManager ehCacheManager = new EhCacheManager(); return ehCacheManager; } @Bean(name = "securityManager") public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroRealm()); securityManager.setCacheManager(ehCacheManager());//用戶授權/認證信息Cache, 采用EhCache 緩存 return securityManager; } @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, String> filterChainDefinitionManager = new LinkedHashMap<>(); filterChainDefinitionManager.put("/druid/**", "anon"); filterChainDefinitionManager.put("/static/**", "anon");//靜態資源不攔截 filterChainDefinitionManager.put("/login", "anon");//anon 可以理解為不攔截 filterChainDefinitionManager.put("/logout", "anon");//anon 可以理解為不攔截 filterChainDefinitionManager.put("/kaptcha", "anon");//anon 可以理解為不攔截 filterChainDefinitionManager.put("/", "anon"); filterChainDefinitionManager.put("/**", "authc,myperm");//authc未登錄攔截 myperm 菜單url權限攔截 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager); shiroFilterFactoryBean.setLoginUrl("/"); //shiroFilterFactoryBean.setSuccessUrl("/"); shiroFilterFactoryBean.setUnauthorizedUrl("/"); URLPermissionsFilter urlPermissionsFilter = new URLPermissionsFilter(); Map<String,Filter> filtermap = new HashMap<>(); filtermap.put("myperm",urlPermissionsFilter);shiroFilterFactoryBean.setFilters(filtermap); return shiroFilterFactoryBean; } @Bean @ConditionalOnMissingBean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); daap.setProxyTargetClass(true); return daap; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(securityManager); return aasa; } //thymeleaf模板引擎和shiro整合時使用 /*@Bean(name = "shiroDialect") public ShiroDialect shiroDialect(){ return new ShiroDialect(); }*/ } ~~~ #### 2.3.4 用戶菜單url訪問權限攔截 > 問題:當用戶登錄系統后,如果當前用戶角色沒有某些菜單訪問權限,但是該用戶知道菜單的url路徑,其通過瀏覽器直接輸入路徑是可以訪問的! ~~~ 解決方法: 在我們配置shiro生命周期配置項時,我們做了兩步操作 1:通過AexitShrioRealm將用戶角色對應的菜單權限信息交給Shrio管理 2:配置攔截器 ~~~ 其實:還可以利用shiro標簽和注解 ![](https://box.kancloud.cn/17b5a00511ea5464f50857b2770ec291_984x776.png) ![](https://box.kancloud.cn/503ca4706d3fecb1bd698a6a32f67a31_1037x847.png) > 然后我們通過URLPermissionsFilter 類來判斷該請求是否是菜單請求,如果是菜單請求我們調用shiro為我們提供的isAccessAllowed(), > 該方法會通過我們之前交給Shrio的用戶角色對應的菜單權限信息來判斷此次請求是否是該用戶角色范圍之內的請求,如果是可以請求,不是不可以訪問。 **通過注解** ~~~ @RequestMapping("/listall") @ResponseBody @RequiresPermissions("userInfo:view") public List<Userinfo> list(){ List<Userinfo> members = userInfoService.getMembers(); return members; } ~~~ ~~~ /** * 自定義shiro的URL攔截器 * 攔截目標為菜單url,根據AexitShrioRealm配置的權限決定用戶有沒有權限訪問菜單 * 注意:這里不做數據層面的請求限制 */ public class URLPermissionsFilter extends PermissionsAuthorizationFilter { /** * @param mappedValue 指的是在聲明url時指定的權限字符串, * 如/User/create.do=perms[User:create].我們要動態產生這個權限字符串,所以這個配置對我們沒用 */ @SuppressWarnings("unchecked") public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException { HttpServletRequest req = (HttpServletRequest) request; String path = req.getServletPath(); //用戶在登陸時把系統所有的菜單項目保存到list里面 List<SysMenu> sysMenus = (List<SysMenu>)((HttpServletRequest) request).getSession().getAttribute(AuthConstants.MENUS); if(sysMenus != null){ for(SysMenu menu : sysMenus){ if(path.equals(menu.getUrl())){ //根據AexitShrioRealm配置的權限決定用戶有沒有權限訪問菜單 return super.isAccessAllowed(request, response, buildPermissions(request)); } } } //不是菜單的,不做數據層面的請求限制 return true; } /** * 根據請求URL產生權限字符串(如:/menu),這里只產生,而比對的事交給Realm */ protected String[] buildPermissions(ServletRequest request) { String[] perms = new String[1]; HttpServletRequest req = (HttpServletRequest) request; String path = req.getServletPath(); perms[0] = path;//path直接作為權限字符串 return perms; } } ~~~ ### 2.4 SpringBoot集成kaptcha驗證碼 1. 添加maven依賴 ~~~ <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> <exclusions> <exclusion> <artifactId>javax.servlet-api</artifactId> <groupId>javax.servlet</groupId> </exclusion> </exclusions> </dependency> ~~~ 2. 驗證碼配置文件 因為kaptcha的配置不符合yaml的規范,所以只能采用properties,新建kaptcha.properties ~~~ kaptcha.border=yes kaptcha.border.color=105,179,90 kaptcha.textproducer.font.color=blue kaptcha.image.width=100 kaptcha.image.height=35 kaptcha.session.key=code kaptcha.textproducer.char.length=4 kaptcha.textproducer.font.names=宋體,楷體,微軟雅黑 ~~~ 3. 新建配置文件CaptchaConfig 讀取配置 ~~~ @Component @PropertySource(value = {"classpath:kaptcha.properties"}) public class CaptchaConfig { @Value("${kaptcha.border}") private String border; @Value("${kaptcha.border.color}") private String borderColor; @Value("${kaptcha.textproducer.font.color}") private String fontColor; @Value("${kaptcha.image.width}") private String imageWidth; @Value("${kaptcha.image.height}") private String imageHeight; @Value("${kaptcha.session.key}") private String sessionKey; @Value("${kaptcha.textproducer.char.length}") private String charLength; @Value("${kaptcha.textproducer.font.names}") private String fontNames; @Bean(name = "captchaProducer") public DefaultKaptcha getKaptchaBean() { DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); Properties properties = new Properties(); properties.setProperty("kaptcha.border", border); properties.setProperty("kaptcha.border.color", borderColor); properties.setProperty("kaptcha.textproducer.font.color", fontColor); properties.setProperty("kaptcha.image.width", imageWidth); properties.setProperty("kaptcha.image.height", imageHeight); properties.setProperty("kaptcha.session.key", sessionKey); properties.setProperty("kaptcha.textproducer.char.length", charLength); properties.setProperty("kaptcha.textproducer.font.names", fontNames); Config config = new Config(properties); defaultKaptcha.setConfig(config); return defaultKaptcha; } } ~~~ 4. 生成驗證碼 ~~~ @Resource DefaultKaptcha captchaProducer; /** * 獲取驗證碼 */ @RequestMapping(value = "/kaptcha", method = RequestMethod.GET) public void kaptcha(HttpSession session,HttpServletResponse response) throws Exception { response.setDateHeader("Expires", 0); response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); response.addHeader("Cache-Control", "post-check=0, pre-check=0"); response.setHeader("Pragma", "no-cache"); response.setContentType("image/jpeg"); String capText = captchaProducer.createText(); //TODO 如果是前后臺分離或分布式部署,這里需要使用SpringSession放到redis里面 //將驗證碼存到session session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText); // create the image with the text BufferedImage bi = captchaProducer.createImage(capText); ServletOutputStream out = response.getOutputStream(); // write the data out ImageIO.write(bi, "jpg", out); try { out.flush(); } finally { out.close(); } } ~~~ 5. 模擬訪問界面 ~~~ <img src="${ctxPath}/kaptcha" id="kaptcha" width="100%" height="100%"/> <script> $(function(){ $("#kaptcha").on('click',function(){ $("#kaptcha").attr('src', '${ctxPath}/kaptcha?' + Math.floor(Math.random()*100) ).fadeIn(); }); }); </script> ~~~ 注意:頁面需要引用js,css,需要配置靜態文件目錄 ~~~ spring: mvc: static-path-pattern: /static/** ~~~ ### 2.5 整合mybatis-plus分頁 1. 引入pom依賴 ~~~ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <shiro.version>1.4.0</shiro.version> <mybatisplus-spring-boot-starter.version>1.0.4</mybatisplus-spring-boot-starter.version> <mybatisplus.version>2.1-gamma</mybatisplus.version> </properties <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatisplus-spring-boot-starter</artifactId> <version>${mybatisplus-spring-boot-starter.version}</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>${mybatisplus.version}</version> </dependency> ~~~ 2. 配置分頁 ~~~ package com.aixin.tuna.weblearn.weblearn.config; import com.baomidou.mybatisplus.plugins.PaginationInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @MapperScan(basePackages = {"com.aixin.tuna.**.mapper"}) public class MybatisPlusConfig { /** * mybatis-plus分頁插件<br> * 文檔:http://mp.baomidou.com<br> */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } } ~~~ 3. controller ~~~ @GetMapping(value = "/list") @ResponseBody public List<FederatedCompany> list(@RequestParam(required = false) Integer pageIndex, @RequestParam(required = false) Integer pageSize) { Page<FederatedCompany> federatedCompanyPage; if (pageIndex !=null && pageSize !=null) { federatedCompanyPage = new Page<>(pageIndex,pageSize); //創建page對象,傳入當前頁和每頁顯示條目數 } else { federatedCompanyPage = new Page<>(1,Integer.MAX_VALUE); } return federatedCompanyService.getCompanyList(federatedCompanyPage); } ~~~ 4. service ~~~ @Resource FederatedCompanyMapper federatedCompanyMapper; public List<FederatedCompany> getCompanyList(Page<FederatedCompany> page) { return federatedCompanyMapper.list(page); } ~~~ 5. mapper接口 接口接收page對象,自動分頁 ~~~ List<FederatedCompany> list(Page<FederatedCompany> page); ~~~ 6. mapper.xml ~~~ <select id="list" resultType="com.aixin.tuna.weblearn.weblearn.enterprise.model.FederatedCompany"> select * from federated_company </select> ~~~ ![](https://box.kancloud.cn/6a07adca5b67f260a45da054f25822da_863x389.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看