准备工作
一、导入静态页面
引入依赖lombok
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
二、编写了pojo和dao
三、编写页面跳转
- 原来的方式:在controller中创建indexController
@Controller
public class IndexController {
/*//在MyMvcConfig中配置了addViewControllers,这里就不需要了
//这样配置css加载不了
@RequestMapping({"/", "/index.html"})
public String index(){
return "index";
}*/
}
- ###现在用扩展SpringMVC的方式:在config中创建MyMvcConfig
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//添加视图控制,视图跳转
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
- controller呢个类就可以删了
四、页面现在css,图片加载不了,开始引入thymeleaf
- 在html上加命名空间
- html页面中的一些改变
- 超链接href前面加
th:
- css的URL前面加@{}
- {/}中表示根目录下(resources),@{/css/bootstrap.min.css},css就可以识别了
- 将thymeleaf中的一些缓存去掉(作用:就是让一些页面的更改生效),不然css样式也会失效
#关闭模板引擎的缓存(作用:就是让一些页面的更改生效)
spring:
thymeleaf:
cache: false
- 页面也需要清理缓存
- html页面中的一些改变
- 图片src前面加th:
- 图片的URL前面加@{}
- {/}中表示根目录下(resources),@{/css/bootstrap.min.css},css就可以识别了
- 其他页面同理
- 注:只需要改本地的链接
注:yaml配置文件中server.servlet.context-path配置的作用
- 定义: server.servlet.context-path= # Context path of the application. 应用的上下文路径,也可以称为项目路径,是构成url地址的一部分。
- server.servlet.context-path不配置时,默认为 / ,如:localhost:8080/xxxxxx
- 当server.servlet.context-path有配置时,比如 /demo,此时的访问方式为localhost:8080/demo/xxxxxx
- 注:页面中加了@{/…}就是表示项目目录,万能匹配
总结(三,四):
- 首页配置:注意点,所有页面的静态资源都需要使用thymeleaf接管;
- url中thymeleaf用到的是
@{}
符号
五、页面国际化(页面中英文的切换:适配)
- 首先确保IDEA配置
fileEncoding
中都是utf-8 - 在
resoures
目录下创建i18n
【是国际化的缩写internationalization:首字母i+中间有18个字母+尾字母n】 - 创建配置文件
- login.properties
- login_zh_CN.properties
- login_en_US.properties
- 可视化配置(一次可以配置三个地方:每个页面的元素都需要)
- 如何识别配置的这些国际化——找到自动国际化类:
MessageSourceAutoConfiguration
——>MessageSourceProperties
MessageSourceAutoConfiguration下的
@ConfigurationProperties(prefix = "spring.messages")
MessageSourceProperties下的
private String basename = "messages";
/**
* Message bundles encoding.
*/
private Charset encoding = StandardCharsets.UTF_8;
spring:
#关闭模板引擎的缓存(作用:就是让一些页面的更改生效)
thymeleaf:
cache: false
# 配置识别国际化(我们配置文件的真实位置)
messages:
basename: i18n.login
- 配置国际化的thymeleaf是
#{}
- 在config中自己自定义一个国际化解析器—>实现LocaleResolver
- 注:以前前端带参是?,现在thymeleaf是()
- 编写MyLocaleResolver——仿照AcceptHeaderLocaleResolver中的resolveLocale方法写
public class MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request) {
//获取请求中的语言参数
String language = request.getParameter("l");
Locale locale = Locale.getDefault(); //如果没有就使用默认的
//如果请求的参数携带了国际化的参数
if(StringUtils.hasLength(language)){ //也可以写成!StringUtils.isEmpty(language)
//zh_CN的字符串分割,分割成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) {
}
}
- 往Spring容器中注入一个组件(在MyMvcConfig下用@Bean)
//往容器中注入一个组件(MyLocaleResolver)
//自定义的国际化组件就生效了
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
总结(五):
注意点:
- 我们需要配置i18n文件
- 我们如果需要项目中进行按钮自动切换,我们需要自定义一个组件
LocaleResolver
- 记得将自己写的组件配置到Spring容器中
@Bean
- 国际化中thymeleaf用到的是
#{}
符号
六、登录功能实现
- 更改index.html中请求跳转
<form class="form-signin" th:action="@{/user/login}">
- 创建Controller类,LoginController
@Controller
public class LoginController {
@RequestMapping("/user/login")
//@ResponseBody //加了这个就跳转不到视图了,变成index了
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
Model model){
//具体的业务
if(StringUtils.hasLength(username) && "123456".equals(password)){
return "dashboard";
}else {
//告诉用户,你登录失败了
model.addAttribute("msg", "用户名或者密码错误");
return "index";
}
}
}
- Model model:(作用就是页面回显——就是将后台的数据,返回到前端的页面上。)
//告诉用户,你登录失败了
model.addAttribute("msg", "用户名或者密码错误");
- index.html中提交表单需要name属性
- 输入错误后的提示没有,需要在index加一个提示
- 写三元运算符时候需要用到thymeleaf中的工具类(判断不为空的:
${#strings.isEmpty(name)}
)
- 成功跳转之后,url有问题(账号密码都显示)
- 在
MyMvcConfig
映射一下就可以了 - 登录成功之后需要重定向过去
- 重定向:return “redirect:/user/index”;
- 结果:(所以我们访问的页面有时候就是一个请求)
- 解决前
- 解决后
总结:
- 虽然页面做好了,但是我们登不登陆,输入main.html都可以进入到页面
- 所以我们接下来需要做:登录拦截器
七、登录拦截器
- 在config中创建类实现
HandlerInterceptor
- 只要实现了
HandlerInterceptor
接口的都是拦截器
- 重写里面的方法(preHandle:因为我们要放行)
- 注:request.getSession().getAttribute(获取session中的数据,和session.setAttribute搭配使用。获取的是Object类型。)
- 如果登录成功,需要加入session(用户名)
- 注:request.getRequestDispatcher(“URL”).forward(request,response);(重定向回去:属于转发,也是服务器跳转,相当于方法调用。)
- URL中所包含的“/”表示应用程序(项目)的路径。
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中配置@Bean来注册到容器中——自定义的拦截器才能生效
//往容器中注入一个组件(LoginHandlerInterceptor)
//重写拦截器组件
@Override
public void addInterceptors(InterceptorRegistry registry) {
/**
* addPathPatterns("/**"):拦截所有请求
* excludePathPatterns("/index.html"):除了....
*/
registry.addInterceptor(new LoginHandlerInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/index.html", "/", "/user/login", "/css/**", "/js/**", "/img/**");
}
- 将登录后页面中的用户名,换成session中取出的名字
[[${session.loginUser}]]
八、CRUD(查看——展示员工列表)
- 编写员工数据的提取EmployeeController
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao;
@RequestMapping("/emps")
public String list(Model model){
Collection<Employee> employees = employeeDao.getAll();
model.addAttribute("emps", employees);
return "emp/list";
}
}
- dashboard和list页面之间有相同的导航栏——需要提取出来:用到模板引擎的Fragments(使用的是~{})…波浪线
- 注: 标签定义导航链接的部分。
- 对不同页面中的导航栏做删除并替换在——dashboard.html中先定义一个id来抽取公共页面。
- 然后在list.html中,删除相同的侧边栏并替换
- 注
th:insert
:相当于嵌入了一层div - 注
th:replace
:相当于直接替换元素【推荐使用】
<!--删除相同的侧边栏并替换-->
<div th:insert="~{dashboard :: sidebar}"></div>
- 将这些共同组件提取到一个新的页面
- 在
templates
—>commons
—>下创建commons.html
- 首先导入模板引擎thymeleaf的命名空间
- 将导航栏代码复制进来做上面步骤
- 其他页面使用注意:这时候不是根目录了需要加
~{/commons/commons :: topbar}
- 侧边栏点中后进行高亮显示功能
- 调用模板引擎的时候给他传递一些参数
- 做高亮判断
总结:
- 员工列表展示
- 提取公共页面
-
th:fragment="topbar"
-
th:replace="~{/commons/commons :: topbar}"
- 如果要传递参数,可以直接使用()传参,接收判断即可
- 列表循环展示
- 注:tr表示table中的行;th表示table中的表的头部,例如一篇文章的标题;td表示table中的列
- 注意:时间的转换看模板引擎thymeleaf文档
九、CRUD(增加——增加员工实现)
- add页面的添加
- 获取部门信息【显示用@GetMapping】
EmployeeController.java下
//这里是GetMapping:只是获得一个跳转
@GetMapping("/emp")
public String toAddpage(Model model){
//查出所有部门的信息
Collection<Department> departments = departmentDao.getDepartments();
//返回到前端
model.addAttribute("departments", departments);
return "emp/add";
}
- 提交表单时候一般用【提交用@PostMapping】
EmployeeController.java下
//这里是PostMapping:用来提交表单
@PostMapping("/emp")
public String toEmp(Employee employee){
//添加员工的操作
//调用底层业务方法保存员工信息
employeeDao.save(employee);
//添加成功后,会重定向到emps页面
return "redirect:/emps";
}
- 重定向(redirect)和转发(forward)的区别
- 注:这里的name是department.id,因为传入的参数为id(我们在controller接收的是一个Employee,所以我们提交的是一个属性)
- 显示和提交用不同的Mapping就是RESTful风格
- 注意:spring时间格式默认是yyyy/MM/dd,需要改为yyyy-MM-dd格式时候
- 如果需要别的时间输入格式就需要自定义
# 时间日期格式化
spring:
mvc:
date-format: yyyy-MM-dd
- 改完之后,以前的格式在适用
十、CRUD(增加——修改员工信息)
- list页面按键的修改
- 新增修改页面
- input是value,div才是text
- 性别gender用checked
- 下拉框的用selected
- Controller增加跳转页面和新增员工
- 注:日期格式化很重要
- 注:每次点击都会增加一个员工
- 解决:将id的隐藏域携带过来
十一、CRUD(删除——删除及404处理)
- 修改list页面中删除链接的跳转
- Controller层编写
总结:
- CRUD功能实现