SpringBoot:web开发

基本配置

springBoot 版本2.2.4 + web

<!--Thymeleaf,我们都是基于3.x开发-->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>

<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

A.创建实体类

//部门表
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Department {
    private Integer id;
    private String departmentName;
}
//员工表
@Data
@NoArgsConstructor
public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;//0:女,1:男
    private Department department;
    private Date birth;

    public Employee(Integer id, String lastName, String email, Integer gender, Department department) {
        this.id = id;
        this.lastName = lastName;
        this.email = email;
        this.gender = gender;
        this.department = department;
        //默认的创建日期
        this.birth = new Date();
    }
}

B.部门Dao

package com.rgh.dao;
//部门Dao
@Repository
public class DepartmentDao {
    //模拟数据库中的数据
    private static Map<Integer,Department> departments = null;
    static{
        departments = new HashMap<>();//创建一个部门表
        departments.put(101,new Department(101,"教学部"));
        departments.put(102,new Department(102,"市场部"));
        departments.put(103,new Department(103,"教研部"));
        departments.put(104,new Department(104,"运营部"));
        departments.put(105,new Department(105,"后勤部"));
    }
    //获得所有部门信息
    public Collection<Department> getDepartments(){
        return departments.values();
    }
    //通过id得到部门
    public Department getDepartmentById(Integer id){
        return departments.get(id);
    }
}

C. 员工Dao

package com.rgh.dao;
//员工Dao
@Repository
public class EmployeeDao {
    //模拟数据库中的数据
    private static Map<Integer,Employee> employees = null;
    //员工有所属的部门
    @Autowired
    private DepartmentDao departmentDao;
    static{
        employees = new HashMap<>();//创建一个部门表
        employees.put(1001,new Employee(1001,"AA","A365854987@qq.com",0,new Department(101,"教学部")));
        employees.put(1002,new Employee(1002,"BB","B365854987@qq.com",1,new Department(102,"市场部")));
        employees.put(1003,new Employee(1003,"CC","C365854987@qq.com",0,new Department(103,"教研部")));
        employees.put(1004,new Employee(1004,"DD","D365854987@qq.com",1,new Department(104,"运营部")));
        employees.put(1005,new Employee(1005,"EE","E365854987@qq.com",0,new Department(105,"后勤部")));
    }
    //主键自增
    private static Integer initId = 1006;
    //增加一个员工
    public void save(Employee employee){
        if(employee.getId() == null){
            employee.setId(initId++);
        }
        employee.setDepartment(departmentDao.getDepartmentById(employee.getDepartment().getId()));
        employees.put(employee.getId(),employee);
    }
    //查询所有员工
    public Collection<Employee> getAll(){
        return employees.values();
    }
    //通过id查询员工
    public Employee getEmployeeById(Integer id){
        return employees.get(id);
    }
    //删除员工通过id
    public void delete(Integer id){
        employees.remove(id);
    }
}

1. 配置首页

1.1 自定义视图控制器

package com.rgh.config;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
    }
}

1.2 html导入thymeleaf

<html lang="en" xmlns:th="http://www.thymeleaf.org">

1.3 修改页面中资源路径@{}

<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">

1.4 application.properties文件配置

# 关闭默认图标
spring.mvc.favicon.enabled=false
# 关闭引擎的缓存
spring.thymeleaf.cache=false

2.国际化

2.1 新建文件夹,配置文件

2.2 全局配置文件

# 我们的配置文件放在的真实位置
spring.messages.basename=i18n.login

2.3 login.properties

