使用IDEA搭建一个Spring + AOP (权限管理 ) + Spring MVC + Mybatis的Web项目 (零配置文件)
前言:
除了mybatis 不是零配置,有些还是有xml的配置文件在里面的。
注解是Spring的一个构建的一个重要手段,减少写配置文件,下面解释一下一些要用到的注解:
@Configuration 作用于类上面,声明当前类是一个配置类(相当于一个Spring的xml文件)
@ComponentScan(“xxx”) 作用于类上面,自动扫描xxx包名下所有使用@Service、@Component、@Repository和@Controller的类,并注册为Bean
@Bean 作用与类和方法上,相当于Spring配置文件bean节点
@EnableWebMvc 作用于类,开启一些默认配置,如一些ViewResolver或者MessageConverter
@RequestMapping 作用于类、方法,配置URL和方法之间的映射
@RequestBody 作用于参数前,允许request的参数在request体中,而不是在直接链接在地址后面
@ResponseBody 作用于返回值、方法上,支持将返回值放在response体中,而不是返回一个页面。
@RequestParam 作用于参数前,将form的对应name值映射到当前参数中。
这里我就不从一开始了。
pom.xml
项目结构:
先把上面的包,依次创建好,(webapp文件夹中的WEB-INF所有文件全部删掉)
我们从 config (配置) 包开始吧。
RootConfig类 (类似于spring-root.xml配置文件一样)
1 package com.oukele.config.spring; 2 3 import org.springframework.context.annotation.ComponentScan; 4 import org.springframework.context.annotation.Configuration; 5 import org.springframework.context.annotation.Import; 6 import org.springframework.web.servlet.config.annotation.EnableWebMvc; 7 8 @Configuration//声明当前类 是一个 配置类 9 @ComponentScan(basePackages = "com.oukele.dao")//扫描 dao包 使用spring 注解的接口 10 @Import({SpringDaoConfig.class,SpringServlet.class})//导入其他配置 11 public class RootConfig { 12 13 }
SpringWebConfig类 (相当于 spring-web.xml )
package com.oukele.config.mvc; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration//声明当前类是配置类 类似于 spring-web.xml 文件 @EnableWebMvc// 若无此注解 WebMvcConfigurer 无效 @ComponentScan(basePackages = {"com.oukele.controller","com.oukele.aspect"})//扫描控制层 和切面 包 @EnableAspectJAutoProxy// 激活 切面 代理 public class SpringWebConfig implements WebMvcConfigurer { //注册静态资源,没注册的话,网站是访问不了的 @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/css/**").addResourceLocations("/WEB-INF/css/"); } }
SpringDaoConfig类 ( 配置 数据源 )
1 package com.oukele.config.spring; 2 3 import com.mchange.v2.c3p0.ComboPooledDataSource; 4 import org.mybatis.spring.SqlSessionFactoryBean; 5 import org.mybatis.spring.mapper.MapperScannerConfigurer; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.context.EnvironmentAware; 8 import org.springframework.context.annotation.Bean; 9 import org.springframework.context.annotation.Configuration; 10 import org.springframework.context.annotation.PropertySource; 11 import org.springframework.core.env.Environment; 12 import org.springframework.core.io.ClassPathResource; 13 import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 14 15 import javax.sql.DataSource; 16 import java.beans.PropertyVetoException; 17 import java.io.IOException; 18 19 @Configuration 20 @PropertySource(value = "classpath:jdbc.properties")//加载资源文件 21 public class SpringDaoConfig implements EnvironmentAware {//数据层 22 23 @Autowired 24 private Environment env; 25 26 @Override 27 public void setEnvironment(Environment environment) { 28 this.env = environment; 29 } 30 31 //配置数据源 32 @Bean 33 public DataSource dataSource() throws PropertyVetoException { 34 ComboPooledDataSource dataSource = new ComboPooledDataSource(); 35 dataSource.setDriverClass(env.getProperty("jdbc.driver")); 36 dataSource.setJdbcUrl(env.getProperty("jdbc.url")); 37 dataSource.setUser(env.getProperty("jdbc.user")); 38 dataSource.setPassword(env.getProperty("jdbc.password")); 39 return dataSource; 40 } 41 //配置 mybatis 42 @Bean 43 public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException, PropertyVetoException { 44 SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); 45 PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 46 factoryBean.setTypeAliasesPackage("com.oukele.entity");//实体类 47 factoryBean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));// 映射 sql文件 48 factoryBean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));//mybatis配置 49 factoryBean.setDataSource(dataSource()); 50 return factoryBean; 51 } 52 // 简化调用 将 dao 放置 容器中 使用:比如 53 //@Autowired 54 //xxxMapper xxmaper ; 55 //也可以在类上面 直接使用 @ComponentScan 扫描接口 56 @Bean 57 public MapperScannerConfigurer mapperScannerConfigurer() { 58 MapperScannerConfigurer configurer = new MapperScannerConfigurer(); 59 configurer.setBasePackage("com.oukele.dao");//扫描接口 60 configurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean"); 61 return configurer; 62 } 63 64 }
SpringServlet 类 (扫描 )
1 package com.oukele.config.spring; 2 3 import org.springframework.context.annotation.ComponentScan; 4 import org.springframework.context.annotation.Configuration; 5 6 @Configuration 7 @ComponentScan(basePackages = "com.oukele.servlet") 8 public class SpringServlet {//服务层 9 10 }
WebConfig 类 (类似于 web.xml文件)
1 package com.oukele.config.web; 2 3 import com.oukele.config.mvc.SpringWebConfig; 4 import com.oukele.config.spring.RootConfig; 5 import org.springframework.web.filter.CharacterEncodingFilter; 6 import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 7 8 import javax.servlet.Filter; 9 10 public class WebConfig extends AbstractAnnotationConfigDispatcherServletInitializer { 11 12 @Override 13 protected Class<?>[] getRootConfigClasses() {// (spring容器) 父容器 14 return new Class[]{RootConfig.class}; 15 } 16 17 @Override 18 protected Class<?>[] getServletConfigClasses() {// (spring mvc容器) 子容器 19 return new Class[]{SpringWebConfig.class}; 20 } 21 22 @Override 23 protected String[] getServletMappings() {//映射 24 return new String[]{"/"}; 25 } 26 27 //设置编码 这里设置好像没有用。。。。。 有解决方案请告诉我,谢谢 28 @Override 29 protected Filter[] getServletFilters() { 30 CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); 31 characterEncodingFilter.setEncoding("UTF-8"); 32 return new Filter[]{characterEncodingFilter}; 33 } 34 }
Controller 包 里面的类
1 package com.oukele.controller; 2 3 import com.oukele.entity.User; 4 import com.oukele.servlet.UserServlet; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.web.bind.annotation.*; 7 import org.springframework.web.context.WebApplicationContext; 8 9 import javax.servlet.http.HttpSession; 10 import java.util.HashMap; 11 import java.util.Objects; 12 13 @RestController 14 public class LoginController { 15 16 @Autowired 17 private WebApplicationContext webApplicationContext; 18 19 @Autowired 20 private UserServlet userServlet; 21 22 @RequestMapping(path = "/login/{name}/{password}", method = RequestMethod.GET,produces = "application/json;charset=utf-8") 23 public String login(@PathVariable("name") String name, @PathVariable("password") String password, HttpSession session) { 24 User user = new User(); 25 user.setUserName(name); 26 user.setPassword(password); 27 session.setAttribute("username",user);//存入session中 28 Boolean aBoolean = userServlet.checkUser(user); 29 30 if(aBoolean){ 31 return "{\"msg\":\"登入成功\"}"; 32 } 33 34 return "{\"msg\":\"登入失败\"}"; 35 } 36 37 @GetMapping(path = "/Ioc") 38 public HashMap<String, String[]> getAllInfo() { 39 40 return new HashMap<String, String[]>() {{ 41 put("子容器", webApplicationContext.getBeanDefinitionNames()); 42 put("父容器", Objects.requireNonNull(webApplicationContext.getParent().getBeanDefinitionNames())); 43 }}; 44 45 } 46 47 }
dao包中的接口
1 package com.oukele.dao; 2 3 import com.oukele.entity.User; 4 import org.apache.ibatis.annotations.Select; 5 import org.springframework.stereotype.Repository; 6 7 @Repository 8 public interface UserMapper { 9 10 //使用xml配置文件 11 int check(User user); 12 //使用注解 13 @Select("select count(*) from user where userName = #{userName} and password = #{password}") 14 int check1(User user); 15 16 }
entity包中的类
1 package com.oukele.entity; 2 3 public class User { 4 private String userName; 5 private String password; 6 7 public String getUserName() { 8 return userName; 9 } 10 11 public void setUserName(String userName) { 12 this.userName = userName; 13 } 14 15 public String getPassword() { 16 return password; 17 } 18 19 public void setPassword(String password) { 20 this.password = password; 21 } 22 23 @Override 24 public String toString() { 25 return "User{" + 26 "userName='" + userName + '\'' + 27 ", password='" + password + '\'' + 28 '}'; 29 } 30 }
servlet包中的类
1 package com.oukele.servlet; 2 3 import com.oukele.dao.UserMapper; 4 import com.oukele.entity.User; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.stereotype.Service; 7 8 @Service 9 public class UserServlet { 10 11 @Autowired 12 private UserMapper userMapper; 13 14 public Boolean checkUser(User user){ 15 //根据传进来的参数,去数据库查找用户 16 int result = userMapper.check(user); 17 //如果查回来的结果不为零,说明数据库中有该用户,让他登陆,否则不让他登陆 18 if( result > 0 ){ 19 return true; 20 } 21 return false; 22 } 23 24 }
resources 目录
jdbc.properties 资源文件
1 jdbc.driver=org.mariadb.jdbc.Driver 2 jdbc.url=jdbc:mariadb://localhost:3306/test 3 jdbc.user=oukele 4 jdbc.password=oukele
mybatis-config.xml 配置文件
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> 3 <configuration> 4 <settings> 5 <!-- 使用jdbc的getGeneratedKeys获取数据库自增主键值 --> 6 <setting name="useGeneratedKeys" value="true"/> 7 <!-- 使用列别名替换列名 默认:true --> 8 <setting name="useColumnLabel" value="true"/> 9 <!-- 开启驼峰命名转换:Table {create_time} -> Entity {createTime} --> 10 <setting name="mapUnderscoreToCamelCase" value="true"/> 11 </settings> 12 </configuration>
mapper文件中的 UserMapper.xml 配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3 <!-- 扫描 接口--> 4 <mapper namespace="com.oukele.dao.UserMapper"> 5 6 <select id="check" parameterType="com.oukele.entity.User" resultType="java.lang.Integer"> 7 select count(*) from user where userName = #{userName} and password = #{password} 8 </select> 9 10 </mapper>
好,到这里我们启动了试一下效果了,(我现在的数据库没有数据库的)
配置Tomcat 启动
运行效果:
那么到这里就开始我们的 权限管理 了,激动。。。。。。
了解一下 AspectJ ? 地址:https://www.cnblogs.com/nongzihong/p/10190866.html
先创建一个包 aspect ( 切面 )
UserPowerAdvice 类 (切面类)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
package com.oukele.aspect; import com.oukele.dao.UserMapper; import com.oukele.entity.User; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.servlet.http.HttpSession; @Component //注入容器 @Aspect //声明这是一个 切面类 public class UserPowerAdvice { @Autowired HttpSession session; @Autowired UserMapper userMapper; //切点 @Pointcut ( "execution(* com.oukele.controller.*.login(..))" ) public void power() { } ; //环绕通知 @Around ( "power()" ) public Object seeStatus(ProceedingJoinPoint joinPoint) { try { // ......前环绕通知 --> 在原方法还没有执行前先执行 Object o = joinPoint.proceed(); //执行被代理的方法 //环绕通知 能覆盖原方法 // .......后环绕通知 --> 在原方法执行后执行 //从session中取出 存储的信息 User user = (User) session.getAttribute( "username" ); //作为 演示 这里的逻辑就随意一写哈 //如果用户名不为空和密码不为空,去数据库查询,这里呢 我数据库只有用户名和密码 //所以 我这里 如果 用户名为 oukele 则为管理管 否则都是普通用户 if (!user.getUserName().isEmpty() && !user.getPassword().isEmpty()) { //去数据库中查询,结果大于 0 则存在用户 否则 int result = userMapper.check1(user); if (result > 0 ) { if (user.getUserName().equals( "oukele" )) { return "{\"msg\":\"该用户 " + user.getUserName() + " 是 管理员\"}" ; } else { return "{\"msg\":\"该用户 " + user.getUserName() + " 不是 管理员\"}" ; } } else { return "{\"msg\":\"用户不存在。。\"}" ; } } else { return "{\"msg\":\"用户名或者密码为空。。\"}" ; } } catch (Throwable throwable) { throwable.printStackTrace(); } return null ; } } |
在SpringWebConfig 类 加上 @EnableAspectJAutoProxy 注解 和 扫描 aspect 包
运行效果(数据库没有数据的情况下):