简单用个实例来加深SpringBoot的使用
一、基础准备
1.1 创建JavaBean
| 12
 3
 4
 
 | <dependency><groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 </dependency>
 
 | 
在SpringBoot中导入lombok依赖不能使用,还要进行插件安装
“Settings” –> “Plugins” –> 搜索”lomnok” –> 安装
 
| 12
 3
 4
 5
 6
 
 | @Data@AllArgsConstructor
 @NoArgsConstructor
 public class Department {
 private Integer id;
 private String departmentName;
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | @Data@AllArgsConstructor
 @NoArgsConstructor
 public class Employee {
 private Integer id;
 private String lastName;
 private String email;
 private Integer gender;
 private Department department;
 private Date date;
 }
 
 | 
1.2 创建对应的DAO类
为了方便,就暂时不整合Mybatis,就将数据存放在Java类中,并直接实现其方法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | public class DepartmentDao {
 
 private static Map<Integer, Department> departmentMap = null;
 
 static {
 departmentMap = new HashMap<>();
 
 departmentMap.put(101, new Department(101, "教学部"));
 departmentMap.put(102, new Department(102, "市场部"));
 departmentMap.put(103, new Department(103, "教研部"));
 departmentMap.put(104, new Department(104, "运营部"));
 departmentMap.put(105, new Department(105, "后勤部"));
 }
 
 
 public static Collection<Department> getDepartMents(){
 return departmentMap.values();
 }
 
 
 public static Department getDepartmentById(Integer id){
 return departmentMap.get(id);
 }
 }
 
 | 
| 12
 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
 
 | public class EmployeeDao {
 
 
 private static Map<Integer, Employee> employees;
 
 static{
 employees = new HashMap<>();
 
 employees.put(101, new Employee(101, "C酱", "CC.com", 1, DepartmentDao.getDepartmentById(101)));
 employees.put(102, new Employee(102, "咕料", "gu.com", 0, DepartmentDao.getDepartmentById(102)));
 employees.put(103, new Employee(103, "定春", "sadaharu.com", 0, DepartmentDao.getDepartmentById(103)));
 employees.put(104, new Employee(104, "YJJ", "yjj.com", 0, DepartmentDao.getDepartmentById(104)));
 employees.put(105, new Employee(105, "盐取", "tukubi.com", 0, DepartmentDao.getDepartmentById(105)));
 }
 
 
 private static Integer initId = 106;
 
 
 public static void addEmployee(Employee employee, Integer id){
 if (employee.getId() == null){
 employee.setId(initId++);
 }
 if (employee.getDepartment() == null){
 employee.setDepartment(DepartmentDao.getDepartmentById(id));
 }
 
 employees.put(employee.getId(), employee);
 }
 
 
 public static Collection<Employee> getEmployees(){
 return employees.values();
 }
 
 
 public static Employee getEmployeeById(Integer id){
 return employees.get(id);
 }
 
 
 public static void delete(Integer id){
 employees.remove(id);
 }
 }
 
 | 
1.3 拓展WebMvc配置类
| 12
 3
 4
 
 | @Configurationpublic class WebMvcConfig implements WebMvcConfigurer {
 
 }
 
 | 
1.4 实例需要的静态资源下载
- 百度网盘 提取码:vi6a 
- asserts放在静态资源文件夹 
- 其他html放在templates文件夹下 
二、设置主页
虽然将index.html直接放在静态资源文件夹就可以自动设置主页,但真正的开发中一般将网页和静态资源区分,所以会将页面放在templates文件夹中
因此需要导入模板引擎thymeleaf启动器
| 12
 3
 4
 
 | <dependency><groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-thymeleaf</artifactId>
 </dependency>
 
 | 
2.1 通过Controller跳转
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | @Controllerpublic class IndexController {
 
 
 @RequestMapping({"/", "/index.html"})
 public String getIndex(){
 return "index";
 }
 
 }
 
 | 
2.2 通过拓展WebMvc配置类跳转
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | @Configurationpublic class WebMvcConfig implements WebMvcConfigurer {
 
 
 @Override
 public void addViewControllers(ViewControllerRegistry registry){
 
 registry.addViewController("/").setViewName("index");
 registry.addViewController("/index.html").setViewName("index");
 }
 
 | 
2.3 解决CSS样式丢失问题
CSS样式丢失原因为thymeleaf模板引擎取值的方式不同
 
也顺便把其他页面的本地资源位置重新按照thymeleaf方式修改
三、国际化设置
所谓国际化,就是支持页面语言的切换
3.1 创建配置文件
- (1)在resources文件夹下创建名为i18n的文件夹(国际化 –> Internationalization –> 首字母i 和 尾字母之间隔了18个字母)
- (2)并在i18n文件夹下创建login.properties(名字随意)【默认语言】,login_zh_CN.properties【中文】,login_en_US.propertirs【英文】,会自动合并为login
- (3)添加网页中需要语言的参数,IDEA中有便捷方式快速添加
 
3.2 配置信息
| 12
 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
 
 | public class MessageSourceAutoConfiguration {
 private static final Resource[] NO_RESOURCES = {};
 
 @Bean
 @ConfigurationProperties(prefix = "spring.messages")
 public MessageSourceProperties messageSourceProperties() {
 return new MessageSourceProperties();
 }
 
 @Bean
 public MessageSource messageSource(MessageSourceProperties properties) {
 ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
 if (StringUtils.hasText(properties.getBasename())) {
 messageSource.setBasenames(StringUtils
 .commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
 }
 if (properties.getEncoding() != null) {
 messageSource.setDefaultEncoding(properties.getEncoding().name());
 }
 messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
 Duration cacheDuration = properties.getCacheDuration();
 if (cacheDuration != null) {
 messageSource.setCacheMillis(cacheDuration.toMillis());
 }
 messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
 messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
 return messageSource;
 }
 ||能配置的内容
 public class MessageSourceProperties {
 
 private String basename = "messages";
 
 private Charset encoding = StandardCharsets.UTF_8;
 }
 
 | 
总结:在配置文件中填写配置信息的位置spring.messages.basename=””
| 12
 3
 
 | spring:messages:
 basename: i18n.login
 
 | 
3.3 修改主页提取信息
 
3.4 语言切换设置
| 12
 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
 
 | WebMvcAutoConfiguration.java@Bean
 @ConditionalOnMissingBean
 @ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
 public LocaleResolver localeResolver() {
 if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
 return new FixedLocaleResolver(this.mvcProperties.getLocale());
 }
 AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
 localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
 return localeResolver;
 }
 
 ||跳转
 public class AcceptHeaderLocaleResolver implements LocaleResolver {
 @Override
 public Locale resolveLocale(HttpServletRequest request) {
 Locale defaultLocale = getDefaultLocale();
 if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
 return defaultLocale;
 }
 Locale requestLocale = request.getLocale();
 List<Locale> supportedLocales = getSupportedLocales();
 if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) {
 return requestLocale;
 }
 Locale supportedLocale = findSupportedLocale(request, supportedLocales);
 if (supportedLocale != null) {
 return supportedLocale;
 }
 return (defaultLocale != null ? defaultLocale : requestLocale);
 }
 }
 
 | 
总结:新建一个自定义的地区分解器,将次注入的WebMvc配置类中
 
- (3)自定义localeResolver(地区分解器)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | public class MyLocaleResolver implements LocaleResolver {
 
 @Override
 public Locale resolveLocale(HttpServletRequest request) {
 
 String language = request.getParameter("l");
 
 Locale locale = Locale.getDefault();
 if (language != null){
 
 String[] split = language.split("_");
 
 
 locale = new Locale(split[0], split[1]);
 }
 return locale;
 }
 
 @Override
 public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
 
 }
 }
 
 | 