login.btn=登陆
login.password=密码 
login.remember=记住我
login.tip=请登录
login.username=用户名
<form class="form-signin" action="dashboard.html">
    <img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">
    <h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
    <input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
    <input type="password" class="form-control" th:placeholder="#{login.password}" required="">
    <div class="checkbox mb-3">
        <label>
            <input type="checkbox" value="remember-me"> [[#{login.remember}]]
        </label>
    </div>
    <button class="btn btn-lg btn-primary btn-block" type="submit">[[#{login.btn}]]</button>
    <p class="mt-5 mb-3 text-muted">© 2017-2018</p>
    <a class="btn btn-sm">中文</a>
    <a class="btn btn-sm">English</a>
</form>

2.4 写一个自己的国际化解析器实现LocaleResolver接口

package com.rgh.config;
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 httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
    }
}

2.5 连接请求

()里面带参数

<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>

2.6 放到Bean里面

package com.rgh.config;
@Configuration
public class MyMvcConfig 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();
    }
}
  1. 首页配置:
    1. 注意点,所有页面的静态资源都需要使用thymeleaf接管;
    2. url:@{}
  2. 页面国际化:
    1. 我们需要配置i18n文件
    2. 我们如果需要在项目中进行按钮自动切换,我们需要自定义一个组件LocaleResolver
    3. 记得将自己写的组件配置到spring容器QBean
    4. #{}

3. 登陆+拦截器

链接

<form class="form-signin" th:action="@{/user/login}">
@Controller
public class LoginController {

    @RequestMapping("/user/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password,
                        Model model,
                        HttpSession session){
        //具体的业务
        if(!StringUtils.isEmpty(username) && "123456".equals(password)){
            session.setAttribute("loginUser",username);
            return "redirect:/main.html";
        }else{
            //告诉用户登陆失败
            model.addAttribute("msg","用户名或密码错误!");
            return "index";
        }
    }
}

显示错误信息,thymeleaf工具方法判断是否为空

<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>

增加一个首页映射

package com.rgh.config;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        .....
            registry.addViewController("/main.html").setViewName("dashboard");
    }
    .....
}

写一个登陆拦截器LoginHandlerInterceptor

package com.rgh.config;
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;
        }
    }
}

配置类中

重写addInterceptors(InterceptorRegistry registry)方法

添加登陆拦截器和拦截的请求,不拦截的请求

package com.rgh.config;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
....
   @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
                .excludePathPatterns("/index.html","/","/user/login","/css/**","/js/**","/img/**");
    }
}

获取登陆名

<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${session.loginUser}]]</a>

4. 员工列表

4.1 侧边栏按钮

<a class="nav-link" th:href="@{/emps}">

4.2 Controller层

package com.rgh.controller;
@Controller
public class EmployeeController {
    @Autowired
    private EmployeeDao employeeDao;
    @RequestMapping("/emps")
    public String list(Model model){
        Collection<Employee> all = employeeDao.getAll();
        model.addAttribute("emps",all);
        return "/emp/list";
    }
}

4.3 提取公共页面commons

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <!--头部导航栏-->
    <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar">
        ....
    </nav>
    <!--侧边导航栏-->
    <nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">
        ....
    </nav>
</html>

4.4 公共部分插入

<!--头部-->
<div th:replace="~{commons/commons::topbar}"></div>
<!--侧边栏-->
<div th:replace="~{commons/commons::sidebar}"></div>

4.5 按钮点击高亮

传递参数active

<div th:replace="~{commons/commons::sidebar(active='main.html')}"></div>

通过参数判断是否高亮

<a th:class="${active=='main.html'?'nav-link active':'nav-link'}" th:href="@{/index.html}">

4.6 列表循环展示

<thead>
    <tr>
        <th>id</th>
        <th>lastName</th>
        <th>email</th>
        <th>gender</th>
        <th>department</th>
        <th>birth</th>
        <th>操作</th>
    </tr>
</thead>
<tbody>
    <tr th:each="emp:${emps}">
        <td th:text="${emp.getId()}"></td>
        <td>[[${emp.getLastName()}]]</td>
        <td th:text="${emp.getEmail()}"></td>
        <td th:text="${emp.getGender()==0?'女':'男'}"></td>
        <td th:text="${emp.department.getDepartmentName()}"></td>
        <td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}"></td>
        <td>
            <button class="btn btn-sm btn-primary">编辑</button>
            <button class="btn btn-sm btn-danger">删除</button>
        </td>
    </tr>

