准备工作
一、导入静态页面
引入依赖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就可以识别了
- css的URL前面加@{}
- 超链接href前面加
-
将thymeleaf中的一些缓存去掉(作用:就是让一些页面的更改生效),不然css样式也会失效
-
#关闭模板引擎的缓存(作用:就是让一些页面的更改生效) spring: thymeleaf: cache: false
-
页面也需要清理缓存
-
-
html页面中的一些改变
- 图片src前面加th:
- 图片的URL前面加@{}
- {/}中表示根目录下(resources),@{/css/bootstrap.min.css},css就可以识别了
- 图片的URL前面加@{}
- 图片src前面加th:
-
其他页面同理
- 注:只需要改本地的链接
注: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用到的是
@{}
符号
- 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)}
)
- 写三元运算符时候需要用到thymeleaf中的工具类(判断不为空的:
-
成功跳转之后,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的隐藏域携带过来
- 解决:将id的隐藏域携带过来
十一、CRUD(删除——删除及404处理)
-
修改list页面中删除链接的跳转
-
Controller层编写
总结:
- CRUD功能实现