- (4)将localeResolver注入WebMvc配置类中
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | @Configurationpublic class WebMvcConfig implements WebMvcConfigurer {
 
 
 @Override
 public void addViewControllers(ViewControllerRegistry registry){
 
 registry.addViewController("/").setViewName("index");
 registry.addViewController("/index.html").setViewName("index");
 }
 
 
 @Bean
 public LocaleResolver localeResolver(){
 return new MyLocaleResolver();
 }
 }
 
 | 
 
 
 
四、编写登录后的页面
4.1 编写主页
 
4.2 编写Controller跳转
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | @Controllerpublic class LoginController {
 
 @RequestMapping("/login")
 public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model){
 
 if ("莱特雷".equals(username) && "123".equals(password)){
 return "dashboard";
 }
 model.addAttribute("msg", "用户名或密码出现错误");
 return "index";
 }
 }
 
 | 
4.3 隐藏账号密码
 
- (2)解决问题
- 在网页跳转在套一层跳转
- 用Controller跳转 / 拓展WebMvc配置类编写
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | Controller修改@RequestMapping("/login")
 public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model modeln){
 
 if ("莱特雷".equals(username) && "123".equals(password)){
 return "redirect:/main.html";
 }
 model.addAttribute("msg", "用户名或密码出现错误");
 return "index";
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | WebMvc配置页面跳转@Configuration
 public class WebMvcConfig implements WebMvcConfigurer {
 
 
 @Override
 public void addViewControllers(ViewControllerRegistry registry){
 
 registry.addViewController("/").setViewName("index");
 registry.addViewController("/index.html").setViewName("index");
 registry.addViewController("/main.html").setViewName("dashboard");
 }
 
 | 
 
五、添加拦截器
添加中间跳转隐藏密码出现新的问题:直接页面输入localhost:8080/main.html会绕过登录界面,此时需要配置拦截器来拦截下来
5.1 创建自定义的拦截器
- 类实现HandlerInterceptor接口,重写方法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | public class MyInterceptor implements HandlerInterceptor {
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 
 Object login = request.getSession().getAttribute("UserLogin");
 if (login == null){
 request.setAttribute("msg", "没有权限,请先登录");
 request.getRequestDispatcher("/index.html").forward(request, response);
 return false;
 }
 return true;
 }
 }
 
 | 
5.2 修改Controller跳转
- 为了用户登录后返回一个Session,方便拦截器拦截
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | @RequestMapping("/login")public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model, HttpSession session){
 
 if ("莱特雷".equals(username) && "123".equals(password)){
 session.setAttribute("UserLogin", username);
 return "redirect:/main.html";
 }
 model.addAttribute("msg", "用户名或密码出现错误");
 return "index";
 }
 
 | 
