【springboot__实战】
1、配置文件
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 热加载-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<!--<scope>true</scope>-->
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://172.20.10.11:3306/test?characterEncoding=UTF-8&serverTimezone=UTC
driver-class-name: com.mysql.jdbc.Driver
mybatis:
config-location: classpath:mybatis/mybatis-config.xml #指定全局配置文件的位置
mapper-locations: classpath:mybatis/mapper/*.xml
type-aliases-package: k.entity #指定sql映射文件的位置
Boot11StudentManagerApplication
@MapperScan(value = "k.mapper")
@SpringBootApplication
public class Boot11StudentManagerApplication {
public static void main(String[] args) {
SpringApplication.run(Boot11StudentManagerApplication.class, args);
}
}
2、组件
ExceptionController
@ControllerAdvice
public class ExceptionController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler(Exception.class)
@ResponseBody
public Object handleException(Exception ex, HttpServletRequest request) {
boolean isAjax = "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"));
if (!isAjax) {
ModelAndView modelAndView = new ModelAndView("/error");//配置需要跳转的Controller方法
request.setAttribute("message", ex.getMessage());
return modelAndView;
} else {//返回json
ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
modelAndView.addObject("code", "500");
modelAndView.addObject("message", ex.getMessage());
modelAndView.addObject("data", "");
logger.error("发生异常 " + ex.toString());
// ex.printStackTrace();
return modelAndView;
}
}
}
HomeController
@Controller
public class HomeController {
@RequestMapping("/errors")
public String getErrorHtml(HttpServletRequest request, Model model) {
Object message = request.getAttribute("message");
model.addAttribute("message", message);
return "error";
}
}
LoginHandlerInterceptor
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object user = request.getSession().getAttribute("loginUser");
if (user != null) {
return true;
}
boolean isAjax = "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"));
if (isAjax) {
response.setContentType("application/json; charset=utf-8");
Map<String, Object> map = new HashMap();
map.put("code", "200");
map.put("message", "没有权限请先登陆");
PrintWriter writer = response.getWriter();
writer.print(objectMapper.writeValueAsString(map));
writer.close();
} else {
request.setAttribute("message", "没有权限请先登陆");
request.getRequestDispatcher("/errors").forward(request, response);
}
return false;
}
}
MyErrorAttributes 暂未
@Component
public class MyErrorAttributes extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
Map<String, Object> map = super.getErrorAttributes(webRequest, options);
Throwable error = getError(webRequest);
map.put("testError", "222");
Map<String, Object> ex = (Map<String, Object>) webRequest.getAttribute("ex", 0);
map.put("ex", ex);
return map;
}
}
MyErrorViewResolver 暂未
@Component
public class MyErrorViewResolver extends DefaultErrorViewResolver {
public MyErrorViewResolver(ApplicationContext applicationContext, ResourceProperties resourceProperties) {
super(applicationContext, resourceProperties);
}
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
// return super.resolveErrorView(request, status, model);
model.put("msg", "发生异常");
return new ModelAndView("/error", model);
}
}
3、k.config
DruidConfig
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid的监控
//1、配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
initParams.put("allow","");//默认就是允许所有访问
initParams.put("deny","192.168.15.21");
bean.setInitParameters(initParams);
return bean;
}
//2、配置一个web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
MyBatisConfig
@org.springframework.context.annotation.Configuration
public class MyBatisConfig {
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return new ConfigurationCustomizer() {
@Override
public void customize(Configuration configuration) {
configuration.setMapUnderscoreToCamelCase(true);
}
};
}
}
Student
public class Student {
private int id;
private int student_id;
private String name;
private int age;
private String sex;
private Date birthday;
}
StudentController
@Controller
public class StudentController {
@Autowired
private StudentService studentService;
@RequestMapping("/addStudent")
public String addStudent(HttpServletRequest request, HttpServletResponse response) {
Student student = new Student();
int studentID = Integer.parseInt(request.getParameter("student_id"));
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String sex = request.getParameter("sex");
Date birthday = null;
// String 类型按照 yyyy-MM-dd 的格式转换为 java.util.Date 类
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
birthday = simpleDateFormat.parse(request.getParameter("birthday"));
} catch (Exception e) {
e.printStackTrace();
}
student.setStudent_id(studentID);
student.setName(name);
student.setAge(age);
student.setSex(sex == "男" ? "1" : "0");
student.setBirthday(birthday);
studentService.addStudent(student);
return "redirect:listStudent";
}
@RequestMapping("/listStudent")
public String listStudent(HttpServletRequest request, HttpServletResponse response) {
// int a = 2 / 0;
// 获取分页参数
int start = 0;
int count = 10;
try {
start = Integer.parseInt(request.getParameter("page.start"));
count = Integer.parseInt(request.getParameter("page.count"));
} catch (Exception e) {
}
Page page = new Page(start, count);
List<Student> students = studentService.list(page.getStart(), page.getCount());
int total = studentService.getTotal();
page.setTotal(total);
request.setAttribute("students", students);
request.setAttribute("page", page);
return "listStudent";
}
@RequestMapping("/deleteStudent")
public String deleteStudent(int id) {
studentService.deleteStudent(id);
return "redirect:listStudent";
}
@RequestMapping("/editStudent")
public ModelAndView editStudent(int id) {
ModelAndView mav = new ModelAndView("editStudent");
Student student = studentService.getStudent(id);
mav.addObject("student", student);
return mav;
}
@RequestMapping("/updateStudent")
public String updateStudent(HttpServletRequest request, HttpServletResponse response) {
Student student = new Student();
int id = Integer.parseInt(request.getParameter("id"));
int student_id = Integer.parseInt(request.getParameter("student_id"));
String name = request.getParameter("name");
int age = Integer.parseInt(request.getParameter("age"));
String sex = request.getParameter("sex");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date birthday = null;
try {
birthday = simpleDateFormat.parse(request.getParameter("birthday"));
} catch (Exception e) {
e.printStackTrace();
}
student.setId(id);
student.setStudent_id(student_id);
student.setName(name);
student.setAge(age);
student.setSex(sex);
student.setBirthday(birthday);
studentService.updateStudent(student);
return "redirect:listStudent";
}
}
StudentService
public interface StudentService {
/**
* 获取到 Student 的总数
*
* @return
*/
int getTotal();
/**
* 增加一条数据
*
* @param student
*/
void addStudent(Student student);
/**
* 删除一条数据
*
* @param id
*/
void deleteStudent(int id);
/**
* 更新一条数据
*
* @param student
*/
void updateStudent(Student student);
/**
* 找到一条数据
*
* @param id
* @return
*/
Student getStudent(int id);
/**
* 列举出从 start 位置开始的 count 条数据
*
* @param start
* @param count
* @return
*/
List<Student> list(int start, int count);
}
StudentServiceImpl
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
StudentDao studentDao;
public int getTotal() {
return studentDao.getTotal();
}
public void addStudent(Student student) {
studentDao.addStudent(student);
}
public void deleteStudent(int id) {
studentDao.deleteStudent(id);
}
public void updateStudent(Student student) {
studentDao.updateStudent(student);
}
public Student getStudent(int id) {
return studentDao.getStudent(id);
}
public List<Student> list(int start, int count) {
return studentDao.list(start, count);
}
}
StudentDao
@Repository
public interface StudentDao {
int getTotal();
void addStudent(Student student);
void deleteStudent(int id);
void updateStudent(Student student);
Student getStudent(int id);
List<Student> list(int start, int count);
}
StudentDao.xml
<?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">
<!-- 将namespace的值设置为DAO类对应的路径 -->
<mapper namespace="k.mapper.StudentDao">
<!-- 查询数据条目 -->
<select id="getTotal" resultType="int">
SELECT COUNT(*) FROM student
</select>
<!-- 增加一条数据 -->
<insert id="addStudent" parameterType="Student">
INSERT INTO student VALUES(NULL, #{student_id}, #{name}, #{age}, #{sex}, #{birthday})
</insert>
<!-- 删除一条数据 -->
<delete id="deleteStudent" parameterType="int">
DELETE FROM student WHERE id = #{id}
</delete>
<!-- 更新一条数据 -->
<update id="updateStudent" parameterType="Student">
UPDATE student SET student_id = #{student_id}, name = #{name},
age = #{age}, sex = #{sex}, birthday = #{birthday} WHERE id = #{id}
</update>
<!-- 查询一条数据 -->
<select id="getStudent" resultMap="student" parameterType="int">
SELECT * FROM student WHERE id = #{id}
</select>
<resultMap id="student" type="student">
<id column="id" property="id"/>
<result column="student_id" property="student_id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday" javaType="java.sql.Date"/>
</resultMap>
<!-- 查询从start位置开始的count条数据-->
<select id="list" resultMap="student">
SELECT * FROM student ORDER BY student_id desc limit #{param1}, #{param2}
</select>
</mapper>
listStudent.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link th:href="@{/script/css/bootstrap/3.3.6/bootstrap.min.css}" rel="stylesheet">
<link th:href="@{/script/css/style.css}" rel="stylesheet">
<script th:src="@{/script/js/jquery/2.0.0/jquery.min.js}"></script>
<script th:src="@{/script/js/bootstrap/3.3.6/bootstrap.min.js}"></script>
<base th:href="${#request.getContextPath()}+''">
<title>学生管理页面 - 首页</title>
<script>
$(function () {
$("ul.pagination li.disabled a").click(function () {
return false;
});
$("#addForm").submit(function () {
if (!checkEmpty("student_id", "学号"))
return false;
if (!checkEmpty("name", "姓名"))
return false;
if (!checkEmpty("age", "年龄"))
return false;
return true;
});
});
function del() {
var msg = "您真的确定要删除吗?\n\n请确认!";
if (confirm(msg) == true) {
return true;
} else {
return false;
}
}
function checkEmpty(id, name) {
var value = $("#" + id).val();
if (value.length == 0) {
alert(name + "不能为空");
$("#" + id).focus();
return false;
}
return true;
}
</script>
</head>
<body>
<div class="listDIV">
<table class="table table-striped table-bordered table-hover table-condensed">
<caption>学生列表 - 共
<th:block th:text="${page.total}"/>
人
</caption>
<thead>
<tr class="success">
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>出生日期</th>
<th>编辑</th>
<th>删除</th>
</tr>
</thead>
<tbody>
<tr th:each="stu:${students}">
<td th:text="${stu.student_id}"></td>
<td>[[${stu.name}]]</td>
<td th:text="${stu.age}"></td>
<td th:text="${stu.sex}==0?'女':'男'"></td>
<td th:text="${#dates.format(stu.birthday, 'yyyy-MM-dd HH:mm')}"></td>
<td><a th:href="@{'/editStudent?id='+ ${stu.id}}"><span class="glyphicon glyphicon-edit"></span> </a>
</td>
<td><a th:href="@{'/deleteStudent?id='+${stu.id}}" onclick="javascript:return del();"><span
class="glyphicon glyphicon-trash"></span> </a></td>
</tr>
</tbody>
</table>
</div>
<div class="addDIV">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">增加学生</h3>
</div>
<div class="panel-body">
<form method="post" id="addForm" action="/addStudent" role="form">
<table class="addTable">
<tr>
<td>学号:</td>
<td><input type="text" name="student_id" id="student_id" placeholder="请在这里输入学号"></td>
</tr>
<tr>
<td>姓名:</td>
<td><input type="text" name="name" id="name" placeholder="请在这里输入名字"></td>
</tr>
<tr>
<td>年龄:</td>
<td><input type="text" name="age" id="age" placeholder="请在这里输入年龄"></td>
</tr>
<tr>
<td>性别:</td>
<td><input type="radio" checked class="radio radio-inline" name="sex" value="男"> 男
<input type="radio" class="radio radio-inline" name="sex" value="女"> 女
</td>
</tr>
<tr>
<td>出生日期:</td>
<td><input type="date" name="birthday" id="birthday" placeholder="请在这里输入出生日期"></td>
</tr>
<tr class="submitTR">
<td colspan="2" align="center">
<button type="submit" class="btn btn-success">提 交</button>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
</body>
</html>
editStudent.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<base th:href="${#request.getContextPath()}+''">
<script src="/script/js/jquery/2.0.0/jquery.min.js"></script>
<link href="/script/css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
<script src="/script/js/bootstrap/3.3.6/bootstrap.min.js"></script>
<link href="/script/css/style.css" rel="stylesheet">
<title>学生管理页面 - 编辑页面</title>
<script>
$(function () {
$("#editForm").submit(function () {
if (!checkEmpty("student_id", "学号"))
return false;
if (!checkEmpty("name", "姓名"))
return false;
if (!checkEmpty("age", "年龄"))
return false;
return true;
});
});
function checkEmpty(id, name) {
var value = $("#" + id).val();
if (value.length == 0) {
alert(name + "不能为空");
$("#" + id).focus();
return false;
}
return true;
}
</script>
</head>
<body>
<div class="editDIV">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">编辑学生</h3>
</div>
<div class="panel-body">
<form method="post" id="editForm" action="/updateStudent" role="form">
<table class="editTable">
<tr>
<td>学号:</td>
<td><input type="text" name="student_id" id="student_id" th:value="${student.student_id}"
placeholder="请在这里输入学号"></td>
</tr>
<tr>
<td>姓名:</td>
<td><input type="text" name="name" id="name" th:value="${student.name}" placeholder="请在这里输入名字">
</td>
</tr>
<tr>
<td>年龄:</td>
<td><input type="text" name="age" id="age" th:value="${student.age}" placeholder="请在这里输入年龄">
</td>
</tr>
<tr>
<td>性别:</td>
<td>
<input type="radio" class="radio radio-inline" name="sex" value="1" th:field="*{student.sex}" >男
<input type="radio" class="radio radio-inline" name="sex" value="0" th:field="*{student.sex}">女
</td>
</tr>
<tr>
<td>出生日期:</td>
<td><input type="date" name="birthday" id="birthday" th:value="${student.birthday}"
placeholder="请在这里输入出生日期"></td>
</tr>
<tr class="submitTR">
<td colspan="2" align="center">
<input type="hidden" name="id" th:value="${student.id}">
<button type="submit" class="btn btn-success">提 交</button>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
</body>
</html>
error.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>统一页面异常处理</title>
</head>
<body>
<h3 th:text="'发生错误:'+${message}"></h3>
</body>
</html>
Page
public class Page {
int start; // 开始数据
int count; // 每一页的数量
int total; // 总共的数据量
public Page(int start, int count) {
super();
this.start = start;
this.count = count;
}
public boolean isHasPreviouse() {
if (start == 0)
return false;
return true;
}
public boolean isHasNext() {
if (start == getLast())
return false;
return true;
}
public int getTotalPage() {
int totalPage;
// 假设总数是50,是能够被5整除的,那么就有10页
if (0 == total % count)
totalPage = total / count;
// 假设总数是51,不能够被5整除的,那么就有11页
else
totalPage = total / count + 1;
if (0 == totalPage)
totalPage = 1;
return totalPage;
}
public int getLast() {
int last;
// 假设总数是50,是能够被5整除的,那么最后一页的开始就是40
if (0 == total % count)
last = total - count;
// 假设总数是51,不能够被5整除的,那么最后一页的开始就是50
else
last = total - total % count;
last = last < 0 ? 0 : last;
return last;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
mybatis-config.xml 暂未
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>