SpringBootWEB开发
1、静态资源导入
1.1、第一种方式使用webjars
官网](https://www.webjars.org/) 找一个jQuery示例
WebMvcAutoConfiguration中关于静态资源的源码部分
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {//如果你在resourceProperties配置文件中自定义了静态资源的路径,那么直接默认的就无效了
logger.debug("Default resource handling disabled");
} else {
this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/"); //第一种使用webjars,要找的静态资源就在这个目录下
this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
//第二种在这里,找resourceProperties中配置好的默认位置 registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
});
}
}
解释:
- addResourceHandlers(ResourceHandlerRegistry registry):这是一个公共方法,用于添加资源处理器。参数registry是资源处理器注册器。
- if (!this.resourceProperties.isAddMappings()):如果不添加映射,就记录一条调试信息。
- this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/"):添加一个资源处理器,处理路径为/webjars/**的请求,资源位置在classpath:/META-INF/resources/webjars/。
- this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {...}):添加另一个资源处理器,处理路径由mvcProperties.getStaticPathPattern()获取,资源位置由resourceProperties.getStaticLocations()获取。如果servletContext不为空,还会添加一个ServletContextResource资源。
在官网上复制maven依赖
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>jquery</artifactId>
<version>3.7.0</version>
</dependency>
导入依赖,导入后可以看到目录结构,访问localhost:8080/webjars/jquery/3.7.0/dist/jquery.js 就可以访问到这个静态资源。
1.2、spring boot默认约定好的资源路径
在WebProperties源码中有Resources静态类,里面指明了资源路径
- classpath:/META-INF/resources/,就是第一种方法中webjars的上一级
- classpath:/resources/,优先级最高,这里放一些上传的资源
- classpath:/static/,优先级次之,默认静态资源放这里
- classpath:/public/。优先级最低,这里放一些公共的资源
public static class Resources {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
private String[] staticLocations;
private boolean addMappings;
private boolean customized;
private final WebProperties.Resources.Chain chain;
private final WebProperties.Resources.Cache cache;
public Resources() {
this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
this.addMappings = true;
this.customized = false;
this.chain = new WebProperties.Resources.Chain();
this.cache = new WebProperties.Resources.Cache();
}
//在这里上面定义的资源路径可以被调用,registration.addResourceLocations(this.resourceProperties.getStaticLocations());从这里点过来的getStaticLocations()方法
public String[] getStaticLocations() {
return this.staticLocations;
}
-------------------此处省略后面源码
}
优先级测试
在resources目录中再创建public、resource目录,分别在这三个目录中各建一个1.js里面内容为,public、resource、static
可以看出resource优先级最高,现在把resource的js文件删除再访问,发现变成static,说明static是第二优先。
原理:静态映射/**
静态资源和请求如果相同的话,会先找请求的Controller看能不能处理,不能处理的话将这些请求 交给静态资源处理器处理,要是静态资源处理器还不能找到就404了。
比如:在resource目录下建一个2.js文件,然后写一个controller让它的请求路径也写成2.js然后返回aaaa
那么在访问localhost:8080/2.js时就会显示的是aaaa
访问静态资源前加前缀
一般静态资源与请求会区分开,请求会经过拦截器进行判断,因为静态资源通常不涉及到业务逻辑处理没有必要再经过拦截器,为了与请求区分开,就会给静态资源搞一个特殊的前缀,默认映射的是/**,我们可以在配置文件中更改。
spring.mvc.static-path-pattern=/resources/**
这样在访问静态资源时都要加上resources才能拿到
如:localhost:8080/resources/1.js才能访问到
2、首页如何定制
Spring Boot 支持静态和模板化的欢迎页面。 它首先在配置的静态内容位置中查找文件。 如果未找到模板,则查找模板。 如果找到任一,它将自动用作应用程序的欢迎页面。index.html index
也就是说,index.html可以放在静态资源里哪一个目录都可以,也可以使用controller处理index请求让它到指定的页面当首页。
但是,如果放在templates下的话只能使用controller让它返回到index.html
使用controller就需要视图解析器了,spring boot中需要使用thymeleaf模板引擎
自定义图标
与其他静态资源一样,Spring 引导会检查配置的静态内容位置中是否有 。 如果存在此类文件,则会自动将其用作应用程序的图标。favicon.ico
这里随便弄个图片命名为favicon.ico,把它放在static目录里,统一一下index.html也放进去
重启之前清理一些浏览器缓存。
这个图片前后端分离基本上就是前端做的了,spring boot都已经弃用了。
3、模板引擎thymeleaf
3.1、Thymeleaf简介
Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。它与 JSP,Velocity,FreeMaker 等模板引擎类似,也可以轻易地与 Spring MVC 等 Web 框架集成。与其它模板引擎相比,Thymeleaf 最大的特点是,即使不启动 Web 应用,也可以直接在浏览器中打开并正确显示模板页面 。
Thymeleaf 是新一代 Java 模板引擎,与 Velocity、FreeMarker 等传统 Java 模板引擎不同,Thymeleaf 支持 HTML 原型,其文件后缀为“.html”,因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 thymeleaf 模板的静态页面效果;当通过 Web 应用程序访问时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示。
Thymeleaf 通过在 html 标签中,增加额外属性来达到“模板+数据”的展示方式,
先导入依赖
<dependency><!--页面模板依赖-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
找源码ThymeleafProperties
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
............
}
分析源码,默认的前缀为classpath:/templates/,默认的后缀为 “.html”,所以将html文件放在templates的目录下,然后用controller处理请求跳转到指定页。
测试:在templates目录下新建test.html,然后写一个controller
@RestController
public class TestController {
@RequestMapping("/t")
public String test(Model model){
model.addAttribute("msg","嗨嗨嗨,Thymeleaf");
return "test";
}
}
test.html,引入头文件:,用${}取变量
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<!--所有的html元素都可以被Thymeleaf接管 th:元素名-->
<div th:text="${msg}"></div>
</body>
</html>
3.2、请求处理-常用参数注解的使用
-
@PathVariable路径变量
新建ParameterTestController测试
@RequestMapping("/car/{id}/owenr/{username}") public Map<String,Object> getCar(@PathVariable("id") Integer id, @PathVariable("username") String name, @PathVariable Map<String,String> pv){ Map<String, Object> map = new HashMap<>(); map.put("id",id); map.put("name",name); map.put("pv",pv); return map; }
-
@RequestHeader获取请求头
@RequestMapping("/car/{id}/owenr/{username}") public Map<String,Object> getCar(@PathVariable("id") Integer id, @PathVariable("username") String name, @PathVariable Map<String,String> pv, @RequestHeader("User-Agent") String UserAgent, @RequestHeader Map<String,String> header){ Map<String, Object> map = new HashMap<>(); map.put("id",id); map.put("name",name); map.put("pv",pv); map.put("UserAgent",UserAgent); map.put("header",header); return map; }
-
@RequestParam获取请求参数
-
@CookieValue获取cookie值
-
@RequestAttribute获取Request域属性
-
@RequestBody获取请求体
-
@MatrixVariable矩阵变量(spring boot默认禁用掉了矩阵变量)
/cars/{path}?xxX=xxx&aaa=ccc querystring查询字符串。@RequestParam;《br/>/cars/{path; low=34;brand=byd , audi,yd} ﹔矩阵变量
页面开发,cookie禁用了,session里面的内容怎么使用;
session.set( a, b)—> jsessionid —> cookie ---->每次发请求携带。url重写: /abc;jsesssionid=xxxx把cookie的值使用矩阵变量的方式进行传递
<a href=" /cars/sell;low=34;brand=byd,audi, yd">@MatrixVariable(矩阵变量)</a> 〈a href= "/cars/sell;low=34;brand=byd;brand=audi;brand=yd">@MatrixVariable(矩阵变量)</a>〈a href="/boss/1;age=20/2;age=10">@MatrixVariable(矩阵变量〉/boss/{[bossId}/ {empId}</a>
";“之前是路径,之后的分号隔开的是矩阵变量,”,"隔开代表这个矩阵变量有多个值
3.3、Thymeleaf语法
- th:text 对文本转义,特殊字符也会被当作普通字符输出
- th:utext 对文本不转义,按照你写的特殊字符解释
修改两个地方再测试,msg的内容包上h1标签,分别使用test和utext测试
@RequestMapping("/t")
public String test(Model model){
model.addAttribute("msg","<h1>嗨嗨嗨,Thymeleaf</h1>");
return "test";
}
<div th:text="${msg}"></div>
<div th:utext="${msg}"></div>
遍历each,和vue中的for each一样的
再加一个集合
model.addAttribute("user", Arrays.asList("张三","李四"));
<hr>
<!--遍历数组user得到一个集合use,然后使用th:text绑定去取use ${use}-->
<h2 th:each="user:${user}" th:text="${user}"></h2>
4、员工信息管理系统(练习)
4.1、准备工作,找静态资源
新建项目SpringBoot-04-system,添加这些依赖
导入静态资源
4.2、伪造数据库
部门表
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//部门表
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Department {
private Integer id;
private String departmentName;
}
员工表
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
//员工表
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
private Integer id;
private String lastName;
private String email;
private Integer gender;//0:女 1:男
private Department department;
private Date date;
}
模拟数据库中员工表的数据.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Repository
public class EmployeeDao {
//模拟数据库中员工表的数据
static private Map<Integer, Employee> employees;
@Autowired
private DepartmentDao departmentDao;
static {
employees = new HashMap<>();//创建一个员工表
employees.put(1, new Employee(1, "zsr", "1234@qq.com", 1, new Department(1, "技术部"), new Date()));
employees.put(2, new Employee(2, "lyr", "1345@qq.com", 1, new Department(2, "市场部"), new Date()));
employees.put(3, new Employee(3, "gcc", "5665@qq.com", 0, new Department(3, "调研部"), new Date()));
employees.put(4, new Employee(4, "zyx", "7688@qq.com", 1, new Department(4, "后勤部"), new Date()));
employees.put(5, new Employee(5, "zch", "8089@qq.com", 1, new Department(5, "运营部"), new Date()));
}
//主键自增
private static Integer initialID = 6;
//增加一个员工
public void addEmployee(Employee employee) {
if (employee.getId() == null)
employee.setId(initialID++);
employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
employees.put(employee.getId(), employee);
}
//查询全部员工信息
public Collection<Employee> getAllEmployees() {
return employees.values();
}
//通过id查询员工
public Employee getEmployeeByID(Integer id) {
return employees.get(id);
}
//通过id删除员工
public void deleteEmployeeByID(int id) {
employees.remove(id);
}
}
模拟部门表的dao
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@Repository
public class DepartmentDao {
//模拟数据库中的数据
private static Map<Integer, Department> departments = null;
static {
departments = new HashMap<>();//创建一个部门表
departments.put(1, new Department(1, "技术部"));
departments.put(2, new Department(2, "市场部"));
departments.put(3, new Department(3, "调研部"));
departments.put(4, new Department(4, "后勤部"));
departments.put(5, new Department(5, "运营部"));
}
//获得部门的所有信息
public Collection<Department> getDepartments() {
return departments.values();
}
//通过id得到部门
public Department getDepartmentById(int id) {
return departments.get(id);
}
}
处理首页index,自定义MyMVCConfig
@Configuration
public class MyMVCConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
启动访问,可以访问index.html
4.3、将所有页面的静态资源使用thymeleaf接管
将thymeleaf的命名空间引入
<html lang="en" xmlns:th="http://www.thymeleaf.org">
然后修改所有的静态资源引入,链接用@{}
4.4、国际化
首先确保idea的properties编码都统一为UTF-8
然后在resource下再建一个国际化的文件i18n,在这个目录下再新建两个个配置文件分别配置中英文
login.properties
:默认无选择语言时生效login_en_US.properties
:英文生效login_zh_CN.properties
:中文生效
点开login.properties可视化配置,点左上角的+号添加key,然后在右边的三个配置框中写值,第一个是默认的,第二个是英语,第三个是中文。
登录页中还有几个属性可以直接添加,idea好像不能保存使用可视化配置的键值,所以可以直接在对应的配置文件中配一下就好了。
login_en_US.properties
login.btn=sign in
login.password=Password
login.remember=Remember me
login.tip=Please sign in
login.username=Username
login_zh_CN.properties和login.properties
login.btn=登录
login.password=密码
login.remember=记住我
login.tip=请登录
login.username=用户名
配置好了,接下来就是让它生效,在application.properties中配置
#配置国家化文件的真实路径
spring.messages.basename=i18n.login
然后去index.html改这些国际化的消息,thymeleaf的语法是 #{…}
刷新一下就有默认的效果了
现在还不能实现点下面的中文和English就切换
先在这俩标签上加跳转链接
<!--这里传入参数不需要使用?使用key=value-->
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
显然两个链接就需要进行处理,所以自定义地区解析器,看源码。
先搜索WebMvcAutoConfiguration找到关于地区解析器的方法localeResolver
@Bean
@ConditionalOnMissingBean(
name = {"localeResolver"}
)
public LocaleResolver localeResolver() {
//如果用户自己配了就用用户配好的
if (this.webProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.WebProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.webProperties.getLocale());
} else {
//用户没配就使用默认的,这里它new了一个地区解析器的对象,然后使用setDefaultLocale给设置了默认的地区解析器
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.webProperties.getLocale());
return localeResolver;
}
}
AcceptHeaderLocaleResolver点进去可以看到它实现类LocaleResolver接口
所以我们要自定义地区解析器也得实现它
在config中新建MyLocaleResolver类实现LocaleResolver
import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
//获取请求中的语言参数
String language = request.getParameter("l");
//如果没有请求就设置默认地区
Locale locale = Locale.getDefault();
//如果请求的连接参数不为空,它携带了国际化参数
if (!StringUtils.isEmpty(language)){
//zh_CN(语言_地区),用_分割开来
String[] split = language.split("_");
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
这里还需要将它添加到组件里,在MyMVCConfig配置类中添加bean,然后重启测试
//添加自定义国际化组件
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
4.5、登录实现
先让登录时提交的表单提交到controller处理,走/user/login就登录。我们让它在登录请求时就携带参数,username和password属性,好判断登录条件。
<form class="form-signin" th:action="@{/user/login}">
新建loginController类,如果登录条件不满足,就给一个回显消息mag,然后在前端加一个p标签提示。
由于我们现在提交表单时浏览器上会直接显示用户名和密码,这就很暴露了,所以设置main.html作为dashboard的映射页,在MyMVCConfig可以给它添加一个地址映射,让真正的首页dashboard.html与mian.html对应,在loginController就直接让请求重定向到main.html
MyMVCConfig添加项
registry.addViewController("/main.html").setViewName("dashboard");
loginController
@Controller
public class loginController {
@RequestMapping("/user/login")
public String login(@RequestParam("username") String name,
@RequestParam("password") String pwd,
Model model){
//如果用户名和密码都正确,用户名为:admin 密码给为123
if ("admin".equals(name) && "123".equals(pwd)){
//重定向到main.html页面,也就是跳到dashboard
return "redirect:/main.html";
}else {
//登录有问题就设回显消息提示
model.addAttribute("msg","用户名或密码错误!");
return "index";//还回到登录页
}
}
}
测试:瞎填用户名和密码
填正确的可以正确登录
但是现在就算不经过登录页面也能访问到主页,所以得加登录拦截器了
4.6、登录拦截器
在config下自定义拦截器LoginHandlerInterceptor,这里需要在登录时将用户登录信息放到session中,所以在此之前先判断用户有没有登录,session不为空就是登录了然后放行。如果没有登录就让它回到登录页登录,并加上错误信息“没有权限,请先登录!”,然后不放行return false。
先去loginController将用户登陆时的信息存session里
@Controller
public class loginController {
@RequestMapping("/user/login")
public String login(@RequestParam("username") String name,
@RequestParam("password") String pwd,
Model model, HttpSession session){
//如果用户名和密码都正确,用户名为:admin 密码给为123
if ("admin".equals(name) && "123".equals(pwd)){
//重定向到main.html页面,也就是跳到dashboard
session.setAttribute("loginname",name);
return "redirect:/main.html";
}else {
//登录有问题就设回显消息提示
model.addAttribute("msg","用户名或密码错误!");
return "index";//还回到登录页
}
}
}
LoginHandlerInterceptor
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断用户有没有登录,看session是否为空
Object session = request.getSession().getAttribute("loginName");
if (session == null){
request.setAttribute("msg","没有权限,请先登录!");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}else {
return true;
}
}
}
然后把它注册到bean中,在MyMVCConfig中重写拦截器的方法,使用自己的,拦截的时候把静态资源放行,还要登录页的请求。
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginHandlerInterceptor())
.addPathPatterns("/**")//拦截所有请求
.excludePathPatterns("/index.html","/user/login","/","/css/**","/img/**","/js/**");//除了这些
}
直接访问http://localhost:8080/main.html
然后正常登录后再访问http://localhost:8080/main.html,由于刚才已经有了session,所以可以直接访问
4.7、展示员工列表
点击主页的员工列表会跳转到list.html页面显示员工信息,所以需要controller处理请求/emps。
在员工列表的部分添加herf链接,作为请求/emps
list.hml也要修改这部分代码
<li class="nav-item">
<a th:class="nav-link" th:href="@{/emps}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-users">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
员工列表
</a>
</li>
在templates下新建emp目录,用来放员工的增删改查,list.html也放这里
现在新建controller,EmployeeController处理/emps请求获取所有员工信息
由于没有server层,就直接调dao层了
@Controller
public class EmployeeController {
@Autowired
private EmployeeDao employeeDao;
@RequestMapping("/emps")
public String list(Model model){
Collection<Employee> employees = employeeDao.getAllEmployees();
model.addAttribute("emps",employees);
return "emp/list";//返回list进行展示
}
}
重启测试,点员工列表能跳到list.html页面
因为list.html的导航栏和侧边栏都是一样的,所以为了实现组件复用,将公共部分抽取出来进行复用
在templates下新建commons包,然后新建commons.html,使用th:fragment标签将公共部分抽取出来,也就是顶部导航栏和侧边栏
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!--顶部导航栏,利用th:fragment提取出来,命名为topbar-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${session.loginName}]]</a>
<input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" th:href="@{/user/logout}">log out</a>
</li>
</ul>
</nav>
<!--侧边栏,利用th:fragment提取出来,命名为sidebar-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="siderbar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
<a th:class="${active=='dashboard.html'?'nav-link active':'nav-link'}" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-home">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
首页 <span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file">
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
<polyline points="13 2 13 9 20 9"></polyline>
</svg>
Orders
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-shopping-cart">
<circle cx="9" cy="21" r="1"></circle>
<circle cx="20" cy="21" r="1"></circle>
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
</svg>
Products
</a>
</li>
<li class="nav-item">
<a th:class="${active=='list.html'?'nav-link active':'nav-link'}" th:href="@{/emps}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-users">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
员工列表
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-bar-chart-2">
<line x1="18" y1="20" x2="18" y2="10"></line>
<line x1="12" y1="20" x2="12" y2="4"></line>
<line x1="6" y1="20" x2="6" y2="14"></line>
</svg>
Reports
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-layers">
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
<polyline points="2 17 12 22 22 17"></polyline>
<polyline points="2 12 12 17 22 12"></polyline>
</svg>
Integrations
</a>
</li>
</ul>
<h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
<span>Saved reports</span>
<a class="d-flex align-items-center text-muted"
href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="feather feather-plus-circle">
<circle cx="12" cy="12" r="10"></circle>
<line x1="12" y1="8" x2="12" y2="16"></line>
<line x1="8" y1="12" x2="16" y2="12"></line>
</svg>
</a>
</h6>
<ul class="nav flex-column mb-2">
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Current month
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Last quarter
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Social engagement
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="feather feather-file-text">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
Year-end sale
</a>
</li>
</ul>
</div>
</nav>
</html>
然后dashboard.html和list.html中的导航栏和侧边栏就就可以删除了,删除是删除了,我们还得导进去,使用th:replace进行覆盖,将topbar和
sidebar导进去。
<!--顶部导航栏-->
<div th:replace="~{commons/commons::topbar}" }></div>
<div class="container-fluid">
<div class="row">
<!--侧边栏-->
<div th:replace="~{commons/commons::siderbar(active='dashboard.html')}"></div>
导入之后就可以看到与原来一样的效果。
高亮处理
侧边栏中每一个选项在点的时候只有首页的那个选项有高亮,我们要做的是选择哪个哪个就高亮,没选择就不高亮。
能让它高亮的是class="nav-link active"
属性,可以使用传递参数判断点击了哪个标签实现相应的高亮
在dashboard.html
的侧边栏标签传递参数active
为dashboard.html
,同样在list.html
的侧边栏标签传递参数active
为list.html
<!--侧边栏-->
<div th:replace="~{commons/commons::siderbar(active='dashboard.html')}"></div>
<!--侧边栏-->
<div th:replace="~{commons/commons::siderbar(active='list.html')}"></div>
然后在commons.html公共组件中使用三元运算判断,如果点击那个选择它会携带参数active,这样在commons.html对应的标签上就可以使用thymeleaf的三元判断,如果有这个参数就是带高亮的标签,如果没有就是普通的。
然后就实现了点哪亮哪(当然这里只有这两个选项写了其他还不能高亮)
显示员工列表
修改list…html,同时添加编辑和删除俩按钮
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th>id</th>
<th>lastName</th>
<th>email</th>
<th>gender</th>
<th>department</th>
<th>date</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}"></td>
<td th:text="${emp.getLastName()}"></td>
<td th:text="${emp.getEmail()}"></td>
<td th:text="${emp.getGender()==0?'女':'男'}"></td>
<td th:text="${emp.getDepartment().getDepartmentName()}"></td>
<td th:text="${#dates.format(emp.getDate(),'yyyy-MM-dd HH:mm:ss')}"></td>
<td>
<a class="btn btn-sm btn-primary" th:href="@{/edit/{id}(id=${emp.getId()})}">编辑</a>
<a class="btn btn-sm btn-danger" th:href="@{/delete/{id}(id=${emp.getId()})}">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
4.8、添加员工
点击按钮提交—>跳转到添加的页面—>添加员工成功返回首页
首先在list.html的显示员工列表上面添加一个“添加员工按钮”,然后href链接请求/add,这里默认的就是get方式,然后去写add的页面跳转请求,让它跳转到add.html页面。
<h2><a class="btn btn-sm btn-success" th:href="@{/add}">添加员工</a></h2>
//添加员工,跳转到添加员工页,并将所有的职位信息放到视图模型中,在add.html页面显示出来选择列表
@GetMapping("/add")
public String toAddPage(Model model){
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return "emp/add";
}
add.html是复制list的,做了一些修改,这里表单提交时设置它的method=“post”,请求的还是/add,但是请求的方式不一样,所以需要再写一个controller处理,把从表单拿到的要添加的对象调用dao的save方法保存,最后重定向到展示所有员工请求。
<!DOCTYPE html>
<!-- saved from url=(0052)http://getbootstrap.com/docs/4.0/examples/dashboard/ -->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Dashboard Template for Bootstrap</title>
<!-- Bootstrap core CSS -->
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
<!-- Custom styles for this template -->
<link th:href="@{/css/dashboard.css}" rel="stylesheet">
<style type="text/css">
/* Chart.js */
@-webkit-keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
@keyframes chartjs-render-animation {
from {
opacity: 0.99
}
to {
opacity: 1
}
}
.chartjs-render-monitor {
-webkit-animation: chartjs-render-animation 0.001s;
animation: chartjs-render-animation 0.001s;
}
</style>
</head>
<body>
<!--顶部导航栏-->
<div th:replace="~{commons/commons::topbar}" }></div>
<div class="container-fluid">
<div class="row">
<!--侧边栏-->
<div th:replace="~{commons/commons::siderbar(active='list.html')}"></div>
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<form th:action="@{/add}" method="post">
<div class="form-group">
<label>LastName</label>
<input type="text" name="lastName" class="form-control" placeholder="lastname:zsr">
</div>
<div class="form-group">
<label>Email</label>
<input type="email" name="email" class="form-control" placeholder="email:xxxxx@qq.com">
</div>
<div class="form-group">
<label>Gender</label><br/>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="1">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" value="0">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<!--注意这里的name是department.id,因为传入的参数为id-->
<select class="form-control" name="department.id">
<option th:each="department:${departments}" th:text="${department.getDepartmentName()}"
th:value="${department.getId()}">
</option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<!--springboot默认的日期格式为yy/MM/dd-->
<input type="text" name="date" class="form-control" placeholder="birth:yyyy/MM/dd">
</div>
<button type="submit" class="btn btn-primary">添加</button>
</form>
</main>
</div>
</div>
可以下拉列表选择部门,这里它的name属性是department的id属性,不能是对象,因为传入的参数就是id
随便添加一个
日期格式默认为
可以看到已经添加过来了。
日期格式默认为yyyy/MM/dd
,我们也可以改成yyyy-MM-dd的格式,到配置文件application.properties中设置就行,但改完就不能使用yyyy/MM/dd格式了。
#更改日期格式
spring.mvc.format.date=yyyy-MM-dd
更改配置文件,需要重启
一次运行,随便添加都可以,重启后就会清空,因为没有数据库。
4.9、修改
之前的编辑按钮现在改成a链接,请求路径需要加上当前员工的id属性,th:href=“@{/edit/{id}(id=${emp.getId()})}”
<a class="btn btn-sm btn-primary" th:href="@{/edit/{id}(id=${emp.getId()})}">编辑</a>
然后写跳转到编辑页的controller,edit
//跳转到修改页面,同时将要修改的员工信息也放到视图模型,还有所有的职位信息
@RequestMapping("/edit/{id}")
public String edit(@PathVariable("id") int id,Model model){
//通过id找到这个员工,并放到视图模型
Employee employee = employeeDao.getEmployeeByID(id);
model.addAttribute("employee",employee);
//和添加员工一样,为了那个选择列表
Collection<Department> departments = departmentDao.getDepartments();
model.addAttribute("departments",departments);
return "emp/edit";
}
复制一份add.html为edit.html修改内容,每一个input都加上th:value然后employee.getxxx把这个员工的值拿出来,做默认的,select选择列表设置默认选择项th:selected,设为员工本来的,th:selected=“${department.getId()==employee.department.getId()}”
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<form th:action="@{/edit}" method="post">
<!--隐藏域,将这个员工的id也提交,保存的时候就是修改,不然一直都是保存添加新的-->
<input type="hidden" name="id" th:value="${employee.getId()}">
<div class="form-group">
<label>LastName</label>
<input th:value="${employee.getLastName()}" type="text" name="lastName" class="form-control"
placeholder="lastname:zsr">
</div>
<div class="form-group">
<label>Email</label>
<input th:value="${employee.getEmail()}" type="email" name="email" class="form-control"
placeholder="email:xxxxx@qq.com">
</div>
<div class="form-group">
<label>Gender</label><br/>
<div class="form-check form-check-inline">
<input th:checked="${employee.getGender()==1}" class="form-check-input" type="radio"
name="gender" value="1">
<label class="form-check-label">男</label>
</div>
<div class="form-check form-check-inline">
<input th:checked="${employee.getGender()==0}" class="form-check-input" type="radio"
name="gender" value="0">
<label class="form-check-label">女</label>
</div>
</div>
<div class="form-group">
<label>department</label>
<!--注意这里的name是department.id,因为传入的参数为id-->
<select class="form-control" name="department.id">
<option th:selected="${department.getId()==employee.department.getId()}"
th:each="department:${departments}" th:text="${department.getDepartmentName()}"
th:value="${department.getId()}">
</option>
</select>
</div>
<div class="form-group">
<label>Birth</label>
<!--springboot默认的日期格式为yy/MM/dd-->
<input th:value="${#dates.format(employee.getDate(),'yyyy/MM/dd')}" type="text" name="date"
class="form-control"
placeholder="birth:yy/MM/dd">
</div>
<button type="submit" class="btn btn-primary">修改</button>
</form>
</main>
编写修改的controller,update
//修改
@PostMapping("/edit")
public String update(Employee employee){
employeeDao.addEmployee(employee);
return "redirect:/emps";
}
现在编辑张三
原始据修改后,由于日期格式改了,所以直接用改之后的
可以看到已经改好了。
4.10、删除、404处理和注销
删除就一个删除的请求/delete带上id,controller调用删除就行了
<a class="btn btn-sm btn-danger" th:href="@{/delete/{id}(id=${emp.getId()})}">删除</a>
deleteEmp
//删除
@RequestMapping("/delete/{id}")
public String deleteEmp(@PathVariable("id") int id){
employeeDao.deleteEmployeeByID(id);
return "redirect:/emps";
}
没删之前,现在全删除
删没了,重启一下就行了,反正没有数据库本身就不是永久存储。
现在搞404页面,spring boot的404只需要在templates中建一个error文件夹,然后404就是404.html,500就是500.html就好了。
随便瞎访问
注销
把session移除就好了,在公共部分commons里,导航栏那里的注销添加请求/user/logout,写controllor把session移除就行,再给它重定向到首页,controller写loginController里。
//注销
@RequestMapping("/user/logout")
public String logout(HttpSession session) {
session.invalidate();
return "redirect:/main.html";
}
点注销后直接出来,让登录
至此,小练习结束。
5、整合JDBC
5.1、测试
新建项目springboot-05-jdbc,选择依赖的时候把JDBC API和MySQL Driver选上。
然后就能看到它自动导入的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
然后新建一个配置文件application.yml,在这里配置数据库的数据源。
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf-8
#serverTimezone=Asia/Shanghai是时区,上海
springboot的自动装配机制会自动生成相应的对象。
测试:查看一下默认的数据源,获得数据库连接,关闭连接
class SpringBoot05JdbcApplicationTests {
@Autowired(required = false)
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
//获取默认数据源
System.out.println(dataSource.getClass());
//获取连接
Connection connection = dataSource.getConnection();
System.out.println(connection);
//关闭连接
connection.close();
}
}
默认的数据源:class com.zaxxer.hikari.HikariDataSource
输出的连接:HikariProxyConnection@1761495255 wrapping com.mysql.cj.jdbc.ConnectionImpl@379ce046
spring boot已经配置了很多的模板,XXXTemplate,可以直接拿来用
测试:先导一下web的依赖,然后写一个JDBCController,使用JdbcTemplate将数据库的表查询出来并访问得到。
@RestController
public class JDBCController {
@Autowired(required = false)
JdbcTemplate jdbcTemplate;
@RequestMapping("/list")
public List<Map<String,Object>> userList(){
String sql = "select * from mybatis.user";
return jdbcTemplate.queryForList(sql);
}
}
可以正常查出来
接下来就是增删改操作了
增:
@RequestMapping("/add")
public String add(){
String sql ="insert into mybatis.user() values(8,'王小明','666666')";
jdbcTemplate.update(sql);
return "添加成功";
}
添加成功,去数据库查看是否添加到库里
确实添加成功
改:刚才添加的id是8,现在修改也是8
@RequestMapping("/update/{id}")
public String update(@PathVariable("id") int id){
String sql ="update mybatis.user set name=?,pwd=? where id="+id;
Object[] o = new Object[2];
o[0] = "wangxiaoming";
o[1] = "abcdefghijk";
jdbcTemplate.update(sql,o);
return "修改成功";
}
删:删除8号
@RequestMapping("/delete/{id}")
public String delete(@PathVariable("id") int id){
String sql = "delete from mybatis.user where id=?";
jdbcTemplate.update(sql,id);
return "删除成功";
}
5.2、整合Druid数据源
Druid为监控而生的数据库连接池,它是阿里巴巴开源平台上的一个项目。Druid是Java语言中最好的数据库连接池,Druid能够提供强大的监控和扩展功能.它可以替换DBCP和C3P0连接池。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。
导入依赖
<!--Druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
配置文件中配置数据库的数据源类型:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf-8
type: com.alibaba.druid.pool.DruidDataSource
各配置说明
后台监控功能实现
在application.yml中设置一些参数
#Spring Boot 默认是不注入这些属性值的,需要自己绑定
#druid 数据源专有配置
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
#如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
#则导入 log4j 依赖即可,Maven 地址: https://mvnrepository.com/artifact/log4j/log4j
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
然后编写配置类,在config包中新建DruidConfig
@Configuration
public class DruidConfig {
//使用私有属性,绑定配置文件
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
return new DruidDataSource();
}
//后台监控,web.xml ServletRegistrationBean
//因为spring boot内置了servlet容器,所以没有web.xml,想代替就使用ServletRegistrationBean
@Bean
public ServletRegistrationBean setViewServlet(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
//后台需要登录,设置账号密码
HashMap<String, String> initParameters = new HashMap<>();
//登录时的key是固定的不要变
initParameters.put("loginUsername","admin");
initParameters.put("loginPassword","123456");
//设置允许谁可以访问,空的就是谁都允许
initParameters.put("allow","");
//设置初始化参数
bean.setInitParameters(initParameters);
return bean;
}
启动程序访问http://localhost:8080/druid/进入监控后台
现在执行之前的SQL就可以看到执行的详细信息了
6、整合MyBatis
meven官网找到依赖
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!--顺便导个lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
-
再新建项目spring boot-06-mybatis,jdbc时选的依赖还选上
-
连上数据库,再导入依赖,把lombok也顺便导了。
-
配置数据源application.yml
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf-8
测试连接是否正常
@SpringBootTest
class SpringBoot06MybatisApplicationTests {
@Autowired(required = false)
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
System.out.println(dataSource.getClass());
System.out.println(dataSource.getConnection());
}
}
可以正常连接
6.1、编写实体pojo
新建包pojo,写user表的实体类
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
6.2、Mapper接口
新建mapper包,新建UserMapper接口,打上@Mapper注解表明了这是mybatis的mapper类
这里写增删改查的方法:
import com.zm.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
//查询所有
List<User> queryList();
//根据id查询
User queryById(int id);
//增加
int add(User user);
//修改
int update(User user);
//删除
int delete(int id);
}
6.3、UserMapper.xml
在resources下建mybatis.mapper,新建UserMapper.xml,在这里写sql
<?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.zm.mapper.UserMapper">
<select id="queryList" resultType="User">
select * from mybatis.user;
</select>
<select id="queryById" resultType="User">
select * from mybatis.user where id = #{id};
</select>
<insert id="add" parameterType="User">
insert into mybatis.user(id, name, pwd) VALUES (#{id},#{name},#{pwd});
</insert>
<update id="update" parameterType="User">
update mybatis.user set name =#{name},pwd=#{pwd} where id=#{id};
</update>
<delete id="delete" parameterType="int">
delete from mybatis.user where id=#{id};
</delete>
</mapper>
6.4、配置文件整合mybatis
#整合mybatis
mybatis:
type-aliases-package: com.zm.pojo
mapper-locations: classpath:mybatis/mapper/*.xml
6.5、编写UserController
@RestController
public class UserController {
@Autowired
UserMapper userMapper;
//查询所有
@RequestMapping("/query")
public List<User> query(){
return userMapper.queryList();
}
//根据id查询
@RequestMapping("/query/{id}")
public User queryById(@PathVariable("id") int id){
return userMapper.queryById(id);
}
//添加
@RequestMapping("/add")
public String add(){
int i = userMapper.add(new User(11,"哈喽","000000"));
if (i>0){
return "添加成功";
}else {
return "添加失败";
}
}
//修改
@RequestMapping("/update")
public String update(){
int i = userMapper.update(new User(11,"哈喽02","1110"));
if (i>0){
return "修改成功";
}else {
return "修改失败";
}
}
//删除
@RequestMapping("/delete/{id}")
public String delete(@PathVariable("id") int id){
userMapper.delete(id);
return "删除成功";
}
}
查询所有:
查询id为6的人:
增加一个人:
[外链图片转
再修改他:
再删除他