5.3 注册拦截器
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | @Configurationpublic class WebMvcConfig implements WebMvcConfigurer {
 
 
 @Override
 public void addViewControllers(ViewControllerRegistry registry){
 
 registry.addViewController("/").setViewName("index");
 registry.addViewController("/index.html").setViewName("index");
 registry.addViewController("/main.html").setViewName("dashboard");
 }
 
 
 @Bean
 public LocaleResolver localeResolver(){
 return new MyLocaleResolver();
 }
 
 
 @Override
 public void addInterceptors(InterceptorRegistry registry) {
 registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/", "/index.html", "/login", "/asserts/**");
 
 }
 }
 
 | 
六、员工管理页面
为了方便管理,将展示员工list的页面放在”emp”文件夹下
6.1 编写Controller跳转
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | @Controllerpublic class EmployeeController {
 
 
 @RequestMapping("/emp/getEmps")
 public String getEmps(Model model){
 Collection<Employee> employees = EmployeeDao.getEmployees();
 model.addAttribute("emps", employees);
 return "emp/list";
 }
 }
 
 | 
6.2 修改页面
(1)代码复用
- 由于dashboard.html 和 list.html 有大量的重复代码(顶部导航栏、侧边栏)
- 为了方便修改,将重复代码提取,进行统一修改
 
 
(2)修改复用代码
 
6.3 解决高亮问题
点击页面时,总是首先那个按钮会发亮,点击员工管理没发亮

\
 
 
6.4 员工表单
修改list.html页面,将后端的数据提取出来,并放在一个表单中
 
 
七、添加员工功能
7.1 添加按钮
修改list.html页面,增加一个“添加员工”按钮,并跳转Contoller进行业务处理
 
7.2 添加员工页面
复制list.html进行修改,变成add.html页面,把表内容删除,变成表单
| 12
 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
 
 | <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
 <form th:action="@{/emp/addEmp}" method="post">
 <div class="form-group">
 <label>LastName</label>
 <input type="text" name="lastName" class="form-control" placeholder="莱特雷">
 </div>
 <div class="form-group">
 <label>Email</label>
 <input type="text" name="email" class="form-control" placeholder="letere.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="0">
 <label class="form-check-label">男</label>
 </div>
 <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>
 <div class="form-group">
 <label>Department</label>
 <select class="form-group" name="department.id">
 
 <option th:each="dpet:${departments}" th:text="${dpet.getDepartmentName()}" th:value="${dpet.getId()}"></option>
 </select>
 </div>
 <div class="form-group">
 <label>Date</label>
 <input type="text" name="date" class="form-control" placeholder="2020-12-01">
 
 </div>
 <button type="submit" class="btn btn-sm btn-primary">添加</button>
 </form>
 </main>
 
 | 
7.3 Controller创建相应的业务
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | @Controllerpublic class EmployeeController {
 
 
 @GetMapping("/emp")
 public String toAddEmp(Model model){
 Collection<Department> departments = DepartmentDao.getDepartMents();
 model.addAttribute("departments", departments);
 return "emp/add";
 }
 
 
 @RequestMapping("/emp/addEmp")
 public String addEmp(Employee employee){
 EmployeeDao.addEmployee(employee, employee.getDepartment().getId());
 return "redirect:/emp/getEmps";
 }
 }
 
 | 
 
八、修改员工功能
8.1 修改按钮
修改list.html,添加一个修改员工按钮
 
 
8.2 创建修改页面
复制add.html进行修改
 
8.3 Controller创建相应业务
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | @Controllerpublic class EmployeeController {
 
 
 @RequestMapping("/emp/{id}")
 public String toUpdateEmp(@PathVariable("id") Integer id, Model model){
 Employee employee = EmployeeDao.getEmployeeById(id);
 Collection<Department> departments = DepartmentDao.getDepartMents();
 
 model.addAttribute("emp", employee);
 model.addAttribute("departments", departments);
 return "emp/update";
 }
 
 
 @RequestMapping("/emp/updateEmp")
 public String updateEmp(Employee employee){
 EmployeeDao.addEmployee(employee, employee.getDepartment().getId());
 return "redirect:/emp/getEmps";
 }
 }
 
 | 
 
九、删除员工功能和收尾
9.1 Controller添加删除员工业务
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | @Controllerpublic class EmployeeController {
 
 
 @RequestMapping("/delemp/{id}")
 public String deleteEmp(@PathVariable("id") Integer id){
 EmployeeDao.delete(id);
 return "redirect:/emp/getEmps";
 }
 
 }
 
 | 
9.2 添加错误页面
- 在templates文件夹下创建”error”文件夹,将对应的错误页面改名为错误代码,放进”error”文件夹,thymeleaf会自动跳转,不用填写相应跳转
9.3 添加注销功能
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | @Controllerpublic class LoginController {
 
 
 @RequestMapping("/logout")
 public String logout(HttpSession session){
 session.invalidate();
 return "redirect:index.html";
 }
 
 }
 
 |