简介:用来简化Spring应用开发,约定大于配置,快速部署。
实战:员工管理系统
注解的解释:
@Mapper:
- @Mapper是mybatis自身带的注解
@Repository:
- @Repository是spring提供的注解,能够将该类注册成Bean
@Controller:展示层Bean
@RestController:
- 用于标注控制层组件,表示这是个控制器bean,并且是将函数的返回值直 接填入HTTP响应体中,是REST风格的控制器;它是@Controller和@ResponseBody的合集。
@ResponseBody:
- 表示该方法的返回结果直接写入HTTP response body中
@Component:
- 泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Bean:
- 表示交给Spring来负责管理。
@AutoWired:
- 把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
@RequestMapping:
- RequestMapping是一个用来处理请求地址映射的注解;提供路由信息,负责URL到Controller中的具体函数的映射,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
@PathVariable:
- 路径变量。参数与大括号里的名字一样要相同。
@Async:
- 告诉Spring要使用异步操作.
- 记得要在主程序入口@EnableAsync开启异步
技术选型:
- 导入静态资源
- 首页
- jsp,模板引擎Thymyleaf
- 装配扩展SpringMVC
- 增删改查
- 拦截器
- 国际化(中英文切换)
在springboot中我们可以使用以下方法处理静态资源
- 使用webjars导入到pom.xml文件中
- 或者在在resources下可以创建public、resources、static文件夹,然后直接访问http://localhost:8080/1.js即可。记住优先级resources>static>public
- 直接在public、resources、static、或者根目录文件夹下创建index.html页面。然后直接访问http://localhost:8080/index.html即可。
- 我们可以在templates中创建一个index.html页面,然后再controller中进行映射配置。
再pom.xml中导入
引入thymeleaf3.x-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
然后我们就可以再controller中进行页面跳转了。
在html中引用
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">//引入thymeleaf
基本语法:
- th:text="${msg}":获得后台传来的字符串。
- 多余的需要去查询doc
- 在引入资源时,我们需要th:href = @{/xx/xxx/xxx}
- [[${session.loginUser}]]//获得session中loginUser
在运行文件目录中创建config文件夹,然后实现需要更改的接口进行定义。然后在这个文件夹内自己编码即可。
-
首先导入静态资源。通过启动项目进行访问,检查项目情况。
-
根目录创建一个config文件夹,重新接管我们的MVC。
package com.blog.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class MyMvcConfig implements WebMvcConfigurer { //进行视图控制 @Override public void addViewControllers(ViewControllerRegistry registry) { //这里创建映射关系,比如我访问localhost:8080/main.html=localhost:8080/dashboard registry.addViewController("/").setViewName("index"); registry.addViewController("/index.html").setViewName("index"); registry.addViewController("/main.html").setViewName("dashboard"); } } -
创建一个LoginController
package com.blog.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.thymeleaf.util.StringUtils; @Controller public class LoginController { @RequestMapping("/user/login") public String login( @RequestParam("username") String username, @RequestParam("password") String password, Model model){ //具体业务 if (!StringUtils.isEmpty(username) && "123456".equals(password)){ //登陆成功后重定向到main.html return "redirect:/main.html"; }else { //登陆失败 model.addAttribute("msg","用户名或者密码错误。"); return "index"; } } } -
在登陆界面中为表单设置name属性。
-
在config文件夹下创建一个LoginHandlerInterceptor拦截器类。
package com.blog.config; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //使用拦截器接口 public class LoginHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //登陆成功后,应该有用户的session: Object loginUser = request.getSession().getAttribute("loginUser"); if (loginUser==null){ //未登录,返回信息 request.setAttribute("msg","没有权限,请先登录!"); //回到首页 request.getRequestDispatcher("/index.html").forward(request,response); return false; }else { return true; } } } -
在MyMvcConfig中激活这个拦截器。
//添加拦截器! @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginHandlerInterceptor()) .addPathPatterns("/**")//拦截所有请求 .excludePathPatterns("/index.html", "/", "/user/login", "/css/**", "/js/**", "/img/**");//允许回到index.html }
- 提取相同页面的组件。
- 在templates文件夹中创建一个commons文件夹用来存放组件。
- 在commons文件夹中创建commons.html文件,用来存放组件,
- 在需要提取组件的html标签中加入th:fragment="siderbar"
- 然后把这段代码见铁道commons.html中。
- 再回到组件原始html页面中,新建一个div使用th:replace="~{commons/commons::topbar}"属性添加这个组件。
- 如果要传递参数,
- 列表循环展示。
-
创建一个提交表单的页面add并添加到EmployeeController中
//增加员工页面 @GetMapping("/emp") public String toAddpage(Model model){ //查出所有部门的信息。 Collection<Department> departments = departmentDao.getDepartments(); model.addAttribute("departments",departments); return "emp/add"; } -
完善add.html页面。
-
处理添加请求的POST。
//增加员工表单POST处理 @PostMapping("/emp") public String addEmp(Employee employee){ //添加的操作 redirect和forward的区别 employeeDao.save(employee);//调用底层业务方法保存员工信息。 return "redirect:/emps"; }
- 编写一个错误页面。
- 再templates文件夹下创建一个error文件夹
- 将错误页面移入error文件夹即可。
-
Application.yml配置数据库信息
spring: datasource: username: root password: xxx # useUnicode=true设置字符 characterEncoding=utf-8设置编码 serverTimezone=UTC设置时区。 url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver -
在controller中实现业务逻辑
@RestController public class JDBCController { @Autowired JdbcTemplate jdbcTemplate; //查询数据库的所有信息 // 没有实体类,数据库中的东西无法存储,所以我们引用MAP @GetMapping("/userList") public List<Map<String,Object>> userList(){ String sql = "select * from user"; List<Map<String, Object>> list_maps = jdbcTemplate.queryForList(sql); return list_maps; } //增 @GetMapping("/addUser") public String addUser(){ String sql = "insert into blog.message(content,ip) values('test','192.168.1.1')"; jdbcTemplate.update(sql); return "addOK!"; } //删 @GetMapping("/delUser/{id}") public String delUser(@PathVariable("id")Integer id){ String sql = "delete from blog.message where id="+id; jdbcTemplate.update(sql); return "deleteOK!"; } //改 @GetMapping("/updateUser/{id}") public String updateUser(@PathVariable("id")Integer id){ String sql = "update blog.message set content='修改成功嗷' where id="+id; jdbcTemplate.update(sql); return "updateOK!"; } }
-
导入pom.xml
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> -
配置application.properties
spring.datasource.username=root spring.datasource.password=xxx spring.datasource.url=jdbc:mysql://localhost:3306/blog?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # 整合mybatis mybatis.type-aliases-package=com.ayjin.pojo mybatis.mapper-locations=classpath:mybatis/mapper/*.xml -
首先根据自身数据库在pojo下创建一个数据类。
package com.ayjin.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; //导入lombok使用Data @Data @NoArgsConstructor//无参构造 @AllArgsConstructor//有参构造 public class User { private int id; private String name; private String pwd; } -
然后在mapper下创建一个事务接口。
package com.ayjin.mapper; import com.ayjin.pojo.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; import java.util.List; //这个注解表示了这是一个Mybatics的mapper接口类。dao层 @Mapper @Repository public interface UserMapper { List<User> queryUserList(); User queryUserById(int id); int addUser(User user); int updateUser(User user); int deleteUser(int id); } -
再将其映射到mybatis的mapper下UserMapper.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"> <mapper namespace="com.ayjin.mapper.UserMapper"> <select id="queryUserList" resultType="User"> select * from users </select> <select id="queryUserById" resultType="User"> select * from users where id = #{id} </select> <insert id="addUser" parameterType="User"> insert into users (id,name,pwd) values (#{id},#{name},#{pwd}) </insert> <update id="updateUser" parameterType="User"> update user set name=#{name},pwd=#{pwd} where id=#{id} </update> <delete id="deleteUser" parameterType="User"> delete from users where id = #{id} </delete> </mapper> -
回到controller中创建UserController集成mapper和事务。
package com.ayjin.controller; import com.ayjin.mapper.UserMapper; import com.ayjin.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class UserController { @Autowired private UserMapper userMapper; //查询所有用户 @GetMapping("/queryUserList") public List<User> queryUserList(){ List<User> userList = userMapper.queryUserList(); for (User user : userList) { System.out.println(user); } return userList; } //添加一个用户 @GetMapping("/addUser") public String addUser(){ userMapper.addUser(new User(5,"阿毛","110101")); return "addUserDone!"; } //修改一个用户 @GetMapping("/updateUser") public String updateUser(){ userMapper.updateUser(new User(5,"阿毛","110101")); return "updateUserDone!"; } //删除一个用户 @GetMapping("/deleteUser/{id}") public String deleteUser(@PathVariable("id")Integer id){ userMapper.deleteUser(id); return "deleteUserDone!"; } }
-
导入pom.xml
<!-- druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.23</version> </dependency> <!-- log4j--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> -
配置yml
spring: datasource: username: root password: xxx #useUnicode=true设置字符 characterEncoding=utf-8设置编码 serverTimezone=UTC设置时区。 url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #druid数据源专有配置 #初始化大小 initialSize: 5 #最小值 minIdle: 5 #最大值 maxActive: 20 #最大等待时间,配置获取连接等待超时,时间单位都是毫秒ms maxWait: 60000 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接 timeBetweenEvictionRunsMillis: 60000 #配置一个连接在池中最小生存的时间 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true # 配置监控统计拦截的filters,去掉后监控界面sql无法统计, #'wall'用于防火墙,SpringBoot中没有log4j,我改成了log4j2 filters: stat,wall,log4j #最大PSCache连接 maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
注意事项:
一定一定在application中配置好xml路径!!!!!
Apache Shiro是一个安全权限框架。
-
导入依赖
<!-- shiro Subject 用户 SecurityManager 管理所有用户 Realm 连接数据 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.5.3</version> </dependency> -
创建一个service文件夹。创建一个UserSercice接口类和一个UserSerciceImpl接口实现类
//定义一个查询用户的接口 public interface UserService { public User queryUserByname(String name); }//用户接口的实现 @Service public class UserServiceImpl implements UserService{ @Autowired UserMapper userMapper; @Override public User queryUserByname(String name) { return userMapper.queryUserByName(name); } } -
创建一个config文件夹。
-
在文件夹中创建UserRealm类。(相当于一个管理员类)
public class UserRealm extends AuthorizingRealm { @Autowired UserService userService; //2.授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } //1.认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("正在执行认证"); UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken; //查询数据库,如果返回值为空,返回错误信息。 User user = userService.queryUserByname(userToken.getUsername()); if (user==null){ return null; } //进行密码认证。 return new SimpleAuthenticationInfo(user,user.getPwd(),""); } } -
在文件夹中创建ShiroConfig类。(用于给创建的管理员设置网页过滤)
@Configuration public class ShiroConfig { //1.创建realm对象 @Bean public UserRealm userRealm(){ return new UserRealm(); } //2.将默认的网络安全管理员DefaultWebSecurityManager与realm对象联系。然后返回一个安全管理员 @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(userRealm); return securityManager; } //3.给安全管理员安排一个ShiroFilterFactoryBean方便其对网站进行管控。 @Bean(name = "shiroFilterFactoryBean") public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); //添加shiro的内置过滤器 /* anon:无需认证就可以访问 authc:必须认证才可以访问 user: 必须拥有记住我 功能才可以访问 perms: 拥有对某个资源的权限才可以访问。 role: 拥有某个角色权限才可以访问。 */ //拦截 Map<String, String> filterMap = new LinkedHashMap<>(); //权限,如果没有权限则跳转。记住一定要先把要授权的写在前面。 filterMap.put("/admin/*","perms[admin]"); filterMap.put("/admin/*","authc"); bean.setFilterChainDefinitionMap(filterMap); //设置登录的请求 bean.setLoginUrl("/admin/login"); //未授权的页面 bean.setUnauthorizedUrl("/"); return bean; } }
解决web安全问题。结合shiro和security。都是为了解决安全问题。相当于加强的过滤器。
功能:
- 权限分配
- 访问权限
- 菜单权限
使用:
-
导入
<!-- 导入security--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> -
再config文件夹下配置访问权限。
//AOP编程。 @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { //首页所有人可以访问,功能页分权限。 http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/level1/**").hasRole("vip1") .antMatchers("/level2/**").hasRole("vip2") .antMatchers("/level3/**").hasRole("vip3") ; //如果没有权限,则会回到登录页,需要开启登录的页面。 http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login").usernameParameter("user").passwordParameter("pwd"); //关闭csrf http.csrf().disable(); //开启注销。回到首页 http.logout().logoutSuccessUrl("/"); //开启记住我功能 cookie,自定义接收前端的参数 http.rememberMe().rememberMeParameter("remember");//默认cookie两天。 } //认证,新版本记得要给密码进行编码,即加密!否则无法登录。 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //这些数据最好从数据库中读取。 auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("ayjin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3") .and() .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3") .and() .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1"); } } -
导入security-thymeleaf整合包,方便再html中结合权限使用。
<dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> <version>3.0.4.RELEASE</version> </dependency> <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
方便创建数据的一个依赖,再需要使用的数据类上面使用
@Data
@AllArgsConstructor//有参构造
@NoArgsConstructor//无参构造
- API框架
- RestFul API 文档在线自动生成工具=>Api文档与API定义同步更新。
- 直接运行,可以在线测试API接口。
项目中使用Swagger需要Springfox;
- swagger2
- ui
SpringBoot集成Swagger
-
导入相关依赖
<!-- Swagger--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> -
配置Swagger进项目
@Configuration @EnableSwagger2 public class SwaggerConfig { } -
配置Swagger
//配置Swagger信息 = apiInfo private ApiInfo apiInfo(){ //作者信息 Contact contact = new Contact("ayjin","http://www.ayjin.cn","ayjinwk@163.com"); return new ApiInfo( "Ayjin的SwaggerAPI文档", "江湖渺渺,再见已枉然", "V1.0", "http://www.ayjin.cn", contact, "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0", new ArrayList()); } -
Swagger配置扫描接口
//配置Swagger的Bean实例 @Bean public Docket docket(){ return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() //.enable(false)//设置了这个就关闭Swagger //RequestHandlerSelectors 配置要扫描接口的方式 //basePackage指定要扫描的包 .apis(RequestHandlerSelectors.basePackage("com.ayjin.controller")) //过滤的路径 ant(正则) // .paths(PathSelectors.ant("/")) .build(); } -
配置Swagger是否启动。.enable
-
配置API文档的分组。.groupName("xxx");可以设置多个返回,进行多个分组.
-
注释
- @APIOpetation("xxx"):可以给每个映射规则写注释
- @APIModel("xxx"):可以给用户实体类写注释.
-
导入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> -
配置mail
# 设置mail spring.mail.username=ayjinwk@163.com spring.mail.password=xxxxxxxxxxxxx spring.mail.host=smtp.xxx.com -
查询资料进行使用.
暂停.
<!-- thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.4.1</version>
</dependency>
<!-- shiro-thymeleaf-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!-- sql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!-- lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>