</tbody>

5. 添加员工

5.1 链接

<h2><a class="btn btn-sm btn-success" th:href="@{/emp}">添加员工</a> </h2>

5.2 Controller中下拉框需要查找

package com.rgh.controller;
@Controller
public class EmployeeController {
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private DepartmentDao departmentDao;
...
    @GetMapping("/emp")
    public String toAddpage(Model model){
        //查出所有部门的信息
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("departments",departments);
        return "emp/add";
    }
}

5.3 下拉菜单的获取

注意:提交的是department的id

<select class="form-control" name="department.id">
    <option th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
</select>

5.4 员工生日的日期格式

默认是yyyy/MM/dd

在配置文件application.properties中修改

# 时间日期格式化
spring.mvc.date-format=yyyy-MM-dd

6. 修改员工

6.1 按钮链接

<a class="btn btn-sm btn-primary" th:href="@{/emp/}+${emp.getId()}">编辑</a>

6.2 Controller层

package com.rgh.controller;
@Controller
public class EmployeeController {
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private DepartmentDao departmentDao;
...
    //去员工的修改页面
    @GetMapping("/emp/{id}")
    public String toUpdateEmp(@PathVariable("id") Integer id,Model model){
        //查出原来的数据
        Employee employeeById = employeeDao.getEmployeeById(id);
        model.addAttribute("emp",employeeById);
        //查出所有部门的信息
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("departments",departments);
        return "emp/update";
    }
}

6.3 下拉菜单,单选按钮,日期的回显方式

<input type="hidden" name="id" th:value="${emp.getId()}">
<div class="form-group">
    <label>LastName</label>
    <input type="text" th:value="${emp.getLastName()}" name="lastName" class="form-control" placeholder="kuangshen">
</div>
<div class="form-group">
    <label>Email</label>
    <input type="email" th:value="${emp.getEmail()}" name="email" class="form-control" placeholder="24736743@qq.com">
</div>
<div class="form-group">
    <label>Gender</label><br/>
    <div class="form-check form-check-inline">
        <input th:checked="${emp.getGender() == 1}" class="form-check-input" type="radio" name="gender"  value="1">
        <label th:checked="${emp.getGender() == 0}" 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>
    <select class="form-control" name="department.id">
        <option th:selected="${dept.getId() == emp.getDepartment().getId()}" th:each="dept:${departments}" th:text="${dept.getDepartmentName()}" th:value="${dept.getId()}"></option>
    </select>
</div>
<div class="form-group">
    <label>Birth</label>
    <input type="text" th:value="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}" name="birth" class="form-control" placeholder="kuangstudy">
</div>

6.4 表单提交链接

<form th:action="@{/updateEmp}" method="post">

6.5 Controller层

package com.rgh.controller;
@Controller
public class EmployeeController {
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private DepartmentDao departmentDao;
...
    @PostMapping("/updateEmp")
    public String updateEmp(Employee employee){
        employeeDao.save(employee);
        return "redirect:/emps";
    }
}

7. 删除员工

7.1 删除连接

<a class="btn btn-sm btn-danger" th:href="@{/delemp/}+${emp.getId()}">删除</a>

7.2 Controller层

package com.rgh.controller;
@Controller
public class EmployeeController {
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private DepartmentDao departmentDao;
......
    @GetMapping("/delemp/{id}")
    public String delEmp(@PathVariable("id") Integer id){
        employeeDao.delete(id);
        return "redirect:/emps";
    }
}

8. 404页面

新建error文件夹把404页面放到里面

9. 注销

9.1 注销连接

<a class="nav-link" th:href="@{/user/logout}">注销</a>

9.2 Controller层

package com.rgh.controller;
@Controller
public class LoginController {
......
    @RequestMapping("/user/logout")
    public String logout(HttpSession httpSession){
        httpSession.invalidate();
        return "redirect:/index.html";
    }
}

参考B栈狂神java

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容